From 96bd4f22b37840b4dd95696e1fe8dba503b66db2 Mon Sep 17 00:00:00 2001 From: PragnyaKhandelwal Date: Fri, 10 Jul 2026 20:14:24 +0530 Subject: [PATCH 1/6] ENH: replace _get_blocks binary reader with mffpy Reader API in _read_mff_header --- mne/io/egi/egimff.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/mne/io/egi/egimff.py b/mne/io/egi/egimff.py index fcd66a50ce8..808a3ade1c6 100644 --- a/mne/io/egi/egimff.py +++ b/mne/io/egi/egimff.py @@ -25,7 +25,6 @@ from ..base import BaseRaw from .events import _combine_triggers, _read_events, _triage_include_exclude from .general import ( - _get_blocks, _get_ep_info, _get_signalfname, ) @@ -70,6 +69,7 @@ def _disk_range_to_epochs(egi_info, disk_start, disk_stop): def _read_mff_header(filepath): """Read mff header.""" _soft_import("mffpy", "reading EGI MFF data") + from mffpy import Reader from mffpy.xml_files import XML all_files = _get_signalfname(filepath) @@ -88,8 +88,14 @@ def _read_mff_header(filepath): rt_elem = info_obj.find("recordTime") record_time = str(rt_elem.text) if rt_elem is not None else "" - fname = op.join(filepath, eeg_file) - signal_blocks = _get_blocks(fname) + reader = Reader(filepath) + signal_blocks = dict( + n_channels=reader.num_channels["EEG"], + sfreq=reader.sampling_rates["EEG"], + n_blocks=len(reader.block_sample_counts["EEG"]), + samples_block=np.array(reader.block_sample_counts["EEG"]), + header_sizes=[], + ) epochs = _get_ep_info(filepath) summaryinfo = dict(eeg_fname=eeg_file, info_fname=eeg_info_file) summaryinfo.update(signal_blocks) @@ -169,9 +175,10 @@ def _read_mff_header(filepath): pns_names = [] if "PNS" in all_files: - pns_fpath = op.join(filepath, all_files["PNS"]["signal"]) - pns_blocks = _get_blocks(pns_fpath) - pns_samples = pns_blocks["samples_block"] + pns_sample_blocks = dict( + samples_block=np.array(reader.block_sample_counts["PNSData"]) + ) + pns_samples = pns_sample_blocks["samples_block"] signal_samples = signal_blocks["samples_block"] same_blocks = np.array_equal( pns_samples[:-1], signal_samples[:-1] @@ -210,7 +217,7 @@ def _read_mff_header(filepath): pns_types=pns_types, pns_units=pns_units, pns_fname=all_files["PNS"]["signal"], - pns_sample_blocks=pns_blocks, + pns_sample_blocks=pns_sample_blocks, ) summaryinfo.update( From e7e142c752b0c08323802f5410b8beed2328c885 Mon Sep 17 00:00:00 2001 From: PragnyaKhandelwal Date: Fri, 10 Jul 2026 20:19:03 +0530 Subject: [PATCH 2/6] DOC: add changelog fragment for PR 14043 --- doc/changes/dev/14043.other.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changes/dev/14043.other.rst diff --git a/doc/changes/dev/14043.other.rst b/doc/changes/dev/14043.other.rst new file mode 100644 index 00000000000..a7a782210fe --- /dev/null +++ b/doc/changes/dev/14043.other.rst @@ -0,0 +1 @@ +Replace manual binary block reader ``_get_blocks`` with :class:`mffpy.Reader` API in ``_read_mff_header``, removing low-level EGI binary parsing in favour of the existing mffpy dependency (:gh:`14043`). By :newcontrib:`Pragnya Khandelwal`. From 3e5d8b3ec3427c572033248b91542f19455afc07 Mon Sep 17 00:00:00 2001 From: PragnyaKhandelwal Date: Fri, 10 Jul 2026 20:25:34 +0530 Subject: [PATCH 3/6] ENH: remove _get_blocks and _block_r, now replaced by mffpy Reader --- mne/io/egi/general.py | 85 ------------------------------------------- 1 file changed, 85 deletions(-) diff --git a/mne/io/egi/general.py b/mne/io/egi/general.py index ff196c0038f..b0bab4c92c1 100644 --- a/mne/io/egi/general.py +++ b/mne/io/egi/general.py @@ -6,8 +6,6 @@ import os import re -import numpy as np - from ...utils import _pl @@ -28,62 +26,6 @@ def _get_ep_info(filepath): return epoch_info -def _get_blocks(filepath): - """Get info from meta data blocks.""" - binfile = os.path.join(filepath) - n_blocks = 0 - samples_block = [] - header_sizes = [] - n_channels = [] - sfreq = [] - # Meta data consists of: - # * 1 byte of flag (1 for meta data, 0 for data) - # * 1 byte of header size - # * 1 byte of block size - # * 1 byte of n_channels - # * n_channels bytes of offsets - # * n_channels bytes of sigfreqs? - with open(binfile, "rb") as fid: - fid.seek(0, 2) # go to end of file - file_length = fid.tell() - block_size = file_length - fid.seek(0) - position = 0 - while position < file_length: - block = _block_r(fid) - if block is None: - samples_block.append(samples_block[n_blocks - 1]) - n_blocks += 1 - fid.seek(block_size, 1) - position = fid.tell() - continue - block_size = block["block_size"] - header_size = block["header_size"] - header_sizes.append(header_size) - samples_block.append(block["nsamples"]) - n_blocks += 1 - fid.seek(block_size, 1) - sfreq.append(block["sfreq"]) - n_channels.append(block["nc"]) - position = fid.tell() - - if any([n != n_channels[0] for n in n_channels]): - raise RuntimeError("All the blocks don't have the same amount of channels.") - if any([f != sfreq[0] for f in sfreq]): - raise RuntimeError("All the blocks don't have the same sampling frequency.") - if len(samples_block) < 1: - raise RuntimeError("There seems to be no data") - samples_block = np.array(samples_block) - signal_blocks = dict( - n_channels=n_channels[0], - sfreq=sfreq[0], - n_blocks=n_blocks, - samples_block=samples_block, - header_sizes=header_sizes, - ) - return signal_blocks - - def _get_signalfname(filepath): """Get filenames.""" from mffpy.xml_files import XML @@ -114,30 +56,3 @@ def _get_signalfname(filepath): ) return all_files - -def _block_r(fid): - """Read meta data.""" - if np.fromfile(fid, dtype=np.dtype("i4"), count=1).item() != 1: # not meta - return None - header_size = np.fromfile(fid, dtype=np.dtype("i4"), count=1).item() - block_size = np.fromfile(fid, dtype=np.dtype("i4"), count=1).item() - hl = int(block_size / 4) - nc = np.fromfile(fid, dtype=np.dtype("i4"), count=1).item() - nsamples = int(hl / nc) - np.fromfile(fid, dtype=np.dtype("i4"), count=nc) # sigoffset - sigfreq = np.fromfile(fid, dtype=np.dtype("i4"), count=nc) - depth = sigfreq[0] & 0xFF - if depth != 32: - raise ValueError("I do not know how to read this MFF (depth != 32)") - sfreq = sigfreq[0] >> 8 - count = int(header_size / 4 - (4 + 2 * nc)) - np.fromfile(fid, dtype=np.dtype("i4"), count=count) # sigoffset - block = dict( - nc=nc, - hl=hl, - nsamples=nsamples, - block_size=block_size, - header_size=header_size, - sfreq=sfreq, - ) - return block From 74f14b6b88ca0c62fd118e7e6461eaef96d14b51 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:56:04 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mne/io/egi/general.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mne/io/egi/general.py b/mne/io/egi/general.py index b0bab4c92c1..f06c4095df0 100644 --- a/mne/io/egi/general.py +++ b/mne/io/egi/general.py @@ -55,4 +55,3 @@ def _get_signalfname(filepath): f"found in {filepath}:\n{infofiles_str}" ) return all_files - From a1650a31a76dc1c59f9923d76d6bef35aa67caab Mon Sep 17 00:00:00 2001 From: PragnyaKhandelwal Date: Sat, 11 Jul 2026 12:31:02 +0530 Subject: [PATCH 5/6] fix changelog: use plain name link and backtick for mffpy.Reader --- doc/changes/dev/14043.other.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/changes/dev/14043.other.rst b/doc/changes/dev/14043.other.rst index a7a782210fe..0dd87c7187a 100644 --- a/doc/changes/dev/14043.other.rst +++ b/doc/changes/dev/14043.other.rst @@ -1 +1 @@ -Replace manual binary block reader ``_get_blocks`` with :class:`mffpy.Reader` API in ``_read_mff_header``, removing low-level EGI binary parsing in favour of the existing mffpy dependency (:gh:`14043`). By :newcontrib:`Pragnya Khandelwal`. +Replace manual binary block reader ``_get_blocks`` with ``mffpy.Reader`` API in ``_read_mff_header``, removing low-level EGI binary parsing in favour of the existing mffpy dependency (:gh:`14043`), by `Pragnya Khandelwal`_. From 99070a29b32d97c0331ff3df6c7da6e69ea008fd Mon Sep 17 00:00:00 2001 From: PragnyaKhandelwal Date: Sat, 11 Jul 2026 16:37:36 +0530 Subject: [PATCH 6/6] DOC: fix changelog entry --- doc/changes/dev/14043.other.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/changes/dev/14043.other.rst b/doc/changes/dev/14043.other.rst index 0dd87c7187a..331ba62d988 100644 --- a/doc/changes/dev/14043.other.rst +++ b/doc/changes/dev/14043.other.rst @@ -1 +1 @@ -Replace manual binary block reader ``_get_blocks`` with ``mffpy.Reader`` API in ``_read_mff_header``, removing low-level EGI binary parsing in favour of the existing mffpy dependency (:gh:`14043`), by `Pragnya Khandelwal`_. +Replace manual binary block reader ``_get_blocks`` with ``mffpy.Reader`` API in ``_read_mff_header``, removing low-level EGI binary parsing in favour of the existing mffpy dependency, by `Pragnya Khandelwal`_.