Skip to content

Commit 997490f

Browse files
MAINT: Replace manual PNS binary block reader in _read_segment_file with mffpy (#14030)
1 parent 9268e85 commit 997490f

2 files changed

Lines changed: 12 additions & 67 deletions

File tree

doc/changes/dev/14030.other.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Replace the manual PNS binary block reader in :func:`mne.io.read_raw_egi` with ``mffpy``-backed reading via ``get_physical_samples_from_epoch``, by `Pragnya Khandelwal`_.

mne/io/egi/egimff.py

Lines changed: 11 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
from ..base import BaseRaw
2626
from .events import _combine_triggers, _read_events, _triage_include_exclude
2727
from .general import (
28-
_block_r,
2928
_get_blocks,
3029
_get_ep_info,
3130
_get_signalfname,
@@ -598,7 +597,6 @@ def __init__(
598597
def _read_segment_file(self, data, idx, fi, start, stop, cals, mult):
599598
"""Read a chunk of data."""
600599
logger.debug(f"Reading MFF {start:6d} ... {stop:6d} ...")
601-
dtype = "<f4" # Data read in four byte floats.
602600

603601
egi_info = self._raw_extras[fi]
604602
one = np.zeros((egi_info["kind_bounds"][-1], stop - start))
@@ -649,71 +647,17 @@ def _read_segment_file(self, data, idx, fi, start, stop, cals, mult):
649647
one[eeg_one, cols] = eeg_chunk[eeg_in]
650648

651649
if len(pns_one) > 0:
652-
# PNS Data is present and should be read:
653-
pns_filepath = egi_info["pns_filepath"]
654-
pns_info = egi_info["pns_sample_blocks"]
655-
n_channels = pns_info["n_channels"]
656-
samples_block = pns_info["samples_block"]
657-
658-
# Get starting/stopping block/samples
659-
block_samples_offset = np.cumsum(samples_block)
660-
offset_blocks = np.sum(block_samples_offset < start)
661-
offset_samples = start - (
662-
block_samples_offset[offset_blocks - 1] if offset_blocks > 0 else 0
663-
)
664-
665-
samples_to_read = stop - start
666-
with open(pns_filepath, "rb", buffering=0) as fid:
667-
# Check file size
668-
fid.seek(0, 2)
669-
file_size = fid.tell()
670-
fid.seek(0)
671-
# Go to starting block
672-
current_block = 0
673-
current_block_info = None
674-
current_data_sample = 0
675-
while current_block < offset_blocks:
676-
this_block_info = _block_r(fid)
677-
if this_block_info is not None:
678-
current_block_info = this_block_info
679-
fid.seek(current_block_info["block_size"], 1)
680-
current_block += 1
681-
682-
# Start reading samples
683-
while samples_to_read > 0:
684-
if samples_to_read == 1 and fid.tell() == file_size:
685-
# We are in the presence of the EEG bug
686-
# fill with zeros and break the loop
687-
one[pns_one, -1] = 0
688-
break
689-
690-
this_block_info = _block_r(fid)
691-
if this_block_info is not None:
692-
current_block_info = this_block_info
693-
694-
to_read = current_block_info["nsamples"] * current_block_info["nc"]
695-
block_data = np.fromfile(fid, dtype, to_read)
696-
block_data = block_data.reshape(n_channels, -1, order="C")
697-
698-
# Compute indexes
699-
samples_read = block_data.shape[1]
700-
if offset_samples > 0:
701-
# First block read, skip to the offset:
702-
block_data = block_data[:, offset_samples:]
703-
samples_read = samples_read - offset_samples
704-
offset_samples = 0
705-
706-
if samples_to_read < samples_read:
707-
# Last block to read, skip the last samples
708-
block_data = block_data[:, :samples_to_read]
709-
samples_read = samples_to_read
710-
711-
s_start = current_data_sample
712-
s_end = s_start + samples_read
713-
714-
one[pns_one, disk_use_idx[s_start:s_end]] = block_data[pns_in]
715-
samples_to_read = samples_to_read - samples_read
716-
current_data_sample = current_data_sample + samples_read
650+
mff_reader = _get_mff_reader(egi_info["mff_path"])
651+
mff_epochs = mff_reader.epochs
652+
for ei, t0, dt, out_start, out_stop in _disk_range_to_epochs(
653+
egi_info, start, stop
654+
):
655+
logger.debug(f" Reading PNS from epoch {ei} t0={t0} dt={dt}")
656+
pns_chunk, _ = mff_reader.get_physical_samples_from_epoch(
657+
mff_epochs[ei], t0=t0, dt=dt, channels=["PNSData"]
658+
)["PNSData"]
659+
cols = disk_use_idx[out_start:out_stop]
660+
one[pns_one, cols[: pns_chunk.shape[1]]] = pns_chunk[pns_in]
717661

718662
# do the calibration
719663
_mult_cal_one(data, one, idx, cals, mult)

0 commit comments

Comments
 (0)