Skip to content

mef3io 1.3.0

Released 2026-10-16.

Highlights

  • Look at a session without reading its samples. mef3io.inspect(path) returns a SessionSummary: 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 with include_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 a Reader does, marked offset_assumed_zero=True and listed in warnings (offset-assumed-zero). It never reads a data (.tdat) file, so a terabyte session costs about as much as opening a Reader. 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_session and recover_session take cancel= (a mef3io.CancelToken, cancelled from any thread) and progress= (a progress(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.tar archives (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 optional mef3io[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 new PasswordInteropWarning flags 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_session and recover_session work 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.Cancelled is not a MefError (nor a RuntimeError): stopping on request is not a failure. It is raised only when you pass a cancel= token and cancel it, so existing code is unaffected; code that passes one should catch Cancelled by name.
  • inspect is strict by default, like Reader: an unreadable segment or record file raises. Pass strict=False (--lenient on the command line) to have it listed in problems instead.
  • 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 with cache=.
  • 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.