Repository navigation
Masks: pair every image with its masks and describe how they relate (plan §12 Q29) - #26
Merged
Merged
Conversation
Masks of any number of types are paired with the images: a masks folder outside the experiment, one subfolder per mask type mirroring the experiment's folders, plus the label images of OME-Zarr images. `check` and `run` check them from their headers only (2D, the image's Y and X, integer or boolean pixels) and a run records them in the manifest's optional `masks` key. The optional mask step (`masks` command, `scan_masks`) reads the pixels one image at a time and writes mask_relationships.json: each type's kind (instances, grouped, one_value, empty), each ordered pair's relation (same_objects, grouped_by, inside, none) with the counts behind it, such as parents with 0, 1, 2 and 3+ children, and the hierarchy of direct parents (nucleoli inside nuclei inside cells). SciPy becomes a core dependency for counting pieces. Contract §13, plan Q29, user guide. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6vJfhGWQ7pTpsJhw48Zf7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6vJfhGWQ7pTpsJhw48Zf7
The seven thresholds become defaults (DEFAULT_THRESHOLDS): scan_masks and pair_counts take thresholds=, the masks command one option each (--inside-object-share 0.8, ...). mask_thresholds checks them before any mask is read (shares and IoU in (0, 1], median pieces >= 1), and the values used are written in the report and printed. The owner confirmed 2D masks at the image's YX, integer/bool pixels and the masks folder outside the experiment; plan Q29 records it, with the v0.2.0 tag proposal and the next steps (notebook step, saved answers). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6vJfhGWQ7pTpsJhw48Zf7
MorphoFeature's end-to-end trial on MorphoRelate's JUMP-Target-2 conversion found masks written as <image>_<type>.tif beside the images' folders. The masks folder may now mirror the experiment with the type after the image name, as well as one folder per type; both layouts may be mixed. A file that could name two images (one image name starting another's) or fit both layouts is the error ambiguous_mask, never guessed. On the four JUMP smoke fields both layouts give the same report. Contract §8 and §13, user guide §2 and §8, plan Q29, AGENTS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6vJfhGWQ7pTpsJhw48Zf7
Contributor
Author
|
@IvanHCenalmor, one more commit on this PR, at the owner's request: Why. MorphoFeature ran the whole pipeline end to end on MorphoRelate's JUMP-Target-2 Cell Painting conversion: 4 fields; preprocessing, then the 4 bricks, then MorphoCoverage. That conversion writes masks as What.
Checked.
Generated by Claude Code |
…a9rxd1 # Conflicts: # AGENTS.md # README.md # docs/contract.md # docs/plan.md # docs/user_guide.md # src/morphobricks_preprocessing/cli.py # src/morphobricks_preprocessing/manifest.py # src/morphobricks_preprocessing/run.py
PR #27 (folder step without the experiment design) takes question 31, and goes in first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bricks that measure objects (MorphoObjects, MorphoRelate, CellPatcher, MorphoFeature workflows) need each image paired with its masks, and need to know how the mask types relate: two nuclei in one cell, nucleoli inside nuclei inside cells, mitochondria labelled with their cell's number. Today each brick asks the user again. This PR lets the preprocessing brick find the masks, check them and suggest the relationships, for any number of mask types (MorphoFeature decision D78). The user then only has to name the masks and confirm.
By module:
masks.py(new).find_maskspairs every image with its masks:position_id, ignoring case and extension. OME-Zarr label images also count as masks.mask_missing,mask_without_image,mask_outside_type_folder.MaskInventory(for_image,to_manifest) andread_mask.mask_scan.py(new). The optional mask step.scan_masksreads the masks one image at a time and returns aMaskReport:instances,grouped,one_valueorempty.same_objects,grouped_by,insideornone.DEFAULT_THRESHOLDScan be changed withthresholds=.mask_thresholdschecks the values before any mask is read, and the values used are written in the report.write_mask_reportwritesmask_relationships.jsonatomically.piece_countsandpair_countsare public.run.py:preflight(..., masks_folder=, ome_zarr_labels=)andrun_experiment(...)with the same arguments. A mask error stops the run.manifest.py: an optionalmaskskey. It is absent without masks, and the manifest stays version 1.plane_histograms.csvnever depends on the masks.cli.py:--masks FOLDERoncheckandrun;maskscommand: it prints the kinds, the relationships, the hierarchy tree and the thresholds used, then writes the report;masks, e.g.--inside-object-share 0.8,--same-objects-iou 0.7.report.py: plain-language summaries (mask_summary,mask_report_summary).pyproject.toml:scipy>=1.10becomes a core dependency.Decisions
Recorded in plan §12 Q29 and the AGENTS decisions log. Taken with the MorphoBricks owner (@guijacquemet):
thresholds=, on the command line with one option each. They are checked, then written in the report.checkandrunread headers only. Reading the pixels is an optional step (maskscommand,scan_masks).maskskey in the manifest, plusmask_relationships.json.scipy.ndimage.Notes for review
experiment_design.csvdoes for repeats.ome_zarr_labels=Trueuses them even without a folder; themaskscommand always does.masksprinted the hierarchycells > mito, nuclei: nuclei inside cells, and mitochondria grouped by cell with a median of 41 pieces per label.Tests
ruff check .andruff format --check .: clean.pytest(Python 3.11, zarr 3): 969 passed, 1 skipped (main: 936 passed, 1 skipped). 33 new tests, intests/test_masks.pyandtests/test_mask_scan.py. Pieces are checked against an independent breadth-first-search reference on 50 random masks.case_conflicttest.🤖 Generated with Claude Code
https://claude.ai/code/session_01U6vJfhGWQ7pTpsJhw48Zf7