Skip to content

Commit ea9a35b

Browse files
jcrduboisZahra-M-AghajanJohnGriffithsrob-lukelarsoner
authored
Feature/td nirs snirf (#13938)
Co-authored-by: Zahra M. Aghajan <zahraa.aghajani@gmail.com> Co-authored-by: John Griffiths <JohnGriffiths@users.noreply.github.com> Co-authored-by: Robert Luke <code@robertluke.net> Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
1 parent bd9ad62 commit ea9a35b

20 files changed

Lines changed: 587 additions & 179 deletions

File tree

.github/workflows/tests.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ jobs:
150150
- run: python ./tools/github_actions_check_old_env.py
151151
if: matrix.kind == 'old'
152152
# Minimal commands on Linux (macOS stalls)
153+
- uses: actions/cache@v5
154+
with:
155+
key: minimal-commands-0
156+
path: ~/minimal_cmds
157+
if: startswith(matrix.os, 'ubuntu') && matrix.kind != 'minimal' && matrix.kind != 'old'
153158
- run: bash ./tools/get_minimal_commands.sh
154159
if: startswith(matrix.os, 'ubuntu') && matrix.kind != 'minimal' && matrix.kind != 'old'
155160
- run: bash ./tools/github_actions_infos.sh

.mailmap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ Yousra Bekhti <yousra.bekhti@gmail.com> Yoursa BEKHTI <ybekhti@is222485.intra.ce
379379
Yousra Bekhti <yousra.bekhti@gmail.com> Yoursa BEKHTI <yousra.bekhti@gmail.com>
380380
Yousra Bekhti <yousra.bekhti@gmail.com> Yousra BEKHTI <yousra.bekhti@gmail.com>
381381
Yousra Bekhti <yousra.bekhti@gmail.com> yousrabk <yousra.bekhti@gmail.com>
382+
Zahra M. Aghajan <zahraa.aghajani@gmail.com> Zahra M. Aghajan <zahraa.aghajani@gmail.com>
382383
Zhi Zhang <850734033@qq.com> ZHANG Zhi <850734033@qq.com>
383384
Zhi Zhang <850734033@qq.com> ZHANG Zhi <zhi271.zhang@connect.polyu.hk>
384385
Ziyi ZENG <ziyizeng@link.cuhk.edu.cn> ZIYI ZENG <CME1909120@XMU.EDU.MY>

azure-pipelines.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ stages:
8989
./tools/setup_xvfb.sh
9090
sudo apt install -yq tcsh
9191
displayName: Install Ubuntu dependencies
92+
- task: Cache@2
93+
inputs:
94+
key: minimal-cmds-0
95+
path: /home/vsts/minimal_cmds
9296
- bash: ./tools/get_minimal_commands.sh
9397
displayName: Get minimal commands
9498
- bash: |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added basic support for TD fNIRS data, by :newcontrib:`Zahra Aghajan`, :newcontrib:`Julien Dubois`, :newcontrib:`John Griffiths`, `Robert Luke`_, and `Eric Larson`_.

doc/changes/names.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
.. _Johann Benerradi: https://github.com/HanBnrd
162162
.. _Johannes Herforth: https://herforth.net
163163
.. _Johannes Niediek: https://github.com/jniediek
164+
.. _John Griffiths: https://www.grifflab.com
164165
.. _John Samuelsson: https://github.com/johnsam7
165166
.. _John Veillette: https://psychology.uchicago.edu/directory/john-veillette
166167
.. _Jon Houck: https://www.mrn.org/people/jon-m.-houck/principal-investigators
@@ -174,6 +175,7 @@
174175
.. _Judy D Zhu: https://github.com/JD-Zhu
175176
.. _Juergen Dammers: https://github.com/jdammers
176177
.. _Jukka Nenonen: https://www.linkedin.com/pub/jukka-nenonen/28/b5a/684
178+
.. _Julien Dubois: https://github.com/jcrdubois
177179
.. _Jussi Nurminen: https://github.com/jjnurminen
178180
.. _Kaisu Lankinen: http://bishoplab.berkeley.edu/Kaisu.html
179181
.. _Kalle Makela: https://github.com/Kallemakela
@@ -376,6 +378,7 @@
376378
.. _Yixiao Shen: https://github.com/SYXiao2002
377379
.. _Yousra Bekhti: https://www.linkedin.com/pub/yousra-bekhti/56/886/421
378380
.. _Yu-Han Luo: https://github.com/yh-luo
381+
.. _Zahra Aghajan: https://github.com/Zahra-M-Aghajan
379382
.. _Zhi Zhang: https://github.com/tczhangzhi/
380383
.. _Ziyi ZENG: https://github.com/ZiyiTsang
381384
.. _Zvi Baratz: https://github.com/ZviBaratz

doc/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@
190190
),
191191
)
192192
)
193+
# Broken as of 2026/06/08 (https://github.com/joblib/joblib/issues/1796)
194+
intersphinx_mapping["joblib"] = ("https://joblib.readthedocs.io/en/stable", None)
193195

194196

195197
# NumPyDoc configuration -----------------------------------------------------

mne/_fiff/constants.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,7 @@
931931
FIFF.FIFF_UNIT_LM = 115 # lumen
932932
FIFF.FIFF_UNIT_LX = 116 # lux
933933
FIFF.FIFF_UNIT_V_M2 = 117 # V/m^2
934+
FIFF.FIFF_UNIT_SEC2 = 118 # second^2
934935
#
935936
# Others we need
936937
#
@@ -972,6 +973,7 @@
972973
FIFF.FIFF_UNIT_LM,
973974
FIFF.FIFF_UNIT_LX,
974975
FIFF.FIFF_UNIT_V_M2,
976+
FIFF.FIFF_UNIT_SEC2,
975977
FIFF.FIFF_UNIT_T_M,
976978
FIFF.FIFF_UNIT_AM,
977979
FIFF.FIFF_UNIT_AM_M2,
@@ -1044,7 +1046,9 @@
10441046
FIFF.FIFFV_COIL_FNIRS_FD_PHASE = 305 # fNIRS frequency domain phase
10451047
FIFF.FIFFV_COIL_FNIRS_RAW = FIFF.FIFFV_COIL_FNIRS_CW_AMPLITUDE # old alias
10461048
FIFF.FIFFV_COIL_FNIRS_TD_GATED_AMPLITUDE = 306 # fNIRS time-domain gated amplitude
1047-
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_AMPLITUDE = 307 # fNIRS time-domain moments amplitude
1049+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_INTENSITY = 307 # fNIRS time-domain moments intensity
1050+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_MEAN = 308 # fNIRS time-domain moments mean
1051+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_VARIANCE = 309 # fNIRS time-domain moments variance
10481052

10491053
FIFF.FIFFV_COIL_EYETRACK_POS = 400 # Eye-tracking gaze position
10501054
FIFF.FIFFV_COIL_EYETRACK_PUPIL = 401 # Eye-tracking pupil size
@@ -1145,7 +1149,9 @@
11451149
FIFF.FIFFV_COIL_FNIRS_FD_AC_AMPLITUDE,
11461150
FIFF.FIFFV_COIL_FNIRS_FD_PHASE,
11471151
FIFF.FIFFV_COIL_FNIRS_TD_GATED_AMPLITUDE,
1148-
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_AMPLITUDE,
1152+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_INTENSITY,
1153+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_MEAN,
1154+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_VARIANCE,
11491155
FIFF.FIFFV_COIL_MCG_42,
11501156
FIFF.FIFFV_COIL_EYETRACK_POS,
11511157
FIFF.FIFFV_COIL_EYETRACK_PUPIL,

mne/_fiff/meas_info.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ def set_montage(
450450
FIFF.FIFF_UNIT_NONE: "NA",
451451
FIFF.FIFF_UNIT_CEL: "C",
452452
FIFF.FIFF_UNIT_S: "S",
453+
FIFF.FIFF_UNIT_SEC: "s",
453454
FIFF.FIFF_UNIT_PX: "px",
454455
}
455456

mne/_fiff/pick.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,26 @@ def get_channel_type_constants(include_defaults=False):
104104
unit=FIFF.FIFF_UNIT_RAD,
105105
coil_type=FIFF.FIFFV_COIL_FNIRS_FD_PHASE,
106106
),
107+
fnirs_td_gated_amplitude=dict(
108+
kind=FIFF.FIFFV_FNIRS_CH,
109+
unit=FIFF.FIFF_UNIT_UNITLESS,
110+
coil_type=FIFF.FIFFV_COIL_FNIRS_TD_GATED_AMPLITUDE,
111+
),
112+
fnirs_td_moments_intensity=dict(
113+
kind=FIFF.FIFFV_FNIRS_CH,
114+
unit=FIFF.FIFF_UNIT_UNITLESS,
115+
coil_type=FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_INTENSITY,
116+
),
117+
fnirs_td_moments_mean=dict(
118+
kind=FIFF.FIFFV_FNIRS_CH,
119+
unit=FIFF.FIFF_UNIT_SEC,
120+
coil_type=FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_MEAN,
121+
),
122+
fnirs_td_moments_variance=dict(
123+
kind=FIFF.FIFFV_FNIRS_CH,
124+
unit=FIFF.FIFF_UNIT_SEC2,
125+
coil_type=FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_VARIANCE,
126+
),
107127
fnirs_od=dict(kind=FIFF.FIFFV_FNIRS_CH, coil_type=FIFF.FIFFV_COIL_FNIRS_OD),
108128
hbo=dict(
109129
kind=FIFF.FIFFV_FNIRS_CH,
@@ -197,6 +217,10 @@ def get_channel_type_constants(include_defaults=False):
197217
FIFF.FIFFV_COIL_FNIRS_FD_AC_AMPLITUDE: "fnirs_fd_ac_amplitude",
198218
FIFF.FIFFV_COIL_FNIRS_FD_PHASE: "fnirs_fd_phase",
199219
FIFF.FIFFV_COIL_FNIRS_OD: "fnirs_od",
220+
FIFF.FIFFV_COIL_FNIRS_TD_GATED_AMPLITUDE: "fnirs_td_gated_amplitude",
221+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_INTENSITY: "fnirs_td_moments_intensity",
222+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_MEAN: "fnirs_td_moments_mean",
223+
FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_VARIANCE: "fnirs_td_moments_variance",
200224
},
201225
),
202226
"eeg": (
@@ -385,6 +409,26 @@ def _triage_fnirs_pick(ch, fnirs, warned):
385409
return True
386410
elif ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_OD and "fnirs_od" in fnirs:
387411
return True
412+
elif (
413+
ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_TD_GATED_AMPLITUDE
414+
and "fnirs_td_gated_amplitude" in fnirs
415+
):
416+
return True
417+
elif (
418+
ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_INTENSITY
419+
and "fnirs_td_moments_intensity" in fnirs
420+
):
421+
return True
422+
elif (
423+
ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_MEAN
424+
and "fnirs_td_moments_mean" in fnirs
425+
):
426+
return True
427+
elif (
428+
ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_VARIANCE
429+
and "fnirs_td_moments_variance" in fnirs
430+
):
431+
return True
388432
return False
389433

390434

@@ -569,7 +613,7 @@ def pick_types(
569613
pick[k] = _triage_meg_pick(info["chs"][k], ref_meg)
570614
elif ch_type in ("eyegaze", "pupil"):
571615
pick[k] = _triage_eyetrack_pick(info["chs"][k], eyetrack)
572-
else: # ch_type in ('hbo', 'hbr')
616+
else: # ch_type in ('hbo', 'hbr', ...)
573617
pick[k] = _triage_fnirs_pick(info["chs"][k], fnirs, warned)
574618

575619
# restrict channels to selection if provided
@@ -867,6 +911,10 @@ def channel_indices_by_type(info, picks=None, *, exclude=()):
867911
fnirs_fd_ac_amplitude=list(),
868912
fnirs_fd_phase=list(),
869913
fnirs_od=list(),
914+
fnirs_td_gated_amplitude=list(),
915+
fnirs_td_moments_intensity=list(),
916+
fnirs_td_moments_mean=list(),
917+
fnirs_td_moments_variance=list(),
870918
eyegaze=list(),
871919
pupil=list(),
872920
)
@@ -1104,6 +1152,10 @@ def _check_excludes_includes(chs, info=None, allow_bads=False):
11041152
"fnirs_fd_ac_amplitude",
11051153
"fnirs_fd_phase",
11061154
"fnirs_od",
1155+
"fnirs_td_gated_amplitude",
1156+
"fnirs_td_moments_intensity",
1157+
"fnirs_td_moments_mean",
1158+
"fnirs_td_moments_variance",
11071159
)
11081160
_EYETRACK_CH_TYPES_SPLIT = ("eyegaze", "pupil")
11091161
_DATA_CH_TYPES_ORDER_DEFAULT = (

mne/_fiff/tests/test_constants.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@
2828

2929
# https://github.com/mne-tools/fiff-constants/commits/master
3030
REPO = "mne-tools"
31-
COMMIT = "e27f68cbf74dbfc5193ad429cc77900a59475181"
31+
COMMIT = "9ccb09d69daa8332f2e7252638ba397b60ba2502"
3232

3333
# These are oddities that we won't address:
3434
iod_dups = (355, 359) # these are in both MEGIN and MNE files
35-
tag_dups = (3501,) # in both MEGIN and MNE files
35+
tag_dups = ( # in both MEGIN and MNE files
36+
3501, # FIFF.FIFF_XPLOTTER_LAYOUT
37+
3507, # FIFF.FIFF_MNE_CH_NAME_LIST
38+
)
3639

3740
_dir_ignore_names = (
3841
"clear",
@@ -91,7 +94,9 @@
9194
304, # fNIRS frequency domain AC amplitude
9295
305, # fNIRS frequency domain phase
9396
306, # fNIRS time domain gated amplitude
94-
307, # fNIRS time domain moments amplitude
97+
307, # fNIRS time domain moments intensity
98+
308, # fNIRS time domain moments mean
99+
309, # fNIRS time domain moments variance
95100
400, # Eye-tracking gaze position
96101
401, # Eye-tracking pupil size
97102
1000, # For testing the MCG software

0 commit comments

Comments
 (0)