Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1099,10 +1099,11 @@ jupyter lab notebooks/MorphoBricks_Preprocessing.ipynb

---

## 11. Status (current state, v0.5.3)
## 11. Status (current state, v0.5.4)

- **Released:** v0.5.3 (13 November 2026), with the normalization brick pinned at v0.6.0 (v0.5.2,
12 November 2026, pinned it at v0.5.0). The
- **Released:** v0.5.4 (14 November 2026): the RGB header override (Spec RH1) and mask-only
requests on RGB units; the normalization brick stays pinned at v0.6.0 (since v0.5.3,
13 November 2026; v0.5.2, 12 November 2026, pinned it at v0.5.0). The
per-release history is in [CHANGELOG.md](CHANGELOG.md); the milestones PP-0 to PP-13 are in
[docs/archive/plan-milestones-v0.1-v0.4.md](docs/archive/plan-milestones-v0.1-v0.4.md); the older
status log of this file is in
Expand Down
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ The design is `docs/restart/preprocessing-design-v0.4.md` in MorphoFeature, on b
are in [docs/plan.md](docs/plan.md) §12. (The v0.3 to v0.4 migration guide was removed in
v0.5.1: no run before v0.5.1 is read.)

## Unreleased
## v0.5.4 (14 November 2026)

RGB scanner input: the RGB header override of Spec amendment RH1, and mask-only requests on RGB
units (Fixed, below). The normalization pin stays at v0.6.0. Run manifest version 5,
`plane_histograms.csv` schema version 5, resolver contract version 2 and conversion record
version 4 are those of v0.5.3; the manifest's new unit keys are additive (only units declared
`rgb` carry them), and a v0.5.3 run is read as it is. The Spec pin moves to `b635b7d` (Changed).

### Added

Expand Down Expand Up @@ -45,6 +51,15 @@ v0.5.1: no run before v0.5.1 is read.)
- **Spec re-pinned to `b635b7d`** (Spec PR #37, RH1 merged; `v40`, `i140`, `i141`, `t14`,
`t15` now vendored): notebook drafts saved under `69a58b3` are not carried over.

### Fixed

- **A mask-only request on an RGB unit was refused** (`A_RGB_NOT_SUPPORTED`) unless the consumer
declared `rgb_support`, so a brick's mask-only features (MorphoObjects shapes, MorphoRelate
relations and skeletons) could not run on an RGB slide (#298). Spec `experiment-v1.md` section 8
refuses only a request that includes the channels of an RGB unit; the resolver now counts only
the RGB images whose channels the request names. Naming one of `R`, `G`, `B` without
`rgb_support` is still refused. Owner decision of 14 November 2026: no new capability value.

## v0.5.3 (13 November 2026)

A pin release: normalization is pinned at v0.6.0, so that every core package (and CellPatcher,
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ from there.

## Status

Pre-alpha; the current release is v0.5.3 (what is planned next is in
Pre-alpha; the current release is v0.5.4 (what is planned next is in
[docs/roadmap.md](docs/roadmap.md)). Implemented and tested:

- Folder discovery and validation, TIFF and OME-Zarr header inspection without reading pixels
Expand Down Expand Up @@ -61,7 +61,7 @@ converted. See the [CHANGELOG](CHANGELOG.md).
## Installation

```bash
pip install "git+https://github.com/CellMigrationLab/morphobricks-preprocessing.git@v0.5.3"
pip install "git+https://github.com/CellMigrationLab/morphobricks-preprocessing.git@v0.5.4"
```

For development, from a clone:
Expand All @@ -71,7 +71,7 @@ pip install -e ".[dev]"
```

The optional `notebook` extra installs the widget dependencies for the notebook
(`pip install "morphobricks-preprocessing[notebook] @ git+https://github.com/CellMigrationLab/morphobricks-preprocessing.git@v0.5.3"`).
(`pip install "morphobricks-preprocessing[notebook] @ git+https://github.com/CellMigrationLab/morphobricks-preprocessing.git@v0.5.4"`).
The notebook's first code cell (**1. Install**) can set this up automatically: it uses a compatible nearby
checkout or installed package, and installs missing requirements into the active kernel. A standalone
download installs from GitHub if needed (internet access and Git required).
Expand Down Expand Up @@ -228,7 +228,7 @@ ruff format .
pytest
```

Coding conventions are described in [docs/development.md](docs/development.md). Planned work after v0.5.3 is in [docs/roadmap.md](docs/roadmap.md).
Coding conventions are described in [docs/development.md](docs/development.md). Planned work after v0.5.4 is in [docs/roadmap.md](docs/roadmap.md).

## License

Expand Down
4 changes: 2 additions & 2 deletions docs/colab-release-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Write the date, the commit and any failure (as an issue number) next to each ite
- **Time-lapse:** a small experiment of time-lapse images (optional; the tests cover it).

**Before opening it.** `RELEASE_REF` in cell 1 is the release preparation commit, and cell 3's
`PreprocessingNotebook(...)` call is that commit's API (v0.5.3: `PreprocessingNotebook()`). The
`PreprocessingNotebook(...)` call is that commit's API (v0.5.4: `PreprocessingNotebook()`). The
release PR moves `RELEASE_REF` and records the pair in `RELEASE_CALLS` of
`tests/test_notebook_file.py`, which fails for a `RELEASE_REF` without one.

Expand All @@ -30,7 +30,7 @@ release PR moves `RELEASE_REF` and records the pair in `RELEASE_CALLS` of
- [ ] One line: "… run cell 1 (Install MorphoBricks preprocessing) first …", no traceback;
nothing is installed.
3. Run **cell 1**.
- [ ] It prints **Ready** with the preprocessing (0.5.3), normalization (0.6.0) and
- [ ] It prints **Ready** with the preprocessing (0.5.4), normalization (0.6.0) and
ipywidgets versions and the pinned source, then names cells 2 and 3. No restart or
ipywidgets upgrade is asked for; Drive is not mounted.
- [ ] Run it again: nothing is installed again, the same versions.
Expand Down
23 changes: 23 additions & 0 deletions docs/conformance.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,29 @@ real run; a skip is never counted as a pass. Owner rulings of 8 November 2026 (i
"no skips" applies to the Spec conformance modules (`tests/test_spec_*.py`); a skip elsewhere
in the suite is listed as **not run**, with its reason.

## Release record: v0.5.4 (14 November 2026)

A G1-style record of the v0.5.4 release candidate (as for v0.5.3 below): the RGB header override
(Spec amendment RH1, #295) and mask-only requests on RGB units (#298). Normalization stays at
v0.6.0. It does not decide a gate; deciding a gate is the owner's.

| | |
|---|---|
| Release candidate | Measured on the tree of the v0.5.4 preparation commit (commit A of branch `claude/release-0.5.4`, from `main` at `052668e`: v0.5.3, #295 and #298) before this record was added; the record changes only this file. A keeps `RELEASE_REF` at v0.5.3's `14f6b1a`. Commit B then points the notebook's `RELEASE_REF` at A and records the pair in `RELEASE_CALLS` (the notebook and two test files only), so `git diff A B -- src pyproject.toml` is empty: the installed package is the one `RELEASE_REF` names |
| Spec pin | `tests/spec_fixtures/PIN.toml`: MorphoBricks-Spec `b635b7d5bc950529bce9dcc5681cec34b75139b8` (RH1 merged; was `69a58b3` in v0.5.3), checked by `test_spec_pin` (16 passed) |
| Environment | Linux, Python 3.13.18, the package from this tree (`PYTHONPATH=src` over an editable install of the same checkout) with `[dev,notebook,zarr]` (normalization 0.6.0 from its tag `v0.6.0` = `95e1d6d`, as pip's `direct_url.json` records; scikit-image not installed; numpy 2.5.4, tifffile 2026.11.12, ipywidgets 8.1.9, zarr 3.4.2, pytest 9.2.0); run as root on a case-sensitive file system |
| Commands | `python tools/check.py` (Ruff, Ruff format, pytest over `tests/`, code rules); `python -m pytest -q -p no:cacheprovider -rsxX tests/test_spec_*.py` |
| `tools/check.py` | Ruff clean, Ruff format 465 files already formatted, pytest **5600 passed, 4 skipped** (not run, below), 0 failed, code rules passed (exit status 0) |
| Spec modules (`tests/test_spec_*.py`) | **1839 passed, 0 skipped, 0 xfailed, 0 failed**, from all 25 modules of `tests/spec_gate.py` `EXPECTED_MODULES` (40 more than v0.5.3: the RH1 cases `v40`, `i140`, `i141`, `t14`, `t15` of the re-pinned Spec) |

**Not run (4 environment skips, outside the Spec modules):** the four of v0.5.3 below
(`tests/test_cli_log.py:166`, `tests/test_folder_rules.py:199` and `:230`: the file system is
case-sensitive; `tests/test_discovery.py:665`: run as root). These four behaviours are **not
verified by this run**.

**Still the owner's:** the Colab and JupyterLab browser check (`docs/colab-release-check.md`),
before tagging.

## Release record: v0.5.3 (13 November 2026)

A G1-style record of the v0.5.3 release candidate (as for v0.5.2 below), a pin release:
Expand Down
6 changes: 3 additions & 3 deletions notebooks/MorphoBricks_Preprocessing.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@
"from pathlib import Path\n",
"\n",
"# LabConstrictor version identifiers.\n",
"current_version = \"0.5.3\"\n",
"current_version = \"0.5.4\"\n",
"notebook_name = \"MorphoBricks_Preprocessing\"\n",
"\n",
"# A downloaded/Colab notebook installs this immutable source revision.\n",
"RELEASE_TAG = \"v0.5.3\"\n",
"RELEASE_REF = \"14f6b1a0e37474d38f3dd54138bbfdcce69d6e9a\"\n",
"RELEASE_TAG = \"v0.5.4\"\n",
"RELEASE_REF = \"05d763a1a0af2436957b860579a2c0636d3929de\"\n",
"REPOSITORY = \"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/CellMigrationLab/morphobricks-preprocessing.git\"\n",
"EXTRAS = \"notebook\"\n",
"\n",
Expand Down
2 changes: 1 addition & 1 deletion notebooks/notebook_latest_versions.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Latest version of each notebook, read by LabConstrictor's version check by notebook_name.
# Equal to the notebook's current_version and its RELEASE_TAG without the "v" (README, "Notebook").
"MorphoBricks_Preprocessing": "0.5.3"
"MorphoBricks_Preprocessing": "0.5.4"
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "morphobricks-preprocessing"
version = "0.5.3"
version = "0.5.4"
description = "MorphoBricks preprocessing brick: per-plane intensity histograms and normalization methods for microscopy TIFFs."
readme = "README.md"
license = "MIT"
Expand Down
2 changes: 2 additions & 0 deletions tests/test_notebook_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ def test_notebook_uses_stable_page_api_not_a_new_app_method():
"cadbed4bb049995b2385e3b8499c8d247d3754bd": "PreprocessingNotebook()",
# v0.5.3: the same call.
"14f6b1a0e37474d38f3dd54138bbfdcce69d6e9a": "PreprocessingNotebook()",
# v0.5.4: the same call.
"05d763a1a0af2436957b860579a2c0636d3929de": "PreprocessingNotebook()",
}
CHECKOUT_CALL = "PreprocessingNotebook()"
"""The call of this checkout's code (every run described, no ``describe`` argument)."""
Expand Down
20 changes: 10 additions & 10 deletions tests/test_notebook_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def setup_environment(tmp_path, monkeypatch):
drive=tmp_path / "content/drive",
namespace={},
versions={
"morphobricks-preprocessing": "0.5.3",
"morphobricks-preprocessing": "0.5.4",
"morphobricks-normalization": "0.6.0",
"ipywidgets": "7.7.1",
},
Expand All @@ -131,7 +131,7 @@ def install(command, *, check):
assert check is True
state.installs.append(command)
state.available.update({*REQUIRED, ZARR})
state.versions["morphobricks-preprocessing"] = "0.5.3"
state.versions["morphobricks-preprocessing"] = "0.5.4"

monkeypatch.setattr(subprocess, "run", install)

Expand Down Expand Up @@ -163,7 +163,7 @@ def checkout_at(path):
package.mkdir(parents=True)
(package / "__init__.py").write_text("", encoding="utf-8")
(path / "pyproject.toml").write_text(
'[project]\nname = "morphobricks-preprocessing"\nversion = "0.5.3"\n',
'[project]\nname = "morphobricks-preprocessing"\nversion = "0.5.4"\n',
encoding="utf-8",
)
return path
Expand All @@ -179,7 +179,7 @@ def test_setup_reuses_the_matching_installed_release(setup_environment, capsys):
"morphobricks_preprocessing.notebook_ui", # cell 3 shows it
]
out = capsys.readouterr().out
assert "Ready: preprocessing 0.5.3" in out
assert "Ready: preprocessing 0.5.4" in out
assert "ipywidgets 7.7.1" in out


Expand All @@ -193,8 +193,8 @@ def test_setup_installs_missing_package_from_the_exact_commit(setup_environment,
target = command[5]
assert target.startswith("morphobricks-preprocessing[notebook] @ git+")
assert target.endswith("@" + namespace["RELEASE_REF"])
assert namespace["RELEASE_REF"] == "14f6b1a0e37474d38f3dd54138bbfdcce69d6e9a"
assert "pinned v0.5.3 candidate" in capsys.readouterr().out
assert namespace["RELEASE_REF"] == "05d763a1a0af2436957b860579a2c0636d3929de"
assert "pinned v0.5.4 candidate" in capsys.readouterr().out


def test_setup_replaces_a_mismatched_installed_release(setup_environment):
Expand Down Expand Up @@ -285,7 +285,7 @@ def test_an_explicit_development_override_uses_the_checkout_and_says_so(
assert sys.path[0] == str(checkout / "src")
assert f"commit {OTHER_COMMIT}, uncommitted changes" in out
assert "DEVELOPMENT OVERRIDE is on" in out
assert "DEVELOPMENT OVERRIDE on" in out.split("Notebook 0.5.3")[1]
assert "DEVELOPMENT OVERRIDE on" in out.split("Notebook 0.5.4")[1]
record = namespace["SETUP_RECORD"]
assert record["checkout_commit"] == OTHER_COMMIT
assert record["checkout_has_uncommitted_changes"] is True
Expand Down Expand Up @@ -428,7 +428,7 @@ def test_cell_1_installs_without_mounting_drive_or_showing_the_app(
assert state.apps == []
assert namespace["SETUP_RECORD"]["release_ref"] == RELEASE_REF
out = capsys.readouterr().out
assert "Ready: preprocessing 0.5.3; normalization 0.6.0; ipywidgets 7.7.1." in out
assert "Ready: preprocessing 0.5.4; normalization 0.6.0; ipywidgets 7.7.1." in out
assert "Next: run cell 2 (Mount Google Drive), then cell 3 (Run preprocessing)." in out


Expand All @@ -444,8 +444,8 @@ def test_running_cell_1_again_installs_nothing_more(setup_environment, capsys):
assert len(state.installs) == 1
assert "Installing notebook requirements" in first
assert "Installing notebook requirements" not in again
assert "Ready: preprocessing 0.5.3" in again
assert state.namespace["SETUP_RECORD"]["preprocessing_version"] == "0.5.3"
assert "Ready: preprocessing 0.5.4" in again
assert state.namespace["SETUP_RECORD"]["preprocessing_version"] == "0.5.4"
assert record["release_ref"] == state.namespace["SETUP_RECORD"]["release_ref"]


Expand Down
Loading