Repository navigation
CP-3: notebook, docs, installers and code standards for v0.2.0 - #71
Merged
Merged
Conversation
…aseline Tooling only, no behaviour change (design v0.4 §9): - tools/code_rules.py: an identical copy of preprocessing's shared file (SHA-256 cc04a420..., checked by tests/test_code_rules.py, as there); - tools/check.py: preprocessing's, plus Ruff's findings counted per file, function and rule against the same shrink-only baseline, since CellPatcher adopts the standards with existing debt; --rules for CI; - tools/code_rules_baseline.json: today's debt (577 entries, noqa 0); - pyproject.toml: tool settings only (Ruff with preprocessing's rule set, the code-rules owner, package and layers); setup.py still builds; - tests/guard_fixtures: preprocessing's deliberately bad modules; - CI: a rules job; Ruff pinned (0.17.3) in the test extra. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
A mechanical move, so the image refusal of the next commit sits beside it in the pure axes module: refuse_transposed_mask_axes and MASK_TRANSPOSE_HELP move verbatim from cellpatcher.io to cellpatcher.axes; pipeline and delivery import them from there. No caller outside CellPatcher (MorphoRelate, MorphoEmbed, MorphoFeature, MorphoObjects, fiberfeatures checked). Baseline lowered: pipeline.py 1031 -> 1030 lines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Design v0.4 §6 asks for a canonical-only layout for in-memory arrays (CP-2b review follow-up). run_patching and lazy delivery accepted common.image_axes='XY' (or 'CXY', 'XYZ'): a 12 x 20 array then gave the whole-FOV patch y0..y1 = 0..20, x0..x1 = 0..12, the coordinates of the transposed image. Now refused with the swapaxes fix (axes.refuse_transposed_image_axes); run_patching checks images and masks with one call (axes.refuse_transposed_inputs), so it shrinks by one line. Regression tests: 13 of the new tests fail on main (12 run_patching cases, one lazy delivery); the mask test now declares the image 'YX'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
rc2 (44971bc) refuses a mask whose header puts X before Y in the run itself; with rc1 the run was written with no axes for that mask and the file run refused the record. test_a_mask_file_whose_header_names_x_before_y now checks the preprocessing run's refusal. The normalization pin (v0.3.2) is the one rc2 pins, unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Since preprocessing v0.4.0rc2 RunInputs.open refuses an experiment holding images or masks the run did not record (UnrecordedFilesError). CellPatcher now reports that as its own issue, unrecorded_files, naming the files and saying that no image is ever left out; a run with OME-Zarr images opened without zarr is zarr_extra_missing, naming cellpatcher[zarr]. Every other refusal keeps preprocessing_run_refused. Nothing is caught and continued. This closes the CP-2a known limitation: an image added after the run was not patched and nothing said so. Docs and CHANGELOG now state the refusal. Regression tests (tests/test_unrecorded_files.py): an added image in a tree and a folder run, an added mask, validate_image_and_mask_folders, the zarr refusal and an rc1 mask record without axes. Against main's source (with rc2 installed) 4 of the 6 fail: the codes were preprocessing_run_refused. test_normalization's added-image test now expects the refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Since preprocessing v0.4.0rc2 `check` writes experiment_design.csv prefilled from the folders, and `run` then stops (design_not_confirmed) until its repeat groups are confirmed, so `check` then `run`, the advice of no_preprocessing_run, no longer works. It now names the new `design` command between them (verified with the rc2 CLI), or the notebook. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
The notebook was broken on main: it imported the removed pair_masks, read_ngff_mask and normalization.cached_statistics, asked for image axes and a mask source, and held a 2,357-line app class inline (0.8 MB of saved widget state). Rewritten like preprocessing's notebook (PR #118): - The user gives the preprocessing run's output folder and, only for a moved or copied experiment, where it and its masks folder are now; every file is read through RunInputs. No axis, label or pairing question. - The cells only call the package (AGENTS.md): cellpatcher.notebook_session (orchestration: summarize_run, preview_image, scan_object_sizes, export_patches_of_run, no widgets) and cellpatcher.notebook_ui / notebook_form (ui: the pages, with preprocessing's notebook_style). The preview is the file-run code on one image, so it gives the patches the export gives (tested); the export is the tree run, combined table. - LabConstrictor portability: "# @title" first on every code cell, Colab code (Drive mount, custom widget manager, zarr extra) only inside if "google.colab" in sys.modules:, pip via subprocess, no magics and no /content outside the guard, one RELEASE_TAG (v0.2.0rc1) for the GitHub install (no GITHUB_TOKEN: the repository is public), current_version and notebook_name with the notebook_latest_versions.yaml entry, Colab and JupyterLab callouts, data and outputs on Drive. - Refusals (unrecorded_files, a changed file, a missing design) are shown with their code, files and action; the step stops there. - Version 0.2.0rc1 (setup.py, __version__, the notebook). - file_runs._read_mask is now public read_run_mask (the object scan reads masks through the run as the patching does). Tests: test_notebook_file.py (portability rules, pin, version index, buttons named in the text, the cells run, and a headless nbclient run in a local kernel), test_notebook_session.py, test_notebook_ui.py. The UI tests skip without the notebook extra. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
- construct.yaml (LabConstrictor installer): its extra_files lacked every module added since CP-1 (file_runs, run_open, run_reading, run_session, run_delivery, run_config_file) and the new notebook modules, so the installed app could not import cellpatcher. Regenerated with .tools/python/bump_constructor.py, as the release workflow does; tests/test_installers.py fails a stale list (it fails on main). Its version line stays for the release workflow (bump_version.py reads X.Y.Z there); the installer installs setup.py, which pins preprocessing v0.4.0rc2 and is version 0.2.0rc1. - The test extra adds nbclient, nbformat and ipykernel; CI adds a test,zarr,notebook job so the notebook's tests run there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
- README: files are read through the preprocessing run; the notebook's four steps; the pinned release install (no GITHUB_TOKEN); tools/check.py. - quick_start: a file-run example through common.preprocessing_run. - normalization.md: the workflow and Python example no longer declare image_axes for a tree run (refused since CP-2a); the v0.2 notebook's Normalization card; unrecorded_files and zarr_extra_missing messages. - configuration_reference: in-memory image_axes must put Y before X. - normalization_contract: the rc2 pin. plan.md: v0.2.0 status and the CP-1..CP-3 milestone; mask_source marked removed. - developer_notes and AGENTS.md: tools/check.py and the code standards, the notebook's structure and portability rules, the release checklist, tools/ in the layout, today's test counts. - CHANGELOG (0.2.0rc1): the notebook, the image refusal, the installers, the code standards, and migration notes for MorphoRelate (check_image_axes, read_patch_table versions), MorphoEmbed (PatchTorchDataset paths) and fiberfeatures (patch_config.json mask_source/mask_label_name). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
guijacquemet
marked this pull request as ready for review
November 2, 2026 10:14
scan_cell_patch_size and scan_cell_objects took mask_axes='XY' on a square image and reported the transposed mask's sizes (bbox_height its width). They now refuse X-before-Y image and mask axes as run_patching does (design v0.4 §6), and CellSegmentationStrategy refuses X-before-Y mask axes when built. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
The shared noqa ratchet counts only C901, PLR0913, PLR0915 and ANN, so a new "# noqa: F401" hid a new Ruff finding and check.py stayed green. Ruff now runs with --ignore-noqa: every finding goes through the shrink-only baseline. The two findings already suppressed (test_code_rules E402, as in preprocessing; test_pipeline_strategies F401, on main) are recorded; the three unused E402 noqa comments of test_notebook_ui are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Owner decision (2026-11-02): rc releases are pip/Colab only. bump_version.py, which the release workflow runs first, refuses a pre-release version with that reason before it changes any file, so no installer is built; a test checks it (the .tools folder is synced from the LabConstrictor template). The developer notes say so, and record that the installer's package layout (src/cellpatcher/cellpatcher/, which setup.py does not find) must be fixed before the final v0.2.0 installers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
…ng plan docs/plan.md and the CHANGELOG record the owner decisions of 2026-11-02: the other two notebooks and the dropped per-group parameters and normalization histograms come in CP-3b before the v0.2.0rc1 tag; the notebook will embed the preprocessing steps through preprocessing's embedding API only after v0.4.0 is final. Step 1 of the notebook now says plainly to run the preprocessing notebook or command line first (tested). The CHANGELOG no longer says the complete module list made the installed app importable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
… patch is missing The test compared each preview patch with its exported twin, but not that the export has no other patch of the image, nor a normalized run. It now checks both (image-scope normalization: the preview's arrays are the exported files). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
An in-memory image or mask declared with X before Y was accepted by the dataset and refused only when an item was loaded, inside a DataLoader worker. It is refused at construction now, as a file path already is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
RunInputsError is a ValueError, so a file changed after step 1 (refused by RunInputs.read_plane or read_mask during the preview or export) was shown under "Please change the settings". It is now shown as a preprocessing run that cannot be used, with the brick's message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
… the notebook The notebook's relative link to docs/README.md does not open on Colab or from the installed app; it points to the repository's docs now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Contributor
Author
Independent review: merged as
|
| Environment | Passed | Skipped |
|---|---|---|
.[test,zarr], check.py (exit 0) |
1057 | 11 (7 torch, 4 notebook extra) |
.[test], check.py (exit 0) |
1036 | 32 (21 zarr, 7 torch, 4 notebook extra) |
.[test,zarr,notebook], check.py (exit 0) |
1068 | 7 (torch) |
With CPU torch: test_torch_dataset.py, test_delivery.py and test_biological_repeat.py gave 57 passed.
§9 figures
- Files:
notebook_ui.py379 lines,notebook_form.py307,notebook_session.py284,tools/check.py206. - Largest values in new code:
- complexity 5 (
check.main); - parameters 4 (
export_patches_of_run); - executable lines 27 (
run_open._refusal_issue); - statements 20 (
CellPatcherNotebook.__init__).
- complexity 5 (
- Touched pre-existing debt (baselined, not grown):
PatchTorchDataset.__init__: 10 parameters, 46 executable lines;scan_cell_objects: 45 executable lines.
- Ratchet: ratcheted
# noqais 0.ruff --isolated --select C901,PLR0913,PLR0915,ANN,Dis clean on the new modules.
For CP-3b (before tagging v0.2.0rc1)
- The other two notebooks: apply the LabConstrictor treatment to
CellPatcher_PytorchandCellPatcher_Strategy_Examples. - The two dropped notebook views: bring back the per-group parameters table and the before/after normalization histograms, computed in the package.
- Installer layout (pre-existing, must be fixed before the final
v0.2.0installers):- LabConstrictor's
construct.yamlplaces the package atsrc/cellpatcher/cellpatcher/. - There,
setup.py(find_packages(where="src")) finds no package. I reproduced this: the installed app has nocellpatchermodule. - The fix needs the template or
setup.py.
- LabConstrictor's
Not tagged.
Generated by Claude Code
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.
CP-3 of the CellPatcher v0.2.0 plan (design v0.4 §6, §8 and §9 on MorphoFeature
claude/restart-doc), built on CP-1 (#68), CP-2a (#69) and CP-2b (#70). This PR does not tag.v0.2.0rc1is tagged only after the CP-3b follow-up (see "Not in this PR").At the coordinator's request it also re-pins to preprocessing v0.4.0rc2 (
44971bc) and wires in rc2's check for files the run did not record.Commits
Implementation:
d2b8d20Code standards (tooling only):tools/code_rules.pyis an identical copy of preprocessing's shared file (SHA-256cc04a420…, tested; the same as preprocessingmainat6711b48).tools/check.pyand--rules.tools/code_rules_baseline.jsonholds today's debt. It can only shrink, and it has a# noqaratchet.testextra.09d668aMechanical move:refuse_transposed_mask_axesmoves fromiotoaxes.87c696bIn-memory images with X before Y are refused, as masks already are (§6).b357297Pin preprocessingv0.4.0rc2(core andzarrextra).0f08b0drc2's unrecorded-files check is surfaced:unrecorded_filesandzarr_extra_missing.88c539dThe preprocessing command names rc2'sdesignstep.d7b89a9The notebook is rewritten for v0.2.878614fInstallers:construct.yamllists every module; CI and thetestextra run the notebook.1d47a6dDocs, CHANGELOG and migration notes.Independent review (fixes):
10.
a58a5fbThe object scan refuses X-before-Y in-memory axes.scan_cell_patch_sizeandscan_cell_objectsrefuse them, and so doesCellSegmentationStrategy(mask_axes=…). Before this fix, a square mask declaredXYwas measured as if it were transposed: an object 7 high and 3 wide was reported asbbox_height3 andbbox_width7.11.
f26c471A# noqacomment no longer hides a Ruff finding from the baseline.- The shared ratchet counts only C901, PLR0913, PLR0915 and ANN. A new
# noqa: F401therefore hid a new finding, andcheck.pystayed green (shown with a mutation).- Ruff now runs with
--ignore-noqa.- The 2 findings that were already suppressed are now recorded in the baseline, and 3 unused
noqacomments are removed.12.
5cc1c52No installer is built for a release candidate (owner decision 4).-
.tools/python/bump_version.pyrefuses a pre-release version with a clear message, before it changes any file. The release workflow runs it first.- This is tested.
- It is documented in
docs/developer_notes.md.13.
87d9924The CP-3b follow-ups and the embedded-preprocessing plan are recorded indocs/plan.mdand the CHANGELOG ("Not yet").- Step 1 of the notebook now says plainly to run the preprocessing notebook or CLI first (tested).
14.
9f68c59The preview equals the export with normalization (image scope), and the preview has exactly the image's exported patches.15.
ac3606bPatchTorchDatasetrefuses X-before-Y axes when it is built. Before, the refusal came only when an item was loaded, in a DataLoader worker. Tested with CPU torch.16.
bb51001A file refused while it is read (RunInputsErrorduring the preview or export) is shown as a refused run, not as "Please change the settings".17.
e45b823CHANGELOG updated for these fixes; the notebook's docs link is now absolute (the relative one does not open on Colab).18.
706accfHealth snapshot.Behaviour changes
notebooks/CellPatcher/CellPatcher.ipynb):RunInputs.cellpatcher.notebook_session(orchestration),notebook_uiandnotebook_form(ui). The old notebook's 2,357-line inline class and 0.8 MB of widget state are gone.# @title Run to …starts every cell, and the code is hidden./contentappears only in the guard.RELEASE_TAG = "v0.2.0rc1", and noGITHUB_TOKEN.common.image_axeswith X before Y (XY,CXY,XYZ) is refused by:run_patching;PatchTorchDataset;unrecorded_files.zarr_extra_missing.preprocessing_run_refused.no_preprocessing_runnamescheck→design --confirm …→run(checked against rc2'scli_design.py).construct.yamllists every module, andtest_installers.pykeeps it complete.setup.pyand__version__are 0.2.0rc1.Not in this PR (owner decisions, 2026-11-02)
CP-3b, a follow-up PR before tagging
v0.2.0rc1:CellPatcher_Pytorch.ipynbandCellPatcher_Strategy_Examples.ipynbget the same LabConstrictor treatment. They still use the oldGITHUB_TOKENinstall ofmain.Before the final
v0.2.0installers:construct.yamlcopies the package toCellPatcher/src/cellpatcher/cellpatcher/.setup.py(find_packages(where="src")) finds no package, so the installed app has nocellpatcher.construct.yamllists them and pip-installing them.setup.pybefore the final installers.After preprocessing v0.4.0 is final:
PreprocessingNotebookandnotebook_style, pinned by itstests/test_embedding_api.py.Accepted debt: Ruff findings are kept in the shrink-only baseline;
ruff formatis not enforced yet.Gate (Python 3.11, uv venvs, preprocessing
v0.4.0rc2, head706accf).[test,zarr],tools/check.py(exit 0).[test],tools/check.py(exit 0).[test,zarr,notebook],tools/check.py(exit 0; includes the nbclient kernel run)torchadded,test_torch_dataset.py,test_delivery.pyandtest_biological_repeat.pypassed: 57 tests.tools/check.py --rulesis clean. Ratcheted# noqa: 0.§9 figures (measured on the new and rewritten code)
notebook_ui.py379 lines,notebook_form.py307,notebook_session.py284,tools/check.py206.check.main);export_patches_of_run);run_open._refusal_issue);CellPatcherNotebook.__init__).PatchTorchDataset.__init__: 10 parameters, 46 executable lines;scan_cell_objects: 45 executable lines, 6 parameters.ruff --isolated --select C901,PLR0913,PLR0915,ANN,D(NumPy convention) passes on the new modules. Every module declares its layer.Colab hand-check list (after tagging
v0.2.0rc1, since the notebook installs that tag)/content/drive. pip installscellpatcher[notebook,zarr] @ …@v0.2.0rc1(with preprocessing rc2). The ready card shows0.2.0rc1..tifgives a red[unrecorded_files]card.patches.csv,images.csvandrun_config.jsonon Drive.zarr_extra_missing.https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Generated by Claude Code