@@ -284,9 +284,17 @@ def test_set_eeg_reference_ch_type(ch_type, msg, projection):
284284 else :
285285 ref_ch = raw .copy ().pick (picks = ch_type ).ch_names
286286
287+ # joint=True forces the union-of-types behavior so we can keep validating
288+ # ref_data against the joint mean; per-type default is covered by
289+ # test_set_eeg_reference_ch_type_list_per_type below.
290+ joint = isinstance (ch_type , list ) and len (ch_type ) > 1
287291 with catch_logging () as log :
288292 reref , ref_data = set_eeg_reference (
289- raw .copy (), ch_type = ch_type , projection = projection , verbose = True
293+ raw .copy (),
294+ ch_type = ch_type ,
295+ projection = projection ,
296+ joint = joint ,
297+ verbose = True ,
290298 )
291299
292300 if not projection :
@@ -304,6 +312,47 @@ def test_set_eeg_reference_ch_type(ch_type, msg, projection):
304312 set_eeg_reference (raw2 , ch_type = "auto" , projection = projection )
305313
306314
315+ @pytest .mark .parametrize ("projection" , [False , True ])
316+ def test_set_eeg_reference_ch_type_list_per_type (projection ):
317+ """Test list ch_type defaults to one reference per channel type (gh-13913)."""
318+ # Build seeg at +10 uV and ecog at -10 uV (constant). Union mean is zero,
319+ # so a single union average reference would leave each subset's original
320+ # offset intact. A per-type CAR zeros both subsets.
321+ sfreq = 1000.0
322+ n = 500
323+ data = np .vstack ([np .full ((4 , n ), 10.0 ), np .full ((4 , n ), - 10.0 )]) * 1e-6
324+ ch_names = [f"S{ i } " for i in range (4 )] + [f"E{ i } " for i in range (4 )]
325+ info = create_info (ch_names , sfreq , ["seeg" ] * 4 + ["ecog" ] * 4 )
326+ raw = RawArray (data , info )
327+
328+ # Default joint=False: per-type reference. ref_data is None.
329+ reref , ref_data = set_eeg_reference (
330+ raw .copy (),
331+ ref_channels = "average" ,
332+ ch_type = ["seeg" , "ecog" ],
333+ projection = projection ,
334+ )
335+ if projection :
336+ reref .apply_proj ()
337+ assert ref_data is None
338+ assert_allclose (reref .get_data (picks = "seeg" ).mean (), 0.0 , atol = 1e-15 )
339+ assert_allclose (reref .get_data (picks = "ecog" ).mean (), 0.0 , atol = 1e-15 )
340+
341+ # joint=True: legacy union-of-types behavior. Union mean is zero, so
342+ # neither subset gets zeroed.
343+ reref_joint , _ = set_eeg_reference (
344+ raw .copy (),
345+ ref_channels = "average" ,
346+ ch_type = ["seeg" , "ecog" ],
347+ projection = projection ,
348+ joint = True ,
349+ )
350+ if projection :
351+ reref_joint .apply_proj ()
352+ assert_allclose (reref_joint .get_data (picks = "seeg" ).mean (), 10e-6 , atol = 1e-15 )
353+ assert_allclose (reref_joint .get_data (picks = "ecog" ).mean (), - 10e-6 , atol = 1e-15 )
354+
355+
307356@testing .requires_testing_data
308357def test_set_eeg_reference_rest ():
309358 """Test setting a REST reference."""
0 commit comments