Skip to content

Open the 2dseq memory map read-only - #215

Merged
headmeister merged 1 commit into
isi-nmr:masterfrom
gdevenyi:fix/read-only-2dseq
Aug 10, 2026
Merged

Open the 2dseq memory map read-only#215
headmeister merged 1 commit into
isi-nmr:masterfrom
gdevenyi:fix/read-only-2dseq

Conversation

@gdevenyi

Copy link
Copy Markdown
Contributor

A dataset on a read-only file or mount cannot be loaded at all:

PermissionError: [Errno 13] Permission denied: ".../2/pdata/1/2dseq"

Cause

read_array in brukerapi/paths.py maps a filesystem path without giving a mode:

return np.array(np.memmap(path, dtype=dtype, shape=shape, order=order)[:])

np.memmap defaults to mode="r+", so every dataset load asks the operating system for write access to the raw data file. Nothing writes it — the array is copied out of the map on the same line.

This matters because a shared scanner archive is normally exposed read-only. The parameter files are unaffected, since those are opened in text mode, so the failure looks oddly selective: acqp, method, visu_pars and reco all read, and only the binary fails, once per scan.

Reproduction

Copy any PV6 study, chmod -R a-w, and load it. On the same file:

mode="r+"  (the default)  -> PermissionError: Permission denied
mode="r"                  -> OK, read 1048576 values

The change

mode="r" on that one call. The archive branch just below already reads through path.open("rb") and was never affected.

test_dataset_reads_from_a_read_only_source covers it. It lives in test_paths.py because that module's study is synthetic and needs no corpus; it fails with PermissionError without the change.

Test suite

Run against a local PV5.1/PV6.0.1/PV7.0.0 corpus:

  • baseline (master): 4 failed, 245 passed, 51 skipped
  • with this change: 4 failed, 246 passed, 51 skipped

The same four failures occur either way — they are corpus-dependent and unrelated to this change. ruff check clean at the pinned 0.16.0.

Found while diagnosing a user report against a downstream converter, where the raw data lives on a read-only archive mount.

read_array maps a filesystem path with np.memmap and no mode. numpy's default
is "r+", so every dataset load asks the operating system for write access to the
raw data file. Nothing writes it: the array is copied out of the map on the same
line.

The consequence is that a dataset on a read-only file or mount cannot be loaded
at all -- which is how a shared scanner archive is normally exposed:

    PermissionError: [Errno 13] Permission denied: '.../2/pdata/1/2dseq'

The parameter files are unaffected, since those are opened in text mode, so the
failure looks selective: acqp, method, visu_pars and reco all read, and only the
binary fails, once per scan.

Reproduced by copying a PV6 study, chmod -R a-w, and loading it; on the same
file, mode="r+" raises and mode="r" reads all 1048576 values.

The archive branch below already reads through path.open("rb") and was never
affected.

test_dataset_reads_from_a_read_only_source covers it, in test_paths.py because
that module's study is synthetic and needs no corpus. It fails with
PermissionError without this change.
@headmeister
headmeister merged commit 3db1b81 into isi-nmr:master Aug 10, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants