mef3io 1.3.0¶
Released 2026-10-16.
Highlights¶
- Look at a session without reading its samples.
mef3io.inspect(path)returns aSessionSummary: channels, segments, gaps, annotations at every level, file sizes, what is encrypted and what your password opened, the recording-time offset, and which identifying fields the session holds (their values only withinclude_values=True). Where section 3 is locked (opened with only the level-1 password, or with none on an encrypted session), times are resolved assuming offset 0, as aReaderdoes, markedoffset_assumed_zero=Trueand listed inwarnings(offset-assumed-zero). It never reads a data (.tdat) file, so a terabyte session costs about as much as opening aReader. From a terminal:python -m mef3io inspect PATH(--json,--values,--index,--lenient,--password/--password-env). Python and C++ only (guide, #67). - Cancel and follow long work.
Reader.read/read_raw,archive_session,extract_session,inspect, validation,repair_sessionandrecover_sessiontakecancel=(amef3io.CancelToken, cancelled from any thread) andprogress=(aprogress(done, total)callback, in bytes). A cancelled call leaves nothing behind. Python and C++; the C ABI for reads, archiving, extracting and recovery; not MATLAB (guide, #69). - What encryption protects, stated plainly. MEF 3.0 encryption hides the subject's identity, the technical metadata and annotation text, not the samples or their timing (encryption model).
-
meflib's recording-time offset is deprecated as anonymization. It does not hide the recording date. mef3io never creates such sessions; it reads and extends existing ones correctly (De-identification, example
11_legacy_rto_sessions.py). -
Documentation. A plain introduction, MEF 3.0 for students; links to the MEF 3.0 specification and the original libraries (meflib, pymef, mef_tools); release notes for every version; and clearer notes on what the legacy tools cannot open:
.mefd.tararchives (unpack them first) and encrypted data blocks. Short how-to pages: converting EDF, EDF+ or BDF to MEF 3.0 (with a runnable example and a new optionalmef3io[edf]extra), reading in Python and in MATLAB, and long recordings with gaps.
Fixes¶
- Encrypted data blocks from other writers are now decoded correctly. meflib enciphers only the first 16 bytes of a data block's compression table; earlier mef3io versions deciphered all 256 and so decoded such blocks wrongly. Sessions mef3io writes were never affected: it writes data blocks unencrypted (#80).
- Non-ASCII passwords now match meflib and pymef (#84). Each character is
turned into a byte the way meflib does it, so a password such as "bé" set in
pymef opens in mef3io and the other way round. Files that mef3io 1.2.0 or
earlier encrypted with a non-ASCII password still open, with a
LegacyPasswordWarning. A newPasswordInteropWarningflags passwords the legacy tools cannot handle (over 15 characters or bytes, or characters above U+00FF). extract_session(..., overwrite=True)can no longer lose both trees. It used to delete the existing target before unpacking; a failure part-way then lost the old session and the new one. It now unpacks into a temporary sibling directory and swaps it in only when complete.- Repair and recovery decide first, then write.
repair_sessionandrecover_sessionwork out every change in a read-only pass, then write in one short step. Before writing, each segment is checked again; one that another program changed in between is skipped with a reason, not overwritten from stale information.
Upgrading¶
extract_session(..., overwrite=True)briefly needs disk space for both the old and the new tree. A hard kill mid-extract can leave a<dest>.mef3io-extract-<hex>directory, and a replaced tree that could not be deleted is left as<dest>.mef3io-replaced-<hex>; both are safe to delete.- Non-ASCII passwords: sessions that mef3io up to 1.2.0 encrypted with a
non-ASCII password open with a
LegacyPasswordWarning; meflib and pymef cannot open them with that password. New files use meflib's rule. mef3io.Cancelledis not aMefError(nor aRuntimeError): stopping on request is not a failure. It is raised only when you pass acancel=token and cancel it, so existing code is unaffected; code that passes one should catchCancelledby name.inspectis strict by default, likeReader: an unreadable segment or record file raises. Passstrict=False(--lenienton the command line) to have it listed inproblemsinstead.- From 1.1.x: if you used
Reader(cache=...)with encrypted sessions on 1.1.x, delete your mef3io cache folder; 1.2.0+ never caches encrypted sessions and removes such snapshots when it next opens that session withcache=. - From 1.1.2 or earlier: sessions written by those versions declare some
buffer sizes as
0, which can crash meflib-based readers; see 1.1.3 and Validating and repairing.
Full list of changes: v1.2.0...v1.3.0.