Home > matlab, nirs > NIRS data analysis (GLM and visualization)

NIRS data analysis (GLM and visualization)

June 12th, 2009

[last updated: 2019/02/01]

Also check out NIRS data analysis (time series)

Environment requirement

  1. MatLab
  2. SPM 5 or 8
  3. xjView 8
    xjview can be downloaded for free from http://www.alivelearn.net/xjview/
    (If you are inside CIBSR, xjview  is located in /fs/fmrihome/fMRItools/Xjview)
    Add xjview to path by addpath(genpath('/fs/fmrihome/fMRItools/Xjview'))
  4. nirs2img function in this article can be obtained in the page http://www.alivelearn.net/?p=1574. It is located in the nirs folder.
  5. NFRI toolbox [Link updated on 2013/08/13] (for standard brain registration)
    Download from http://www.jichi.ac.jp/brainlab/tools.html and save it in a directory whose name contains no space (e.g. not in something like c:\program files\…).


  1. convert NIRS data file to csv format using ETG4000 program.
  2. copy the 3D positioning data (00X.pos). If you didn’t measure 3D positioning data, jump to step 5
  3. use NFRI toolbox (Pepe Dan, Japan. http://www.jichi.ac.jp/brainlab/tools.html) to get the MNI coordinates of each probe.  Detailed information on how to use this toolbox can be found in its manual. [Update 2015-07-13. A video tutorial: http://www.alivelearn.net/?p=1726]
    1. Convert 00?.pos file to csv file using
    2. Convert the 3D positioning data into MNI space coordinate using
    3. You will get a xls file containing the positions. There are several sheets in that file and you should use the sheet called “WShatC”, which contains the positions of cortical surface.
  4. Find channel positions based on probe positions using probe2channel.m
    probe2channel(probe, config)
  5. If you don’t have 3D positioning data, you may use the template channel positions located in
    load xjview/nirs_data_sample/templateMNI.mat
    . (Please note, this file was created by Xu based on a single subject’s data. It’s useful for quick data review but it will be inaccurate to your own subjects. So you should create your own file in formal analysis. [update 2019-02-01])
    You will find 6 variables in MatLab workspace. They are channelMNI3x11  channelMNI3x5   channelMNI4x4   probeMNI3x11    probeMNI3x5     probeMNI4x4. They are all Nx3 matrix.

Read data and do GLM

  1. use readHitachData.m to read the data file (csv format). Type help readHitachData to see how to use it. Note if your input is two files (for 4×4 and 3×5 configurations), this script will automatically concatenate the data.
    [hbo,hbr,mark] = readHitachData({’XC_tap_MES_Probe1.csv’,'XC_tap_MES_Probe2.csv’});
  2. Prepare event onset timing, duration etc from the mark data, or external data you have, for later GLM analysis (step 3). The format is:
    • onset: onset timing of every event. a cell array. Each element is a numeric vector for one event type. Unit: second
    • duration: duration of every event. same with onset, except the meaning of numbers are duration. If the event is punctuated event, use 0 as duration. Unit: second
    • modulation (optional): modulation of event. For the same type of event you may have different intensities. For example, your event is flash of 5 levels of intensities. You can use modulation to modulate the intensity.  Format is exactly same with onset.
  3. GLM analysis using glm. Type help glm for more info.
    [beta, T, pvalue] = glm(hbdata, onset, duration, modulation);
  4. You may want to save the data for future use.
  5. (if you want to view the result in a standard brain) Convert the values (T or beta or contrasts) to an image file by nirs2img. Try help nirs2img to get more information.
    nirs2img(imgFileName, mni, value, doInterp, doXjview)


  1. plotTopoMap will plot data on a plane. The data can be T or beta or other values. Type help plotTopoMap for more info. Here is an example (note the data is smoothed by spline):
    plotTopoMap(randn(24,1), '4x4');
  2. nirs2img will convert your data to an image file which can be visuzlied by many fMRI functional image programs (such as xjview). Here is an example of visualizing the image by xjview. Note, after xjview window launches, you need to check “render view”, and then you may choose between new or old style.
    nirs2img('nirs_test.img', mni, value, 1, 1);
  3. You can also visualize the result with NFRI’s nfri_mni_plot (in NFRI toolbox). You need to prepare the the plot data in excel format beforehand. More information can be found in Readme.doc in NFRI toolbox.

Group analysis

  1. For each individual subject, perform GLM and save the beta values for each condition and subject.
  2. Do contrast  on each subject. Contrasts are simply difference of beta values. For example, contrast between 1st condition and 2nd condition is simply c = beta(:,1) - beta(:,2); Then save the contrast in an image file using nirs2img for each subject. You get a bunch of contrast images (one for each subject)
  3. Perform T test on the contrast images using onesampleT.m, or you can use SPM to do one sample T test if you prefer. You will get a T test image file.
  4. Visualize the T test image with xjview (or SPM)
Author: Xu Cui Categories: matlab, nirs Tags:
Try Stork, a research tool we developed

Stork is a publication alert app developed by us at Stanford. As a researcher we often forget to follow up important publications - and it's practically impossible to search many keywords or researchers' names everyday. Stork can help us to search everyday and notifies us when there are new publications/grants. How Stork helped me?

About the author:

Xu Cui is a human brain research scientist in Stanford University. He lives in the Bay Area in the United States. He is also the founder of Stork (smart publication alert app), PaperBox and BizGenius.


He was born in He'nan province, China. He received education in Beijing University(BS), University of Tennessee (Knoxville) (MS), Baylor College of Medicine (PhD) and Stanford University (PostDoc). Read more ...
  1. lee
    August 31st, 2009 at 18:26 | #1

    Dear Xu,

    I have been reading your writing on NIRS_SPM for a while. Thank you for contributing :)

    Just a short qns: do you know if there is any Help Forum on NIRS-SPM? I have been trying to use the program but I encountered some annoying errors which I couldnt solve.

    Hope you may point me to the right direction. Thanks in advance!

    - Lee from Singapore

  2. Sabin
    February 22nd, 2010 at 09:40 | #2

    Hi Xu,
    I have been following your writings on NIRS_SPM. Your contribution have been a great help for me.
    I have been trying to learn this NIRS_SPM, but it keeps on giving me error. Is there any other material that I can use to learn NIRS_SPM apart from its user manual OR is there any help forum for NIRS_SPM.
    Hope to get help from you.
    Thanks in advance.

  3. February 22nd, 2010 at 09:49 | #3

    I haven’t been using NIRS_SPM for a while. I don’t know if there is any other resources but I do know the authors are very helpful. You might want to contact them directly.

  4. Lin
    March 9th, 2010 at 02:01 | #4

    Why can’t find this three function code (glm.m, nirs2img.m, onesampleT.m) in environment requirement your suggestion?

  5. Leanne Hirshfield
    August 3rd, 2011 at 13:26 | #5

    Hi Xu,
    I just downloaded the code described in this section and want to play around with an ETG dataset that I did not create position data for. I’m trying to find the template position files that are referenced in:

    “If you don’t have 3D positioning data, you may use the template channel positions located in
    load xjview/nirs_data_sample/templateMNI.mat”

    But I’m having trouble. I don’t have a folder called xjview, just the xjview.m. I can’t seem to find templateMNI.mat. This may be just an issue I’m having w/ matlab, as I haven’t worked with .mat files before. I’ve only worked with .m files. Can you be more specific about how to find these template datafiles? Thanks–I’m really excited to play around with the code you have posted here:)!!

  6. August 3rd, 2011 at 14:55 | #6

    @Leanne Hirshfield
    That file is not in the public package of xjview.
    An email has been sent to you.

  7. November 17th, 2011 at 06:48 | #7

    Dear Cui,
    Could you send me templateMNI.mat, I am using ETG4000, is this file appropriate for the 3×11 configurations? Thank you!

  8. Gang Xu
    February 17th, 2013 at 06:16 | #8

    Can you send me a copy of this three files? glm.m, nirs2img.m, and onesampleT.m. Thank you very much.

  9. Amy
    August 11th, 2015 at 20:25 | #9

    Hi Xu,
    Could you please also send me the copy of those three files? glm.m, nirs2img.m, and onesampleT.m. Thank you a lot!

  10. August 12th, 2015 at 16:26 | #10

    They are in xjview full version:

  11. vera
    August 18th, 2015 at 13:50 | #11

    Dear Prof Xu,
    Could you please also send me the copy of those three files

  12. August 18th, 2015 at 21:11 | #12

    They are in xjview full version:

  13. LiXia Wang
    September 14th, 2016 at 05:48 | #13

    We used “readHitachData”to read files from two probes, but an error appeared:
    “Undefined function or variable “timeindex”.
    Error in loadHitachiText (line 42)
    data(:, timeindex) = timedata;
    Error in readHitachData (line 48)
    [data, variablename] = loadHitachiText(filenames{fileindex});

    Our data have a “Time” column. Could you tell me what are the possibe reasons?

  14. September 14th, 2016 at 12:36 | #14

    @LiXia Wang
    Is your data from Hitachi ETG4000?

  15. Yinying Hu
    December 7th, 2016 at 23:30 | #15

    @LiXia Wang

    Hello, I have this problem, too. The data was collected by ETG-7100. Did you fix it? What’s wrong with this data?

  16. farzan
    April 18th, 2017 at 23:25 | #16

    Dear Prof Xu

    could you help me?
    i have some datas for nirs. i want to read these datas and use wavelet for processing. i want to know do you have any book or paper that help me how to read data in matlab and use wavelet.

    Thank you a lot!

  17. Yanchun Zheng
    August 4th, 2017 at 08:24 | #17

    Dear Prof Xu,
    Thank you sooo much for sharing this Visualization tool of fNIRS.
    But I have a problem about the input parameter of nirs2img.
    In the 5th step of “Read data and do GLM” process,”(if you want to view the result in a standard brain) Convert the values (T or beta or contrasts) to an image file by nirs2img(imgFileName, mni, value, doInterp, doXjview)”, I don’t know why can beta or contrasts can work and get the P value in xjview. Because NIRS_SPM just use the T to get the P value. Could you please help me understand why beta and contrasts can work?

    Thank you so much!!

  18. August 4th, 2017 at 09:54 | #18

    @Yanchun Zheng
    Yanchun, nirs2img is to convert your data (whatever it is) to an image file which can be opened by xjview. It’s does not convert to p-value. In xjview, you can view the image (beta, T, contrast etc). If it’s beta or contrast, then p-value in xjview is meaningless.

  19. Yanchun Zheng
    August 4th, 2017 at 17:14 | #19

    Get it! Thank you very much.

  20. Avi
    November 6th, 2017 at 04:47 | #20

    Hi I am at the GLM stage and cannot continue because of this erro that I am getting:

    [beta, T, pvalue, covb] = glm(hbo, {onset}, {duration});
    Undefined function ‘max’ for input arguments of type ‘cell’.

    Can you please help me?


  21. Hao Deng
    July 4th, 2018 at 02:40 | #21

    See source code of glm in line 84~ 86, this is where the function ‘max’ appears. You may set a stop point there to see what’s going on there.

  22. Hao Deng
    July 4th, 2018 at 02:47 | #22

    Dear Prof. Cui
    I have a question concerning following step:
    “GLM analysis using glm. Type help glm for more info.[beta, T, pvalue] = glm(hbdata, onset, duration, modulation)”. Shouldn’t we correct the serial correlation for Hb data before we estimate the beta coefficient? Hb data usually shows strong serial correlation after low pass filtering,also considering its relative high sampling rate compared to fMRI.

  23. July 5th, 2018 at 17:59 | #23

    @Hao Deng
    We have not done this step (correct for serial correlation) in the past …

  24. Hao Deng
    July 9th, 2018 at 03:11 | #24

    @Xu Cui
    Got it. Thanks for your reply.

  25. Jiaxin Yang
    December 17th, 2018 at 18:20 | #25

    For the nirs2img.funciton. I have a question about “value” in the function.[nirs2img(imgFileName, mni, value, doInterp, doXjview, bilateral) ]
    The Note said “value: Nx1 matrix, each row is the value corresponding to mni” , But it sill confunse me a lot.

    The value is related with girddata function ? I have try it several time, but still fail…

    How should I define this parameter?

  26. December 17th, 2018 at 19:01 | #26

    @Jiaxin Yang
    the ‘mni’ parameter is Nx3 (N points, each point 3D), and value is Nx1 (N points). To start, you can simply use ones as the value. ones(N,1)

  27. Jiaxin Yang
    December 17th, 2018 at 19:17 | #27

    Thanks, I got it !! I could also define these value using the t-value or F-value, right? Thanks again for your help.