Skip to content

Crop fully black borders after Z alignment#23

Open
msayr wants to merge 1 commit into
z_alignfrom
codex/add-optimization-for-black-canvas-cropping
Open

Crop fully black borders after Z alignment#23
msayr wants to merge 1 commit into
z_alignfrom
codex/add-optimization-for-black-canvas-cropping

Conversation

@msayr

@msayr msayr commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Motivation

  • The Z-aligned output uses a large estimated Y/X canvas (derived from root_offset + pad_offset + [10000,10000]) which produces permanent black borders across many slices when stacks drift.
  • We want to shrink the final aligned dataset to the minimal common YX canvas that still contains any valid data across the full stack to reduce wasted black space and downstream storage/visualization costs.

Description

  • Added ._mask_union_bbox, ._copy_cropped_store, and crop_aligned_stack_borders helpers to emalign/align_dataset_z.py to compute the union bbox of the mask over Z, create cropped temporary stores, and atomically replace the output with the cropped versions.
  • The crop rewrites the aligned image store, the aligned mask store, and the optional downsampled inspection store, and updates spatial metadata keys such as voxel_offset, offset, uncropped_shape, and crop_bbox_yx.
  • Enabled the crop by default at the end of align_dataset_z and added a CLI flag --no-crop-black-borders to preserve the previous behavior.
  • The crop implementation operates using temporary .crop_tmp stores and atomic os.replace to avoid leaving partial outputs on failure.

Testing

  • Ran python -m py_compile emalign/align_dataset_z.py which succeeded.
  • Ran python -m compileall emalign/align_dataset_z.py which succeeded.
  • Attempted a small TensorStore smoke test to exercise the crop end-to-end but it was blocked by an environment dependency: importing cv2 failed due to a missing libGL.so.1 (test therefore could not complete in this environment).

Codex Task

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 36070a7d7b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


for z0 in range(0, z_max, chunk_z):
z1 = min(z0 + chunk_z, z_max)
block = mask_store[z0:z1].read().result()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Limit mask reads to smaller tiles

With the default destination canvas created as root_offset + pad_offset + [10000, 10000], this read materializes up to 64 full YX mask slices at once, and the following np.nonzero allocates index arrays for every true voxel. On a typical 10k x 10k aligned stack this is already more than 6 GB before the index arrays, so the new default crop can OOM after a long alignment finishes; scan one/few slices or YX tiles instead.

Useful? React with 👍 / 👎.


if crop_black_borders:
logging.info('Cropping fully black borders from aligned stack...')
crop_aligned_stack_borders(destination_path, save_downsampled, project_name)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Account for cropped outputs before rerendering

Because the crop runs by default for the same destination that later resumable runs open, a subsequent align_dataset_z --wipe-progress <stack> without --start-over reuses the original config offsets in execute_alignment/align_stack_z against an already-cropped store. Those writes are still in the uncropped canvas coordinate system, so the rerendered stack is shifted by the crop amount and may expand the store back out with black borders; either adjust offsets by crop_bbox_yx or require --start-over/no-crop for rerenders.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant