Skip to content

B1: stack every z-plane before 3D processing - #1181

Merged
trissim merged 2 commits into
mainfrom
fix/B1-zstack-3d-input
Oct 10, 2026
Merged

trissim merged 2 commits into
mainfrom
fix/B1-zstack-3d-input

Conversation

@trissim

@trissim trissim commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Symptom

test_main[disk-ImageXpress-3d-multiprocessing-direct-none-none] (and every test_main case) failed with create_projection: input must be a 3D array, got 2D in step 6 (second Z-Stack Flattening).

Bisect

First-parent bisect from fc1f946 (good, 2026-09-24): first bad is a3e6a15, merge of PR #394 (shared runtime plumbing). Inside #394 the first observed bad commit is d092a03 "preserve whole-image domains across main-flow handoff". Its parents are hidden by a separate test_main failure (see 3).

Root cause (two defects; the first predates #394)

  1. Stitching ran for z001 only. CallableContract.group_scope_inputs treated every artifact input as the owner of the group scope when the callable declared no group-lineage relation. assemble_stack_cpu(image_tiles, positions) therefore got runtime domain ARTIFACT_MANAGED, and select_lifecycle_anchors kept anchors[:1], so only the first z-plane was assembled. This dates from ccfef5f (July). Before Consolidate runtime execution, producer and projection ownership #394 it was hidden because the loader always gave the lone z001 file a leading axis, so create_projection received (1,H,W).
  2. The rank of a cohort depended on how many files matched. After d092a03, a one-member cohort whose producer declared no plane axis was passed whole as 2D, while the same member in a cohort of three was stacked on the runtime-slice axis. This exposed defect 1 and also broke Cell Counting on the single stitched site.

Fix

  • CallableContract.main_flow_supplies_primary_image is true when the callable takes main-flow pixels as its primary argument and no adapter manages its artifact inputs. Such a callable's group scope is owned by the main flow. Adapter-managed and relation-declared callables are unchanged.
  • ImagePayloadStackComposition.keeps_single_member_whole is the one rule for both the load path (from_loaded_images) and the producer stack cache (with_saved_output_context). Only a persisted whole image (volume domain), or a member that carries its declared axis, stays whole. No case is special-cased for Z.
  • G3 note: the second change is in aligned_image_payload.py, one predicate used in two places. Please carry it through the payload refactor.

3. Stale test_main check (not a production bug)

#134 (8224363, in #394) publishes result-only directories with an empty raster inventory on purpose. test_main rejected that, so it now accepts a subdirectory declared as a results_dir.

Tests

  • New: test_stored_context_input_beside_main_flow_image_keeps_every_anchor, plus a one-member variant of the RGB cohort reload test. The opaque-domain expectations now load a lone member without a plane axis as (1, …) on RUNTIME_SLICE.
  • test_opaque_main_flow_image_domain.py and test_function_patterns.py: 119 passed. Across the 7 related unit files, the 9 failures that remain also fail on main.
  • Official30 parity: 29/30 equivalent, identical to main 3d6a6d7 (both fail only cp_tutorial_3d_monolayer, "No image serialization format is registered for suffix '.pkl'").
  • test_main: 12/48 pass, listed in the PR comment. The remaining failures are not this bug; they are listed below.

Out of scope, found here

  • zarr backend: Zarr conversion output has no declared source projection (zarr-OpenHCS, step 0), and the zarr results metadata entry lacks image_files/available_backends/microscope_handler_name.
  • napari: Timed out waiting 30000ms for Napari ack on port 5555, and MetadataWriteError: Saved images lack typed produced addresses.
  • zmq: port 7777 is fixed and shared with other agents on this machine; the results mixed plates, so they are inconclusive here.

B1 · PR #1181 · guards n/a (bug fix) · production −9 +50 · tests −9 +62

🤖 Generated with Claude Code

Two defects together sent a 2D image into a full-stack callable, so the
z-planes were never stacked.

1. A plain callable that takes main-flow pixels as its primary argument
   (assemble_stack_cpu) treated its stored context input (positions) as
   the owner of its group scope. CallableContract.group_scope_inputs
   defaulted to every artifact input when no group-lineage relation was
   declared, so the runtime domain became ARTIFACT_MANAGED and
   select_lifecycle_anchors kept one anchor: only z001 was assembled.
   Such a callable's group scope is now owned by the main flow
   (main_flow_supplies_primary_image); adapter-managed and
   relation-declared callables are unchanged.

2. Since d092a03 (PR #394) a one-member cohort whose producer declared
   no plane axis was passed whole, while the same member in a larger
   cohort is stacked on the runtime-slice axis. The rank a callable
   received depended on how many files matched. Before #394 the lone
   member got a leading axis, which hid defect 1. Now
   keeps_single_member_whole is the one rule for the load path and for
   the producer's stack cache: only a persisted whole image, or a member
   carrying its declared axis, stays whole.

test_main also checked plate metadata against a rule that #134
(8224363, in #394) changed on purpose: result-only directories are
published with an empty raster inventory. The check now accepts a
subdirectory declared as a results_dir.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 10, 2026 11:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@trissim

trissim commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

test_main passing (12/48): disk-{ImageXpress,OperaPhenix}-direct-{none,fiji}, disk-OpenHCS-direct-{none,fiji}, disk-{ImageXpress,OperaPhenix}-zmq-{none,fiji}. All 48 failed on main before this fix.

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