57
57
)
58
58
59
59
# Kernel
60
- kernel_path = testing_path / "SNIRF" / "Kernel" / "Flow50" / "Portal_2021_11"
61
- kernel_hb = kernel_path / "hb.snirf"
62
- kernel_td = kernel_path / "td_moments.snirf"
60
+ kernel_flow1_path = testing_path / "SNIRF" / "Kernel" / "Flow50" / "Portal_2021_11"
61
+ kernel_hb_old = kernel_flow1_path / "hb.snirf"
62
+ kernel_td_moments_old = kernel_flow1_path / "td_moments.snirf"
63
+ kernel_flow2_path = testing_path / "SNIRF" / "Kernel" / "Flow2" / "Portal_2024_10_23"
64
+ kernel_td_gated = kernel_flow2_path / "c345d04_2.snirf" # Type 201 (TD Gated, 201)
65
+ kernel_td_moments = kernel_flow2_path / "c345d04_3.snirf" # Type 202 (TD Moments, 301)
66
+ kernel_hb = kernel_flow2_path / "c345d04_5.snirf" # Type 203 (Hb, 99999)
67
+
63
68
64
69
h5py = pytest .importorskip ("h5py" ) # module-level
65
70
@@ -87,8 +92,13 @@ def _get_loc(raw, ch_name):
87
92
nirx_nirsport2_103 ,
88
93
nirx_nirsport2_103_2 ,
89
94
nirx_nirsport2_103_2 ,
90
- kernel_hb ,
91
- kernel_td ,
95
+ pytest .param (kernel_hb_old , id = f"kernel: { kernel_hb_old .stem } " ),
96
+ pytest .param (
97
+ kernel_td_moments_old , id = f"kernel: { kernel_td_moments_old .stem } "
98
+ ),
99
+ pytest .param (kernel_td_gated , id = f"kernel: { kernel_td_gated .stem } " ),
100
+ pytest .param (kernel_td_moments , id = f"kernel: { kernel_td_moments .stem } " ),
101
+ pytest .param (kernel_hb , id = f"kernel: { kernel_hb .stem } " ),
92
102
lumo110 ,
93
103
]
94
104
),
@@ -97,15 +107,26 @@ def test_basic_reading_and_min_process(fname):
97
107
"""Test reading SNIRF files and minimum typical processing."""
98
108
raw = read_raw_snirf (fname , preload = True )
99
109
# SNIRF data can contain several types, so only apply appropriate functions
110
+ kinds = [
111
+ "fnirs_cw_amplitude" ,
112
+ "fnirs_od" ,
113
+ "fnirs_td_gated_amplitude" ,
114
+ "fnirs_td_moments_intensity" ,
115
+ "hbo" ,
116
+ # TODO: add fd_*
117
+ ]
118
+ ch_types = raw .get_channel_types (unique = True )
119
+ got_kinds = [kind for kind in kinds if kind in raw ]
120
+ assert len (got_kinds ) == 1 , f"Need one data type, { got_kinds = } and { ch_types = } "
100
121
if "fnirs_cw_amplitude" in raw :
101
122
raw = optical_density (raw )
102
- if "fnirs_od" in raw :
123
+ elif "fnirs_od" in raw :
103
124
raw = beer_lambert_law (raw , ppf = 6 )
104
- if "fnirs_td_moments_intensity" in raw :
105
- # TODO: Re-enable once types are triaged
106
- # assert "fnirs_td_moments_mean" in raw
107
- # assert "fnirs_td_moments_variance" in raw
125
+ elif "fnirs_td_gated_amplitude" in raw :
108
126
pass
127
+ elif "fnirs_td_moments_intensity" in raw :
128
+ assert "fnirs_td_moments_mean" in raw
129
+ assert "fnirs_td_moments_variance" in raw
109
130
else :
110
131
assert "hbo" in raw
111
132
assert "hbr" in raw
@@ -422,40 +443,80 @@ def test_snirf_fieldtrip_od():
422
443
423
444
424
445
@requires_testing_data
425
- @pytest .mark .parametrize ("kind" , ("hb" , "td" ))
426
- def test_snirf_kernel (kind ):
446
+ @pytest .mark .parametrize (
447
+ "kind, ver, shape, n_nan, fname" ,
448
+ [
449
+ pytest .param ("hb" , "new" , (4 , 38 ), 0 , kernel_hb , id = "hb" ),
450
+ pytest .param ("hb" , "old" , (180 * 2 , 14 ), 20 , kernel_hb_old , id = "hb old" ),
451
+ pytest .param (
452
+ "td moments" , "new" , (12 , 38 ), 0 , kernel_td_moments , id = "td moments"
453
+ ),
454
+ pytest .param ("td gated" , "new" , (100 , 38 ), 0 , kernel_td_gated , id = "td gated" ),
455
+ pytest .param (
456
+ "td moments" ,
457
+ "old" ,
458
+ (1080 , 14 ),
459
+ 60 ,
460
+ kernel_td_moments_old ,
461
+ id = "td moments old" ,
462
+ ),
463
+ ],
464
+ )
465
+ def test_snirf_kernel_basic (kind , ver , shape , n_nan , fname ):
427
466
"""Test reading Kernel SNIRF files with haemoglobin or TD data."""
428
- fname = dict (hb = kernel_hb , td = kernel_td )[kind ]
429
467
raw = read_raw_snirf (fname , preload = True )
430
468
if kind == "hb" :
431
469
# Test data import
432
- assert raw ._data .shape == ( 180 * 2 , 14 )
470
+ assert raw ._data .shape == shape
433
471
hbo_data = raw .get_data ("hbo" )
434
472
hbr_data = raw .get_data ("hbr" )
435
- assert hbo_data .shape == hbr_data .shape == (180 , 14 )
473
+ assert hbo_data .shape == hbr_data .shape == (shape [ 0 ] // 2 , shape [ 1 ] )
436
474
hbo_norm = np .nanmedian (np .linalg .norm (hbo_data , axis = - 1 ))
437
475
hbr_norm = np .nanmedian (np .linalg .norm (hbr_data , axis = - 1 ))
438
- assert 1 < hbr_norm < hbo_norm < 3
439
- n_nan = 20
476
+ # TODO: Old file vs new file scaling, one is wrong!
477
+ if ver == "new" :
478
+ assert 1e-5 < hbr_norm < hbo_norm < 1e-4
479
+ else :
480
+ assert 1 < hbr_norm < 3
481
+ elif kind == "td moments" :
482
+ assert raw ._data .shape == shape
483
+ n_ch = 0
484
+ # TODO: Reasonable values here???
485
+ lims = dict (intensity = (1e4 , 1e7 ), mean = (1e3 , 1e4 ), variance = (1e5 , 1e7 ))
486
+ for key , val in lims .items ():
487
+ data = raw .get_data (f"fnirs_td_moments_{ key } " )
488
+ assert data .shape [1 ] == len (raw .times )
489
+ norm = np .nanmedian (np .linalg .norm (data , axis = - 1 ))
490
+ min_ , max_ = val
491
+ assert min_ < norm < max_ , key
492
+ n_ch += data .shape [0 ]
493
+ assert raw ._data .shape [0 ] == len (raw .ch_names ) == n_ch
440
494
else :
441
- assert raw . _data . shape == ( 1080 , 14 )
442
- data = raw . get_data ( "fnirs_td_moments_intensity" )
443
- # TODO: This will need to update once we triage properly
444
- assert data . shape == raw . _data . shape
445
- norm = np . nanmedian ( np . linalg . norm ( data , axis = - 1 ))
446
- assert 1e5 < norm < 1e6 # TODO: 429256, is this reasonable Molars!??
447
- n_nan = 60
495
+ pass # TODO: add some gated tests
496
+ if ver == "old" :
497
+ sfreq = 8.257638
498
+ n_annot = 2
499
+ else :
500
+ sfreq = 3.759398
501
+ n_annot = 8
448
502
449
- assert_allclose (raw .info ["sfreq" ], 8.257638 )
503
+ assert_allclose (raw .info ["sfreq" ], sfreq , atol = 1e-5 )
450
504
451
505
bad_nans = np .isnan (raw .get_data ()).any (axis = 1 )
452
506
assert np .sum (bad_nans ) == n_nan
453
507
454
- assert len (raw .annotations .description ) == 2
455
- assert raw .annotations .onset [0 ] == 0.036939
456
- assert raw .annotations .onset [1 ] == 0.874633
457
- assert raw .annotations .description [0 ] == "StartTrial"
458
- assert raw .annotations .description [1 ] == "StartIti"
508
+ if n_annot == 2 :
509
+ assert len (raw .annotations .description ) == n_annot
510
+ assert raw .annotations .onset [0 ] == 0.036939
511
+ assert raw .annotations .onset [1 ] == 0.874633
512
+ assert raw .annotations .description [0 ] == "StartTrial"
513
+ assert raw .annotations .description [1 ] == "StartIti"
514
+ else :
515
+ assert len (raw .annotations .description ) == n_annot
516
+ assert raw .annotations .onset [0 ] == 4.988107
517
+ assert raw .annotations .onset [1 ] == 5.988107
518
+ assert raw .annotations .description [0 ] == "StartBlock"
519
+ assert raw .annotations .description [1 ] == "StartTrial"
459
520
460
521
461
522
@requires_testing_data
0 commit comments