Skip to content

fix: route multipage frames by the acquisition XML, and carry z forward across frames - #134

Open
MilagrosMarin wants to merge 2 commits into
datajoint:mainfrom
MilagrosMarin:fix/bidirectional-z-and-multiplane-detection
Open

fix: route multipage frames by the acquisition XML, and carry z forward across frames#134
MilagrosMarin wants to merge 2 commits into
datajoint:mainfrom
MilagrosMarin:fix/bidirectional-z-and-multiplane-detection

Conversation

@MilagrosMarin

Copy link
Copy Markdown
Collaborator

What this covers

Two defects in reading PrairieView acquisitions, both found while validating two-photon
sessions against the lab's own analysis.

Multipage frame routing

get_prairieview_filenames already filters the file list by channel and plane. The multipage
branch then derived page offsets from a global channel-by-plane stride and applied them to
that already-filtered list, so the offset was applied twice.

With two channels this left roughly half the output frames unassigned. Because the output array
is allocated with np.empty, those frames carried uninitialised memory instead of raising — a
movie of nominally correct length whose content was arbitrary.

get_prairieview_file_pages() now returns the (filename, page) pair the acquisition XML names
for each frame, and the multipage branch writes exactly those, asserting one write per output
frame so a mismatch between XML and disk fails instead of passing silently.

Z positions across frames

Z is read from a PVStateShard, which records state changes. A frame whose z has not moved
omits positionCurrent entirely, so counting those elements counts re-declarations rather than
planes. A 3-plane bidirectional-Z recording therefore failed outright with "Number of z fields
does not match number of depths"
. Z is now carried forward from the document-level shard.

Verification

Regression tests live in the workflow repository, since element-interface has no test suite:
8 cases on a synthetic two-channel multipage acquisition, built with tifffile only — no CaImAn
and no database. All 8 pass against this change. Against the previous loader 5 fail, including
both tests that check frame content.

The coverage test truncates the source file so the XML names a page that does not exist on disk,
which is the case the previous implementation passed through silently.

Not covered

The affected acquisitions are two-channel. Every session currently available to us is
single-channel, so the fix is verified against a constructed acquisition rather than recorded
data. A real two-channel session has been requested.

Two defects in reading PrairieView acquisitions.

Multipage routing derived page offsets from a global channel-by-plane stride
and applied them to a file list that get_prairieview_filenames had already
filtered by channel and plane, so the offset was applied twice. With two
channels roughly half the output frames were never assigned, and because the
output array is allocated with np.empty those frames held uninitialised memory
rather than raising. get_prairieview_file_pages now returns the filename and
page the XML names for each frame, and the multipage branch asserts one write
per output frame.

Z positions are read from a PVStateShard, which records state *changes*: a
frame whose z has not moved omits positionCurrent entirely, so counting the
elements counts re-declarations rather than planes. A 3-plane bidirectional-Z
recording therefore failed outright with 'Number of z fields does not match
number of depths'. Z is now carried forward from the document-level shard.
@MilagrosMarin
MilagrosMarin marked this pull request as ready for review August 21, 2026 12:50
@MilagrosMarin
MilagrosMarin requested a review from ttngu207 August 21, 2026 12:50
Two gaps in the frame-routing change.

A depth declared neither at the document level nor in any preceding frame left
None in the position list. The length assert compares counts, so it could not
see the None, and the value reached fieldZ and then ScanInfo.Field.field_z. It
now raises where the value is produced.

num_frames is floored by num_planes, so an acquisition that stopped part-way
through its last cycle names more frames for the early planes than the late
ones. Refusing outright made such a recording unprocessable; every plane must
come out the same length, so the incomplete cycle is dropped with a warning.
Fewer frames than expected still raises, since that means data is missing
rather than a cycle being partial.

Version 0.8.4 with a changelog entry, which the previous commit omitted.
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.

1 participant