Read MEF 3.0 in Python¶
import mef3io
with mef3io.Reader("recording.mefd") as r:
print(r.channels) # channel names
x = r.read(r.channels[0]) # whole channel, numpy float64, gaps are NaN
fs = r.info(r.channels[0])["sampling_frequency"]
Install with pip install mef3io. x holds the values in physical units
(r.info(ch)["units_description"], for example uV), one per sample period
from the channel's first sample to its last.
A time window¶
MEF 3.0 times are microseconds since 1970-01-01 UTC ("uUTC"). Ask for a
window [t0, t1); only the data needed for it is read from disk, so this is
fast even on a recording of many gigabytes.
from datetime import datetime, timezone
def uutc(when: datetime) -> int:
return round(when.timestamp() * 1e6)
with mef3io.Reader("recording.mefd") as r:
start = r.info("Fp1")["start_time"] # first sample, uUTC
first_minute = r.read("Fp1", start, start + 60_000_000)
t0 = uutc(datetime(2024, 3, 5, 9, 30, tzinfo=timezone.utc))
ten_seconds = r.read("Fp1", t0, t0 + 10_000_000)
A window returns round((t1 - t0) * fs / 1e6) samples. To turn a sample
index i back into a time: t0 + i * 1e6 / fs.
Gaps are NaN¶
Where the recording has no data (an electrode was off, acquisition paused),
read returns NaN at those positions instead of shifting later samples
earlier. Times stay correct.
import numpy as np
missing = np.isnan(x)
print(f"{missing.mean():.1%} of the span has no data")
clean = x[~missing] # only the recorded samples
To find where the gaps are without reading samples, see Long recordings with gaps.
Annotations¶
with mef3io.Reader("recording.mefd") as r:
r.records() # session-level annotations: type, time (uUTC), text, ...
r.records("Fp1") # one channel's annotations
Encrypted sessions¶
with mef3io.Reader("recording.mefd", password="your password") as r:
...
The level-2 password opens everything. The level-1 password reads the signals but not the subject fields or the annotations. See what encryption protects.
Single-file archives (.mefd.tar)¶
A session packed into one .mefd.tar file is read the same way, in place,
without unpacking:
with mef3io.Reader("recording.mefd.tar") as r:
x = r.read("Fp1")
Code written for mef_tools¶
from mef3io import MefReader # was: from mef_tools.io import MefReader
More¶
The Python guide covers every option: the stored integer
values (read_raw), segment maps, lenient opening of damaged sessions,
cancelling long reads, and writing.