NeuroAnalyzer tutorials: NIRS
Load NIRS data:
using NeuroAnalyzer
n = import_nirs("files/fnirs.nirs");
info(n)
[ Info: Imported: NIRS (12 × 9015 × 1; 359.98 s)
Data type: NIRS
File format: NIRS
Source file: files/fnirs.nirs
File size [MB]: 0.72
Memory size [MB]: 0.9
Subject:
Recording:
Recording notes:
Recording date:
Recording time:
Sampling rate (Hz): 25
Signal length [samples]: 9015
Signal length [seconds]: 360.6
Number of channels: 12
Epochs ID:
Number of epochs: 1
Epoch length [samples]: 9015
Epoch length [seconds]: 360.6
Wavelength [nm]: [690.0, 830.0]
Markers: no
Channel locations: yes
Components: no
Number of NIRS channels: 12
Channels:
ch label type unit wavelength
------ --------------- ----------- ------- ------------
1 S1_D1 690 NIRS_INT V 690.0
2 S1_D2 690 NIRS_INT V 690.0
3 S1_D1 830 NIRS_INT V 830.0
4 S1_D2 830 NIRS_INT V 830.0
5 AUX1 NIRS_AUX
6 AUX2 NIRS_AUX
7 AUX3 NIRS_AUX
8 AUX4 NIRS_AUX
9 AUX5 NIRS_AUX
10 AUX6 NIRS_AUX
11 AUX7 NIRS_AUX
12 AUX8 NIRS_AUX
Load SNIRF data:
n = import_snirf("files/fnirs.snirf");
info(n)
[ Info: Imported: NIRS (72 × 500 × 1; 9.98 s)
Data type: NIRS
File format: SNIRF
Source file: files/fnirs.snirf
File size [MB]: 1.91
Memory size [MB]: 0.29
Subject: default:
Recording:
Recording notes:
Recording date: 2022-03-03
Recording time: 12:03:48
Sampling rate (Hz): 50
Signal length [samples]: 500
Signal length [seconds]: 10.0
Number of channels: 72
Epochs ID:
Number of epochs: 1
Epoch length [samples]: 500
Epoch length [seconds]: 10.0
Wavelength [nm]: [760.0, 850.0]
Markers: yes
Channel locations: yes
Components: no
Number of NIRS channels: 72
Channels:
ch label type unit wavelength
------ --------------- ----------- ------- ------------
1 S2_D1 760 NIRS_OD V 760.0
2 S4_D1 760 NIRS_OD V 760.0
3 S1_D1 760 NIRS_OD V 760.0
4 S4_D2 760 NIRS_OD V 760.0
5 S6_D2 760 NIRS_OD V 760.0
6 S3_D2 760 NIRS_OD V 760.0
7 S2_D3 760 NIRS_OD V 760.0
8 S4_D3 760 NIRS_OD V 760.0
9 S7_D3 760 NIRS_OD V 760.0
10 S5_D3 760 NIRS_OD V 760.0
11 S4_D4 760 NIRS_OD V 760.0
12 S6_D4 760 NIRS_OD V 760.0
13 S7_D4 760 NIRS_OD V 760.0
14 S8_D4 760 NIRS_OD V 760.0
15 S10_D5 760 NIRS_OD V 760.0
16 S9_D5 760 NIRS_OD V 760.0
17 S12_D6 760 NIRS_OD V 760.0
18 S14_D6 760 NIRS_OD V 760.0
19 S11_D6 760 NIRS_OD V 760.0
20 S10_D7 760 NIRS_OD V 760.0
21 S15_D7 760 NIRS_OD V 760.0
22 S13_D7 760 NIRS_OD V 760.0
23 S12_D8 760 NIRS_OD V 760.0
24 S14_D8 760 NIRS_OD V 760.0
25 S16_D8 760 NIRS_OD V 760.0
26 S17_D9 760 NIRS_OD V 760.0
27 S18_D9 760 NIRS_OD V 760.0
28 S21_D9 760 NIRS_OD V 760.0
29 S17_D10 760 NIRS_OD V 760.0
30 S18_D10 760 NIRS_OD V 760.0
31 S23_D10 760 NIRS_OD V 760.0
32 S19_D11 760 NIRS_OD V 760.0
33 S22_D11 760 NIRS_OD V 760.0
34 S19_D12 760 NIRS_OD V 760.0
35 S20_D12 760 NIRS_OD V 760.0
36 S24_D12 760 NIRS_OD V 760.0
37 S2_D1 850 NIRS_OD V 850.0
38 S4_D1 850 NIRS_OD V 850.0
39 S1_D1 850 NIRS_OD V 850.0
40 S4_D2 850 NIRS_OD V 850.0
41 S6_D2 850 NIRS_OD V 850.0
42 S3_D2 850 NIRS_OD V 850.0
43 S2_D3 850 NIRS_OD V 850.0
44 S4_D3 850 NIRS_OD V 850.0
45 S7_D3 850 NIRS_OD V 850.0
46 S5_D3 850 NIRS_OD V 850.0
47 S4_D4 850 NIRS_OD V 850.0
48 S6_D4 850 NIRS_OD V 850.0
49 S7_D4 850 NIRS_OD V 850.0
50 S8_D4 850 NIRS_OD V 850.0
51 S10_D5 850 NIRS_OD V 850.0
52 S9_D5 850 NIRS_OD V 850.0
53 S12_D6 850 NIRS_OD V 850.0
54 S14_D6 850 NIRS_OD V 850.0
55 S11_D6 850 NIRS_OD V 850.0
56 S10_D7 850 NIRS_OD V 850.0
57 S15_D7 850 NIRS_OD V 850.0
58 S13_D7 850 NIRS_OD V 850.0
59 S12_D8 850 NIRS_OD V 850.0
60 S14_D8 850 NIRS_OD V 850.0
61 S16_D8 850 NIRS_OD V 850.0
62 S17_D9 850 NIRS_OD V 850.0
63 S18_D9 850 NIRS_OD V 850.0
64 S21_D9 850 NIRS_OD V 850.0
65 S17_D10 850 NIRS_OD V 850.0
66 S18_D10 850 NIRS_OD V 850.0
67 S23_D10 850 NIRS_OD V 850.0
68 S19_D11 850 NIRS_OD V 850.0
69 S22_D11 850 NIRS_OD V 850.0
70 S19_D12 850 NIRS_OD V 850.0
71 S20_D12 850 NIRS_OD V 850.0
72 S24_D12 850 NIRS_OD V 850.0
View optode locations:
plot_locs(n, ch="all", src_labels=false, det_labels=false, opt_labels=false, head=false)
(!) Red (or black in monochrome mode) optodes represent sources, green (white) optodes are detectors.
Get wavelengths:
n.header.recording[:wavelengths]
2-element Vector{Float64}:
760.0
850.0
Get channel of 760 or 850 nm wavelength:
ch760 = get_channel(n, ch=get_channel(n, wl=760))
ch850 = get_channel(n, ch=get_channel(n, wl=850))
36-element Vector{Int64}:
37
38
39
40
41
42
43
44
45
46
47
48
49
⋮
61
62
63
64
65
66
67
68
69
70
71
72
Get data associated with these channels:
d760 = n.data[ch760, :, :]
d850 = n.data[ch850, :, :]
36×500×1 Array{Float64, 3}:
[:, :, 1] =
4.81625 1.2555 1.25525 1.25525 … 1.2635 1.2635 1.26375 1.264
4.81625 1.105 1.105 1.10475 1.0925 1.092 1.0915 1.09125
4.81625 1.4645 1.46425 1.46425 1.47075 1.47075 1.471 1.47125
4.81625 1.8875 1.887 1.887 1.8895 1.89 1.89 1.8905
4.81625 0.9755 0.97525 0.975 0.9775 0.97725 0.97725 0.97725
4.81625 1.046 1.046 1.04575 … 1.03925 1.039 1.03875 1.039
4.81625 1.1375 1.1375 1.1375 1.12875 1.12875 1.1285 1.1285
4.81625 1.936 1.9355 1.9355 1.9345 1.9345 1.9345 1.935
4.81625 1.25925 1.25925 1.259 1.2435 1.2435 1.24325 1.24325
4.81625 1.23375 1.2335 1.23325 1.22525 1.22475 1.2245 1.2245
4.81625 0.93625 0.936 0.93575 … 0.9195 0.91875 0.91825 0.91775
4.81625 1.50075 1.5005 1.50025 1.50175 1.50175 1.50175 1.50175
4.81625 2.0225 2.0225 2.02175 2.00475 2.004 2.00475 2.00475
⋮ ⋱
4.81625 0.98325 0.983 0.983 0.967 0.967 0.967 0.967
4.81625 0.9285 0.928 0.92725 … 0.8855 0.88525 0.88475 0.88425
4.81625 0.452 0.4515 0.45075 0.43725 0.43675 0.43625 0.43575
4.81625 0.27875 0.27875 0.27875 0.27525 0.275 0.27475 0.27475
4.81625 0.84575 0.845 0.84425 0.7775 0.77725 0.77725 0.777
4.81625 0.66325 0.66275 0.66225 0.64425 0.64375 0.64325 0.643
4.81625 1.2735 1.2735 1.27325 … 1.2655 1.2655 1.2655 1.26525
4.81625 1.16825 1.168 1.168 1.12325 1.123 1.1225 1.122
4.81625 1.14825 1.14825 1.14825 1.13725 1.137 1.13675 1.13625
4.81625 1.247 1.24675 1.2465 1.207 1.2065 1.206 1.2055
4.81625 1.15625 1.156 1.15575 1.11625 1.11575 1.11525 1.1145
4.81625 1.63575 1.63575 1.63525 … 1.625 1.6245 1.62425 1.62375
Convert RAW intensity to OD (optical density):
n = import_nirs("files/fnirs.nirs");
info(n)
[ Info: Imported: NIRS (12 × 9015 × 1; 359.98 s)
Data type: NIRS
File format: NIRS
Source file: files/fnirs.nirs
File size [MB]: 0.72
Memory size [MB]: 0.9
Subject:
Recording:
Recording notes:
Recording date:
Recording time:
Sampling rate (Hz): 25
Signal length [samples]: 9015
Signal length [seconds]: 360.6
Number of channels: 12
Epochs ID:
Number of epochs: 1
Epoch length [samples]: 9015
Epoch length [seconds]: 360.6
Wavelength [nm]: [690.0, 830.0]
Markers: no
Channel locations: yes
Components: no
Number of NIRS channels: 12
Channels:
ch label type unit wavelength
------ --------------- ----------- ------- ------------
1 S1_D1 690 NIRS_INT V 690.0
2 S1_D2 690 NIRS_INT V 690.0
3 S1_D1 830 NIRS_INT V 830.0
4 S1_D2 830 NIRS_INT V 830.0
5 AUX1 NIRS_AUX
6 AUX2 NIRS_AUX
7 AUX3 NIRS_AUX
8 AUX4 NIRS_AUX
9 AUX5 NIRS_AUX
10 AUX6 NIRS_AUX
11 AUX7 NIRS_AUX
12 AUX8 NIRS_AUX
Data type: NIRS
File format: NIRS
Source file: files/fnirs.nirs
File size [MB]: 0.72
Memory size [MB]: 1.18
Subject:
Recording:
Recording notes:
Recording date:
Recording time:
Sampling rate (Hz): 25
Signal length [samples]: 9015
Signal length [seconds]: 360.6
Number of channels: 16
Epochs ID:
Number of epochs: 1
Epoch length [samples]: 9015
Epoch length [seconds]: 360.6
Wavelength [nm]: [690.0, 830.0]
Markers: no
Channel locations: yes
Components: no
Number of NIRS channels: 16
Channels:
ch label type unit wavelength
------ --------------- ----------- ------- ------------
1 S1_D1 690 NIRS_INT V 690.0
2 S1_D2 690 NIRS_INT V 690.0
3 S1_D1 830 NIRS_INT V 830.0
4 S1_D2 830 NIRS_INT V 830.0
5 S1_D1 690 OD NIRS_OD V 690.0
6 S1_D2 690 OD NIRS_OD V 690.0
7 S1_D1 830 OD NIRS_OD V 830.0
8 S1_D2 830 OD NIRS_OD V 830.0
9 AUX1 NIRS_AUX
10 AUX2 NIRS_AUX
11 AUX3 NIRS_AUX
12 AUX4 NIRS_AUX
13 AUX5 NIRS_AUX
14 AUX6 NIRS_AUX
15 AUX7 NIRS_AUX
16 AUX8 NIRS_AUX
(!) OD channels will be added to the object as nirs_od
channel type. OD channels will be placed after RAW (intensity channels) and before other channels.
Convert OD (optical density) to hemoglobin concentration:
Data type: NIRS
File format: NIRS
Source file: files/fnirs.nirs
File size [MB]: 0.72
Memory size [MB]: 1.59
Subject:
Recording:
Recording notes:
Recording date:
Recording time:
Sampling rate (Hz): 25
Signal length [samples]: 9015
Signal length [seconds]: 360.6
Number of channels: 22
Epochs ID:
Number of epochs: 1
Epoch length [samples]: 9015
Epoch length [seconds]: 360.6
Wavelength [nm]: [690.0, 830.0]
Markers: no
Channel locations: yes
Components: no
Number of NIRS channels: 22
Channels:
ch label type unit wavelength
------ --------------- ----------- ------- ------------
1 S1_D1 690 NIRS_INT V 690.0
2 S1_D2 690 NIRS_INT V 690.0
3 S1_D1 830 NIRS_INT V 830.0
4 S1_D2 830 NIRS_INT V 830.0
5 S1_D1 690 OD NIRS_OD V 690.0
6 S1_D2 690 OD NIRS_OD V 690.0
7 S1_D1 830 OD NIRS_OD V 830.0
8 S1_D2 830 OD NIRS_OD V 830.0
9 AUX1 NIRS_AUX
10 AUX2 NIRS_AUX
11 AUX3 NIRS_AUX
12 AUX4 NIRS_AUX
13 AUX5 NIRS_AUX
14 AUX6 NIRS_AUX
15 AUX7 NIRS_AUX
16 AUX8 NIRS_AUX
17 S1_D1 HbO NIRS_HBO
18 S1_D1 HbR NIRS_HBR
19 S1_D1 HbT NIRS_HBT
20 S1_D2 HbO NIRS_HBO
21 S1_D2 HbR NIRS_HBR
22 S1_D2 HbT NIRS_HBT
(!) For each channel three channels will be added: nirs_hbo
(oxygenated hemoglobin), nirs_hbr
(deoxgenated hemoglobin) and nirs_hbt
(total hemoglobin). The sequence of added channels is: ch1 HbO, ch1 HbR, ch1 HbT, ch2 HbO, ch2 HbR, ch2 HbT etc.
(!) It is recommended to run a band-pass filter prior to calculating Hb concentration:
n = import_nirs("files/fnirs.nirs");
intensity2od!(n)
[ Info: Imported: NIRS (12 × 9015 × 1; 359.98 s)
OD of channel 1:
9015×1 Matrix{Float64}:
-0.0005150299141518043
0.0010209688274578903
-0.002445900500786136
-0.0052140011428542495
-0.008772120789647224
-0.010092098928011477
-0.008707687021497932
-0.006070397302632848
-0.004462030215970816
-0.006320714237476389
-0.009778359554364867
-0.012116968545753415
-0.011169325736148709
⋮
0.022383449987165117
0.023243333582738144
0.026777728371919527
0.027705172813399886
0.0284731365000764
0.02903944991903703
0.02833334151231847
0.03368347704639658
0.04037981487859521
0.04240412723556646
0.044218836966165624
0.042366900503228146
NeuroAnalyzer.filter!(n, ch="all", fprototype=:fir, ftype=:bp, cutoff=(0.01, 10))
od2conc!(n)
[ Info: Signal should be tapered prior to filtering to reduce edge artifacts
[ Info: Creating BP filter:
[ Info: Using default window: hamming(2)
[ Info: Attenuation: 16 dB
[ Info: Transition bandwidth: 0.4156 Hz
[ Info: F1_stop: -0.1898 Hz
[ Info: F1_pass: 0.01 Hz
[ Info: Cutoff frequency: -0.1978 Hz
[ Info: F2_pass: 10 Hz
[ Info: F2_stop: 10.1998 Hz
[ Info: Cutoff frequency: 10.2078 Hz
HbO, HbR, HbT of channel 1:
labels(n)[17:22]
n.header.recording[:channel_type][17:22]
ch1_od = n.data[17:22, :, :]
6×9015×1 Array{Float64, 3}:
[:, :, 1] =
-132.676 -132.397 -136.272 -141.853 … 129.526 132.831 135.192
25.2166 26.7194 23.9568 22.2336 17.8564 19.0548 16.7195
-107.46 -105.678 -112.315 -119.62 147.382 151.885 151.911
40.7612 35.1063 36.4021 26.8672 91.334 91.2172 85.1749
124.74 127.68 123.276 121.35 -14.277 -12.6902 -15.7291
165.502 162.786 159.678 148.217 … 77.0569 78.527 69.4458
Plot channels:
NeuroAnalyzer.plot(n, ch="all")
Plot Hb concentrations:
p1 = NeuroAnalyzer.plot(n, ch=["S1_D1 HbO", "S1_D2 HbO"], type=:butterfly, seg=(0, 30), title="HbO", ylabel="HbO [μM/mm]", xlabel="")
p2 = NeuroAnalyzer.plot(n, ch=["S1_D1 HbR", "S1_D2 HbR"], type=:butterfly, seg=(0, 30), title="HbR", ylabel="HbR [μM/mm]", xlabel="")
p3 = NeuroAnalyzer.plot(n, ch=["S1_D1 HbT", "S1_D2 HbT"], type=:butterfly, seg=(0, 30), title="HbT", ylabel="HbT [μM/mm]")
Plots.plot(p1, p2, p3, layout=(3,1), legend=:outertopright)