Skip to content

Restore stitched TIFF illumination correction worker - #176

Merged
arjunrajlab merged 5 commits into
masterfrom
codex/stitched-tiff-illumination-correction
Sep 1, 2026
Merged

Restore stitched TIFF illumination correction worker#176
arjunrajlab merged 5 commits into
masterfrom
codex/stitched-tiff-illumination-correction

Conversation

@arjunrajlab

@arjunrajlab arjunrajlab commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • restore the findings-based illumination correction worker as a separately named stitched-TIFF fallback
  • keep automatic held-out model selection across identity, BaSiC, Fourier-domain folded log-gradient, and split-half affine correction
  • register the CPU worker and Docker test service, with full worker documentation and registry entry
  • carry forward review hardening for malformed saved settings, missing frame metadata, guardrail failures, identity fallback, and streamed output
  • pin and test the matching pyvips/libvips runtime required by final TIFF conversion

TDD and review

  • restored the historical tests before the implementation (red: imports/collection failed while the worker was absent)
  • added a production-runtime regression test after the live run exposed a pyvips CFFI initialization failure (red), then pinned pyvips==3.1.1.8.18.2, added build-time/runtime ABI assertions, and serialized libvips concurrency (green)
  • reproduced the first review findings with six failing regressions covering constant-input Spearman rank, identity/Pareto selection, variability-expanded tie margins, incomplete automatic panels, missing candidate warnings, and backward progress
  • fixed automatic selection so a correction must beat identity by more than the fixed 5% margin in aggregate and on every paired held-out plane; removed the uncalibrated independent-normal uncertainty calculation for two or three correlated Z planes
  • mark undefined constant-input Spearman rank unavailable, distinguish unavailable candidates from execution errors, warn when a comparison panel is incomplete, and fail when the identity baseline or every non-identity algorithm fails
  • map nested grid/model callbacks into monotonic global progress phases
  • reproduced the second review findings with two targeted failing tests, then added a third regression for the generalized pre-Pareto masking case
  • treat corrected object-intensity collapse as a preservation failure when the raw object intensities vary; only a constant raw baseline makes the rank guardrail unavailable
  • apply identity eligibility to every correction before Pareto reduction and the simplicity tie-break, so an inconsistent candidate cannot mask another eligible correction
  • reproduced the third review finding with a failing erased-object regression, then generalized it to zero, negative, and sub-10-object cases
  • define the P2 preservation cohort from raw-positive objects, retain nonpositive corrected sums in rank evaluation, and reject any nonzero erased-object fraction even when rank correlation is unavailable
  • audited all worker preservation filters for corrected-outcome survivor bias; no other instances were found
  • bump worker provenance to 1.0.3

Validation

  • ./build_workers.sh --build-and-run-tests stitched_illumination_correction — 48 passed, including real BaSiC fits, the production pyvips/libvips runtime check, candidate-masking regressions, and erased-object preservation regressions
  • git diff --check origin/master...HEAD
  • docker compose config --quiet
  • production image labels verified, including isGPUWorker=false and workerVersion=1.0.3
  • end-to-end run via .agents/skills/nimbus-run-worker/scripts/run_worker.py on dataset view 6a6de7c89be9076cdae3ef17
    • processed all 40 frames and uploaded a new 3.73 GB pyramidal TIFF
    • output: 6556×6542, 6 pyramid levels, 5 channels, 8 Z planes, 40 frames, preserved uint16
    • physical pixel size and magnification match the source
    • fresh-page browser inspection confirmed the output loads and broad grid/quadrant shading is reduced on corrected channels
    • this live run established the image-processing and upload path before the final conservative-selection hardening; the final selection behavior is covered by the Docker regressions above

Algorithm clarification

The stitched worker's Folded log-gradient method uses an FFT/Fourier-domain periodic Poisson solve. It is not the overlap-DCT method. The separate raw-ND2 Stitch Refinement + Illumination Correction worker uses order-5 overlap-DCT because it still has access to independent raw-tile overlaps.

Source

The recovered implementation is based on codex/findings-based-illumination-correction (155a53a), renamed and isolated so it can coexist with the raw-ND2 stitch-refinement worker.

@arjunrajlab

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T11:54:41.275451Z 05213b3 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: c726d2d3ea

ℹ️ 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".

Comment on lines +1184 to +1187
return {
"P2_n_objects": int(keep.sum()),
"P2_spearman": float(spearmanr(raw_sum[keep], corrected_sum[keep]).statistic),
"P2_applicable": True,

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 Treat undefined object ranks as an unavailable guardrail

When a plane contains at least ten measurable objects with identical summed intensities, spearmanr(raw_sum, corrected_sum) returns NaN, but this branch still reports P2_applicable=True. check_guardrails() consequently treats the non-finite result as a hard violation, so every candidate—including the identity model—can be rejected and an otherwise valid correction job fails. Check that both rank inputs have variation, and mark P2 inapplicable when the correlation is undefined.

Useful? React with 👍 / 👎.

@arjunrajlab

Copy link
Copy Markdown
Collaborator Author

Addressed in 4b64215 using TDD. Constant object-intensity inputs now mark the Spearman guardrail unavailable instead of rejecting identity. I generalized the issue across automatic selection: added a direct conservative identity gate, removed the uncalibrated independent-normal uncertainty calculation, surfaced incomplete candidate panels, and fail safely when identity or all correction algorithms fail. Nested progress callbacks now map into monotonic global phases.

Branch-wide audit found no other Spearman consumers, uncertainty-expanded tie calculations, or unscoped progress callbacks. The worker Docker suite passes all 42 tests.

@codex review

@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: 4b642158e2

ℹ️ 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".

Comment on lines +1186 to +1188
if np.ptp(raw_values) <= np.finfo(float).eps or np.ptp(
corrected_values
) <= np.finfo(float).eps:

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 Reject corrections that collapse object intensities

Unlike the previously reported constant-raw case, when raw object sums vary but a correction collapses all corrected sums to one value, the new corrected_values arm marks P2 inapplicable. check_guardrails() then skips the Spearman guardrail, allowing a candidate that erased every object-intensity distinction to remain valid and potentially win; only constant raw values should make preservation unassessable, while constant corrected values with variable raw input should be a violation.

Useful? React with 👍 / 👎.

Comment on lines +1598 to +1601
consistent = _consistently_improves(
selected, identity, use_spot_uniformity
)
if aggregate_improvement <= base_margin or not consistent:

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 Apply the identity gate before choosing among tied corrections

When multiple Pareto corrections are within the 5% tie margin, the simpler candidate is selected before paired consistency is checked. If that simpler candidate regresses one held-out plane, this branch immediately falls back to identity even when another tied candidate improves identity strongly and consistently on every plane, so Automatic mode can discard a correction that satisfies its documented displacement rule; filter candidates through the identity gate before tie-breaking or retry the remaining tied candidates.

Useful? React with 👍 / 👎.

@arjunrajlab

Copy link
Copy Markdown
Collaborator Author

Addressed both new findings in d3a1ad5 with TDD.

  • Constant corrected object sums with variable raw sums are now treated as destructive rank collapse, while only a constant raw baseline makes the guardrail unavailable.
  • Identity eligibility is now applied before Pareto selection and simplicity tie-breaking, so an inconsistent model cannot mask a consistent eligible alternative.

I also generalized the audit across the branch and added regressions for both tie-stage and Pareto-stage masking. All 45 Docker tests pass.

@codex review

@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: d3a1ad5647

ℹ️ 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".

corrected_sum = ndimage.sum_labels(
corrected.astype(np.float64), labels, indices
)
keep = (raw_sum > 0) & (corrected_sum > 0)

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 Reject candidates that erase measured objects

When a correction makes enough previously positive object sums zero or negative, this filter removes those objects; if fewer than ten remain, the next branch marks P2 unavailable. On a large mosaic, erasing a small object can remain below P5's 1e-4 pixel-fraction threshold, so the candidate can pass every hard guardrail despite destroying biological signal. The new d3a1ad5 constant-collapse check does not cover this case because this early return bypasses it; keep raw-positive objects in the rank calculation and treat nonpositive corrected sums as a preservation failure. This also contradicts the worker documentation's claim that only a constant raw baseline makes this guardrail unavailable.

AGENTS.md reference: AGENTS.md:L49-L57

Useful? React with 👍 / 👎.

@arjunrajlab

Copy link
Copy Markdown
Collaborator Author

Addressed the P1 finding in 05213b3 with TDD.

P2 now defines its preservation cohort from raw-positive objects and no longer filters objects based on corrected positivity. Zero or negative corrected object sums are retained and reported through a zero-tolerance erased-object guardrail, including when too few objects exist to calculate Spearman rank.

I searched all worker preservation metrics for the same corrected-outcome survivor-bias pattern. This was the only instance; it is fixed, with regressions for zero, negative, and sub-10-object cases. All 48 Docker tests pass, and worker provenance is now 1.0.3.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 05213b306b

ℹ️ 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".

@arjunrajlab
arjunrajlab merged commit 4e2506f into master Sep 1, 2026
1 check 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.

1 participant