|
24 | 24 | import pytest |
25 | 25 |
|
26 | 26 | from mne import pick_types, Annotations |
27 | | -from mne.annotations import events_from_annotations, read_annotations |
| 27 | +from mne.annotations import _ndarray_ch_names, events_from_annotations, read_annotations |
28 | 28 | from mne.datasets import testing |
29 | 29 | from mne.io import read_raw_edf, read_raw_bdf, read_raw_fif, edf, read_raw_gdf |
30 | 30 | from mne.io.tests.test_raw import _test_raw_reader |
@@ -504,6 +504,81 @@ def test_read_utf8_annotations(): |
504 | 504 | assert raw.annotations[1]["description"] == "仰卧" |
505 | 505 |
|
506 | 506 |
|
| 507 | +def test_read_annotations_edf(tmp_path): |
| 508 | + """Test reading annotations from EDF file.""" |
| 509 | + annot = ( |
| 510 | + b"+1.1\x14Event A@@CH1\x14\x00\x00" |
| 511 | + b"+1.2\x14Event A\x14\x00\x00" |
| 512 | + b"+1.3\x14Event B@@CH1\x14\x00\x00" |
| 513 | + b"+1.3\x14Event B@@CH2\x14\x00\x00" |
| 514 | + b"+1.4\x14Event A@@CH3\x14\x00\x00" |
| 515 | + b"+1.5\x14Event B\x14\x00\x00" |
| 516 | + ) |
| 517 | + annot_file = tmp_path / "annotations.edf" |
| 518 | + with open(annot_file, "wb") as f: |
| 519 | + f.write(annot) |
| 520 | + |
| 521 | + # Test reading annotations from channel data |
| 522 | + with open(annot_file, "rb") as f: |
| 523 | + tal_channel = _read_ch( |
| 524 | + f, |
| 525 | + subtype="EDF", |
| 526 | + dtype="<i2", |
| 527 | + samp=-1, |
| 528 | + dtype_byte=None, |
| 529 | + ) |
| 530 | + |
| 531 | + # Read annotations without input channel names: annotations are left untouched and |
| 532 | + # assigned as global |
| 533 | + annotations = _read_annotations_edf(tal_channel, ch_names=None, encoding="latin1") |
| 534 | + assert_allclose(annotations.onset, [1.1, 1.2, 1.3, 1.3, 1.4, 1.5]) |
| 535 | + assert not any(annotations.duration) # all durations are 0 |
| 536 | + assert_array_equal( |
| 537 | + annotations.description, |
| 538 | + [ |
| 539 | + "Event A@@CH1", |
| 540 | + "Event A", |
| 541 | + "Event B@@CH1", |
| 542 | + "Event B@@CH2", |
| 543 | + "Event A@@CH3", |
| 544 | + "Event B", |
| 545 | + ], |
| 546 | + ) |
| 547 | + assert_array_equal( |
| 548 | + annotations.ch_names, _ndarray_ch_names([(), (), (), (), (), ()]) |
| 549 | + ) |
| 550 | + |
| 551 | + # Read annotations with complete input channel names: each annotation is parsed and |
| 552 | + # associated to a channel |
| 553 | + annotations = _read_annotations_edf( |
| 554 | + tal_channel, ch_names=["CH1", "CH2", "CH3"], encoding="latin1" |
| 555 | + ) |
| 556 | + assert_allclose(annotations.onset, [1.1, 1.2, 1.3, 1.4, 1.5]) |
| 557 | + assert not any(annotations.duration) # all durations are 0 |
| 558 | + assert_array_equal( |
| 559 | + annotations.description, ["Event A", "Event A", "Event B", "Event A", "Event B"] |
| 560 | + ) |
| 561 | + assert_array_equal( |
| 562 | + annotations.ch_names, |
| 563 | + _ndarray_ch_names([("CH1",), (), ("CH1", "CH2"), ("CH3",), ()]), |
| 564 | + ) |
| 565 | + |
| 566 | + # Read annotations with incomplete input channel names: "CH3" is missing from input |
| 567 | + # channels, turning the related annotation into a global one |
| 568 | + annotations = _read_annotations_edf( |
| 569 | + tal_channel, ch_names=["CH1", "CH2"], encoding="latin1" |
| 570 | + ) |
| 571 | + assert_allclose(annotations.onset, [1.1, 1.2, 1.3, 1.4, 1.5]) |
| 572 | + assert not any(annotations.duration) # all durations are 0 |
| 573 | + assert_array_equal( |
| 574 | + annotations.description, |
| 575 | + ["Event A", "Event A", "Event B", "Event A@@CH3", "Event B"], |
| 576 | + ) |
| 577 | + assert_array_equal( |
| 578 | + annotations.ch_names, _ndarray_ch_names([("CH1",), (), ("CH1", "CH2"), (), ()]) |
| 579 | + ) |
| 580 | + |
| 581 | + |
507 | 582 | def test_read_latin1_annotations(tmp_path): |
508 | 583 | """Test if annotations encoded as Latin-1 can be read. |
509 | 584 |
|
|
0 commit comments