From 9a4fffe0ec12e95df9285156072b4be627ff7476 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 20:54:22 +0000 Subject: [PATCH 1/2] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/biomejs/pre-commit: v2.5.3 → v2.6.3](https://github.com/biomejs/pre-commit/compare/v2.5.3...v2.6.3) - [github.com/tox-dev/pyproject-fmt: v2.25.3 → v2.30.3](https://github.com/tox-dev/pyproject-fmt/compare/v2.25.3...v2.30.3) - [github.com/astral-sh/ruff-pre-commit: v0.15.21 → v0.17.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.21...v0.17.2) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9320c3a..6cc9931 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,16 +7,16 @@ default_stages: minimum_pre_commit_version: 2.16.0 repos: - repo: https://github.com/biomejs/pre-commit - rev: v2.5.3 + rev: v2.6.3 hooks: - id: biome-format exclude: ^\.cruft\.json$ # inconsistent indentation with cruft - file never to be modified manually. - repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.25.3 + rev: v2.30.3 hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.21 + rev: v0.17.2 hooks: - id: ruff-check types_or: [python, pyi, jupyter] From c259b041cb0cc6178224cd8a3112b35d66e2c53e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 20:54:35 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .codecov.yaml | 22 +-- .github/ISSUE_TEMPLATE/bug_report.yml | 168 +++++++++---------- .github/ISSUE_TEMPLATE/config.yml | 6 +- .github/ISSUE_TEMPLATE/feature_request.yml | 14 +- .github/workflows/build.yaml | 44 ++--- .github/workflows/release.yaml | 48 +++--- .github/workflows/test.yaml | 184 ++++++++++----------- .pre-commit-config.yaml | 66 ++++---- .readthedocs.yaml | 26 +-- AGENTS.md | 24 +-- CHANGELOG.md | 24 +++ README.md | 12 +- REVIEW_GUIDE.md | 28 ++-- docs/contributing.md | 2 +- pyproject.toml | 3 +- 15 files changed, 347 insertions(+), 324 deletions(-) diff --git a/.codecov.yaml b/.codecov.yaml index d0c0e29..829e56c 100644 --- a/.codecov.yaml +++ b/.codecov.yaml @@ -1,17 +1,17 @@ # Based on pydata/xarray codecov: - require_ci_to_pass: no + require_ci_to_pass: no coverage: - status: - project: - default: - # Require 1% coverage, i.e., always succeed - target: 1 - patch: false - changes: false + status: + project: + default: + # Require 1% coverage, i.e., always succeed + target: 1 + patch: false + changes: false comment: - layout: diff, flags, files - behavior: once - require_base: no + layout: diff, flags, files + behavior: once + require_base: no diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c91d8e9..c6247a8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -2,93 +2,93 @@ name: Bug report description: Report something that is broken or incorrect type: Bug body: - - type: markdown - attributes: - value: | - **Note**: Please read [this guide](https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports) - detailing how to provide the necessary information for us to reproduce your bug. In brief: - * Please provide exact steps how to reproduce the bug in a clean Python environment. - * In case it's not clear what's causing this bug, please provide the data or the data generation procedure. - * Sometimes it is not possible to share the data, but usually it is possible to replicate problems on publicly - available datasets or to share a subset of your data. + - type: markdown + attributes: + value: | + **Note**: Please read [this guide](https://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports) + detailing how to provide the necessary information for us to reproduce your bug. In brief: + * Please provide exact steps how to reproduce the bug in a clean Python environment. + * In case it's not clear what's causing this bug, please provide the data or the data generation procedure. + * Sometimes it is not possible to share the data, but usually it is possible to replicate problems on publicly + available datasets or to share a subset of your data. - - type: textarea - id: report - attributes: - label: Report - description: A clear and concise description of what the bug is. - validations: - required: true + - type: textarea + id: report + attributes: + label: Report + description: A clear and concise description of what the bug is. + validations: + required: true - - type: textarea - id: versions - attributes: - label: Versions - description: | - Which version of packages. + - type: textarea + id: versions + attributes: + label: Versions + description: | + Which version of packages. - Please install `session-info2`, run the following command in a notebook, - click the “Copy as Markdown” button, then paste the results into the text box below. + Please install `session-info2`, run the following command in a notebook, + click the “Copy as Markdown” button, then paste the results into the text box below. - ```python - In[1]: import session_info2; session_info2.session_info(dependencies=True) - ``` + ```python + In[1]: import session_info2; session_info2.session_info(dependencies=True) + ``` - Alternatively, run this in a console: + Alternatively, run this in a console: - ```python - >>> import session_info2; print(session_info2.session_info(dependencies=True)._repr_mimebundle_()["text/markdown"]) - ``` - render: python - placeholder: | - anndata 0.11.3 - ---- ---- - charset-normalizer 3.4.1 - coverage 7.7.0 - psutil 7.0.0 - dask 2024.7.1 - jaraco.context 5.3.0 - numcodecs 0.15.1 - jaraco.functools 4.0.1 - Jinja2 3.1.6 - sphinxcontrib-jsmath 1.0.1 - sphinxcontrib-htmlhelp 2.1.0 - toolz 1.0.0 - session-info2 0.1.2 - PyYAML 6.0.2 - llvmlite 0.44.0 - scipy 1.15.2 - pandas 2.2.3 - sphinxcontrib-devhelp 2.0.0 - h5py 3.13.0 - tblib 3.0.0 - setuptools-scm 8.2.0 - more-itertools 10.3.0 - msgpack 1.1.0 - sparse 0.15.5 - wrapt 1.17.2 - jaraco.collections 5.1.0 - numba 0.61.0 - pyarrow 19.0.1 - pytz 2025.1 - MarkupSafe 3.0.2 - crc32c 2.7.1 - sphinxcontrib-qthelp 2.0.0 - sphinxcontrib-serializinghtml 2.0.0 - zarr 2.18.4 - asciitree 0.3.3 - six 1.17.0 - sphinxcontrib-applehelp 2.0.0 - numpy 2.1.3 - cloudpickle 3.1.1 - sphinxcontrib-bibtex 2.6.3 - natsort 8.4.0 - jaraco.text 3.12.1 - setuptools 76.1.0 - Deprecated 1.2.18 - packaging 24.2 - python-dateutil 2.9.0.post0 - ---- ---- - Python 3.13.2 | packaged by conda-forge | (main, Feb 17 2025, 14:10:22) [GCC 13.3.0] - OS Linux-6.11.0-109019-tuxedo-x86_64-with-glibc2.39 - Updated 2025-03-18 15:47 + ```python + >>> import session_info2; print(session_info2.session_info(dependencies=True)._repr_mimebundle_()["text/markdown"]) + ``` + render: python + placeholder: | + anndata 0.11.3 + ---- ---- + charset-normalizer 3.4.1 + coverage 7.7.0 + psutil 7.0.0 + dask 2024.7.1 + jaraco.context 5.3.0 + numcodecs 0.15.1 + jaraco.functools 4.0.1 + Jinja2 3.1.6 + sphinxcontrib-jsmath 1.0.1 + sphinxcontrib-htmlhelp 2.1.0 + toolz 1.0.0 + session-info2 0.1.2 + PyYAML 6.0.2 + llvmlite 0.44.0 + scipy 1.15.2 + pandas 2.2.3 + sphinxcontrib-devhelp 2.0.0 + h5py 3.13.0 + tblib 3.0.0 + setuptools-scm 8.2.0 + more-itertools 10.3.0 + msgpack 1.1.0 + sparse 0.15.5 + wrapt 1.17.2 + jaraco.collections 5.1.0 + numba 0.61.0 + pyarrow 19.0.1 + pytz 2025.1 + MarkupSafe 3.0.2 + crc32c 2.7.1 + sphinxcontrib-qthelp 2.0.0 + sphinxcontrib-serializinghtml 2.0.0 + zarr 2.18.4 + asciitree 0.3.3 + six 1.17.0 + sphinxcontrib-applehelp 2.0.0 + numpy 2.1.3 + cloudpickle 3.1.1 + sphinxcontrib-bibtex 2.6.3 + natsort 8.4.0 + jaraco.text 3.12.1 + setuptools 76.1.0 + Deprecated 1.2.18 + packaging 24.2 + python-dateutil 2.9.0.post0 + ---- ---- + Python 3.13.2 | packaged by conda-forge | (main, Feb 17 2025, 14:10:22) [GCC 13.3.0] + OS Linux-6.11.0-109019-tuxedo-x86_64-with-glibc2.39 + Updated 2025-03-18 15:47 diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 5b62547..5cad625 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - - name: Scverse Community Forum - url: https://discourse.scverse.org/ - about: If you have questions about “How to do X”, please ask them here. + - name: Scverse Community Forum + url: https://discourse.scverse.org/ + about: If you have questions about “How to do X”, please ask them here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 10d9311..ac66eec 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -2,10 +2,10 @@ name: Feature request description: Propose a new feature for cellmapper type: Enhancement body: - - type: textarea - id: description - attributes: - label: Description of feature - description: Please describe your suggestion for a new feature. It might help to describe a problem or use case, plus any alternatives that you have considered. - validations: - required: true + - type: textarea + id: description + attributes: + label: Description of feature + description: Please describe your suggestion for a new feature. It might help to describe a problem or use case, plus any alternatives that you have considered. + validations: + required: true diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index fd4e8bd..4518678 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,31 +1,31 @@ name: Check Build on: - push: - branches: [main] - pull_request: - branches: [main] + push: + branches: [main] + pull_request: + branches: [main] concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true defaults: - run: - # to fail on error in multiline statements (-e), in pipes (-o pipefail), and on unset variables (-u). - shell: bash -euo pipefail {0} + run: + # to fail on error in multiline statements (-e), in pipes (-o pipefail), and on unset variables (-u). + shell: bash -euo pipefail {0} jobs: - package: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - with: - filter: blob:none - fetch-depth: 0 - - name: Install uv - uses: astral-sh/setup-uv@v7 - - name: Build package - run: uv build - - name: Check package - run: uvx twine check --strict dist/*.whl + package: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + filter: blob:none + fetch-depth: 0 + - name: Install uv + uses: astral-sh/setup-uv@v7 + - name: Build package + run: uv build + - name: Check package + run: uvx twine check --strict dist/*.whl diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c3fff3d..7499363 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,32 +1,32 @@ name: Release on: - release: - types: [published] + release: + types: [published] defaults: - run: - # to fail on error in multiline statements (-e), in pipes (-o pipefail), and on unset variables (-u). - shell: bash -euo pipefail {0} + run: + # to fail on error in multiline statements (-e), in pipes (-o pipefail), and on unset variables (-u). + shell: bash -euo pipefail {0} # Use "trusted publishing", see https://docs.pypi.org/trusted-publishers/ jobs: - release: - name: Upload release to PyPI - runs-on: ubuntu-latest - environment: - name: pypi - url: https://pypi.org/p/cellmapper - permissions: - id-token: write # IMPORTANT: this permission is mandatory for trusted publishing - steps: - - uses: actions/checkout@v5 - with: - filter: blob:none - fetch-depth: 0 - - name: Install uv - uses: astral-sh/setup-uv@v7 - - name: Build package - run: uv build - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + release: + name: Upload release to PyPI + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/cellmapper + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + steps: + - uses: actions/checkout@v5 + with: + filter: blob:none + fetch-depth: 0 + - name: Install uv + uses: astral-sh/setup-uv@v7 + - name: Build package + run: uv build + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index dd63a68..7fb754e 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,106 +1,106 @@ name: Test on: - push: - branches: [main] - pull_request: - branches: [main] - schedule: - - cron: "0 5 1,15 * *" + push: + branches: [main] + pull_request: + branches: [main] + schedule: + - cron: "0 5 1,15 * *" concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true defaults: - run: - # to fail on error in multiline statements (-e), in pipes (-o pipefail), and on unset variables (-u). - shell: bash -euo pipefail {0} + run: + # to fail on error in multiline statements (-e), in pipes (-o pipefail), and on unset variables (-u). + shell: bash -euo pipefail {0} jobs: - # Get the test environment from hatch as defined in pyproject.toml. - # This ensures that the pyproject.toml is the single point of truth for test definitions and the same tests are - # run locally and on continuous integration. - # Check [[tool.hatch.envs.hatch-test.matrix]] in pyproject.toml and https://hatch.pypa.io/latest/environment/ for - # more details. - get-environments: - runs-on: ubuntu-latest - outputs: - envs: ${{ steps.get-envs.outputs.envs }} - steps: - - uses: actions/checkout@v5 - with: - filter: blob:none - fetch-depth: 0 - - name: Install uv - uses: astral-sh/setup-uv@v7 - - name: Get test environments - id: get-envs - run: | - ENVS_JSON=$(uvx hatch env show --json | jq -c 'to_entries - | map( - select(.key | startswith("hatch-test")) - | { - name: .key, - label: (if (.key | contains("pre")) then .key + " (PRE-RELEASE DEPENDENCIES)" else .key end), - python: .value.python - } - )') - echo "envs=${ENVS_JSON}" | tee $GITHUB_OUTPUT + # Get the test environment from hatch as defined in pyproject.toml. + # This ensures that the pyproject.toml is the single point of truth for test definitions and the same tests are + # run locally and on continuous integration. + # Check [[tool.hatch.envs.hatch-test.matrix]] in pyproject.toml and https://hatch.pypa.io/latest/environment/ for + # more details. + get-environments: + runs-on: ubuntu-latest + outputs: + envs: ${{ steps.get-envs.outputs.envs }} + steps: + - uses: actions/checkout@v5 + with: + filter: blob:none + fetch-depth: 0 + - name: Install uv + uses: astral-sh/setup-uv@v7 + - name: Get test environments + id: get-envs + run: | + ENVS_JSON=$(uvx hatch env show --json | jq -c 'to_entries + | map( + select(.key | startswith("hatch-test")) + | { + name: .key, + label: (if (.key | contains("pre")) then .key + " (PRE-RELEASE DEPENDENCIES)" else .key end), + python: .value.python + } + )') + echo "envs=${ENVS_JSON}" | tee $GITHUB_OUTPUT - # Run tests through hatch. Spawns a separate runner for each environment defined in the hatch matrix obtained above. - test: - needs: get-environments + # Run tests through hatch. Spawns a separate runner for each environment defined in the hatch matrix obtained above. + test: + needs: get-environments - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - env: ${{ fromJSON(needs.get-environments.outputs.envs) }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + env: ${{ fromJSON(needs.get-environments.outputs.envs) }} - name: ${{ matrix.env.label }} - runs-on: ${{ matrix.os }} - # Allow pre-release tests to fail without blocking the PR (dependency compatibility issues) - continue-on-error: ${{ contains(matrix.env.name, 'pre') }} + name: ${{ matrix.env.label }} + runs-on: ${{ matrix.os }} + # Allow pre-release tests to fail without blocking the PR (dependency compatibility issues) + continue-on-error: ${{ contains(matrix.env.name, 'pre') }} - steps: - - uses: actions/checkout@v5 - with: - filter: blob:none - fetch-depth: 0 - - name: Install uv - uses: astral-sh/setup-uv@v7 - with: - python-version: ${{ matrix.env.python }} - - name: create hatch environment - run: uvx hatch env create ${{ matrix.env.name }} - - name: run tests using hatch - env: - MPLBACKEND: agg - PLATFORM: ${{ matrix.os }} - DISPLAY: :42 - run: uvx hatch run ${{ matrix.env.name }}:run-cov -v --color=yes -n auto - - name: generate coverage report - run: | - # See https://coverage.readthedocs.io/en/latest/config.html#run-patch - test -f .coverage || uvx hatch run ${{ matrix.env.name }}:cov-combine - uvx hatch run ${{ matrix.env.name }}:cov-report # report visibly - uvx hatch run ${{ matrix.env.name }}:coverage xml # create report for upload - - name: Upload coverage - uses: codecov/codecov-action@v5 - with: - token: ${{ secrets.CODECOV_TOKEN }} + steps: + - uses: actions/checkout@v5 + with: + filter: blob:none + fetch-depth: 0 + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + python-version: ${{ matrix.env.python }} + - name: create hatch environment + run: uvx hatch env create ${{ matrix.env.name }} + - name: run tests using hatch + env: + MPLBACKEND: agg + PLATFORM: ${{ matrix.os }} + DISPLAY: :42 + run: uvx hatch run ${{ matrix.env.name }}:run-cov -v --color=yes -n auto + - name: generate coverage report + run: | + # See https://coverage.readthedocs.io/en/latest/config.html#run-patch + test -f .coverage || uvx hatch run ${{ matrix.env.name }}:cov-combine + uvx hatch run ${{ matrix.env.name }}:cov-report # report visibly + uvx hatch run ${{ matrix.env.name }}:coverage xml # create report for upload + - name: Upload coverage + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} - # Check that all tests defined above pass. This makes it easy to set a single "required" test in branch - # protection instead of having to update it frequently. See https://github.com/re-actors/alls-green#why. - check: - name: Tests pass in all hatch environments - if: always() - needs: - - get-environments - - test - runs-on: ubuntu-latest - steps: - - uses: re-actors/alls-green@release/v1 - with: - jobs: ${{ toJSON(needs) }} + # Check that all tests defined above pass. This makes it easy to set a single "required" test in branch + # protection instead of having to update it frequently. See https://github.com/re-actors/alls-green#why. + check: + name: Tests pass in all hatch environments + if: always() + needs: + - get-environments + - test + runs-on: ubuntu-latest + steps: + - uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6cc9931..cc2a617 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,38 +1,38 @@ fail_fast: false default_language_version: - python: python3 + python: python3 default_stages: - - pre-commit - - pre-push + - pre-commit + - pre-push minimum_pre_commit_version: 2.16.0 repos: - - repo: https://github.com/biomejs/pre-commit - rev: v2.6.3 - hooks: - - id: biome-format - exclude: ^\.cruft\.json$ # inconsistent indentation with cruft - file never to be modified manually. - - repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.30.3 - hooks: - - id: pyproject-fmt - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.17.2 - hooks: - - id: ruff-check - types_or: [python, pyi, jupyter] - args: [--fix, --exit-non-zero-on-fix] - - id: ruff-format - types_or: [python, pyi, jupyter] - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 - hooks: - - id: detect-private-key - - id: check-ast - - id: end-of-file-fixer - - id: mixed-line-ending - args: [--fix=lf] - - id: trailing-whitespace - - id: check-case-conflict - # Check that there are no merge conflicts (could be generated by template sync) - - id: check-merge-conflict - args: [--assume-in-merge] + - repo: https://github.com/biomejs/pre-commit + rev: v2.6.3 + hooks: + - id: biome-format + exclude: ^\.cruft\.json$ # inconsistent indentation with cruft - file never to be modified manually. + - repo: https://github.com/tox-dev/pyproject-fmt + rev: v2.30.3 + hooks: + - id: pyproject-fmt + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.17.2 + hooks: + - id: ruff-check + types_or: [python, pyi, jupyter] + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format + types_or: [python, pyi, jupyter] + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: detect-private-key + - id: check-ast + - id: end-of-file-fixer + - id: mixed-line-ending + args: [--fix=lf] + - id: trailing-whitespace + - id: check-case-conflict + # Check that there are no merge conflicts (could be generated by template sync) + - id: check-merge-conflict + args: [--assume-in-merge] diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 6c28477..7f029f3 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,16 +1,16 @@ # https://docs.readthedocs.io/en/stable/config-file/v2.html version: 2 build: - os: ubuntu-24.04 - tools: - python: "3.13" - nodejs: latest - jobs: - create_environment: - - asdf plugin add uv - - asdf install uv latest - - asdf global uv latest - build: - html: - - uvx hatch run docs:build - - mv docs/_build $READTHEDOCS_OUTPUT + os: ubuntu-24.04 + tools: + python: "3.13" + nodejs: latest + jobs: + create_environment: + - asdf plugin add uv + - asdf install uv latest + - asdf global uv latest + build: + html: + - uvx hatch run docs:build + - mv docs/_build $READTHEDOCS_OUTPUT diff --git a/AGENTS.md b/AGENTS.md index e54c53a..ab934a8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,18 +23,18 @@ table below — everything else is delegated. ## Where To Find What -| Topic | Source of truth | -|-------|----------------| -| User-facing overview, use cases, quickstart | `README.md` | -| Public API reference | `docs/api.md` and autosummary under `docs/generated/` | -| Tutorials (query→reference, spatial mapping, spatial smoothing, data denoising) | `docs/notebooks/tutorials/` | -| Contributor setup, environments, docs build | `docs/contributing.md` | -| Release notes | `docs/changelog.md` | -| PR review workflow and risk areas | `REVIEW_GUIDE.md` | -| Test fixtures | `tests/conftest.py`, `tests/data/` | -| Kernel taxonomy and tunable thresholds (sklearn warning cutoff, spectral threshold) | `src/cellmapper/constants.py` | -| Optional-dependency gating | `src/cellmapper/check.py` | -| Method-level behavior (parameters, return shapes) | docstrings in `src/cellmapper/model/` | +| Topic | Source of truth | +| ----------------------------------------------------------------------------------- | ----------------------------------------------------- | +| User-facing overview, use cases, quickstart | `README.md` | +| Public API reference | `docs/api.md` and autosummary under `docs/generated/` | +| Tutorials (query→reference, spatial mapping, spatial smoothing, data denoising) | `docs/notebooks/tutorials/` | +| Contributor setup, environments, docs build | `docs/contributing.md` | +| Release notes | `docs/changelog.md` | +| PR review workflow and risk areas | `REVIEW_GUIDE.md` | +| Test fixtures | `tests/conftest.py`, `tests/data/` | +| Kernel taxonomy and tunable thresholds (sklearn warning cutoff, spectral threshold) | `src/cellmapper/constants.py` | +| Optional-dependency gating | `src/cellmapper/check.py` | +| Method-level behavior (parameters, return shapes) | docstrings in `src/cellmapper/model/` | ## Review Guidelines diff --git a/CHANGELOG.md b/CHANGELOG.md index ab592b7..3370642 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,26 +11,31 @@ and this project adheres to [Semantic Versioning][]. ## [Unreleased] ### Changed + - Dropped Python 3.11 support; the minimum supported version is now Python 3.12, aligning with `cellrank` (≥2.1 requires Python ≥3.12) and unpinning the `tutorials` extra from the old `cellrank` 2.0.7 {pr}`81` - The `gpcca-fast` dependency group now delegates `petsc4py`/`slepc4py` to `cellrank[petsc]>=2.3.1` (mpi4py-free) instead of hardcoding them, keeping only an explicit `slepc` to work around slepc4py's missing runtime metadata {pr}`82` ### Fixed + - Fixed intermittent `OSError: Can't synchronously read data (filter returned failure during read)` when running the test suite under `pytest -n auto`, caused by xdist workers racing on scanpy's shared `pbmc3k_raw.h5ad` dataset cache. Each worker now uses its own cache directory. ## [v0.2.5] ### Added + - Added `batch_size` parameter to `Kernel.compute_neighbors()` for backend-agnostic batching {pr}`60` - Added `subset` parameter to `plot_confusion_matrix()` for filtering cells {pr}`60` - Added Python 3.14 support {pr}`62` ### Changed + - Default postfixes now include underscore: `"_pred"` and `"_conf"` instead of `"pred"` and `"conf"` {pr}`60` - Switched from MathJax to KaTeX for documentation math rendering {pr}`61` - Updated GitHub Actions to latest versions (checkout v5, setup-uv v7) {pr}`61` - Updated test matrix to Python 3.11/3.14 {pr}`62` ### Fixed + - Fixed `PackageNotFoundError` when checking rapids availability in conda environments {pr}`60` - Fixed stale k-NN state when `compute_neighbors()` fails {pr}`60` - Fixed `plot_confusion_matrix()` handling of NaN values in both y_true and y_pred {pr}`60` @@ -41,34 +46,44 @@ and this project adheres to [Semantic Versioning][]. ## [v0.2.4] ### Changed + - Deprecated Python 3.10 support {pr}`55` - Updated to cookiecutter-scverse template v0.6.0 {pr}`54` ## [v0.2.3] ### Changed + - Improved returning probabilities (after mapping categorical obs fields) to always return a DataFrame {pr}`49` ### Added + - Add the possibility to adjust the library size after `.map_layers` {pr}`50` - Added the option to turn off post-processing of the presence scores, so that they can be first smoothed and then processed, like in HNOCA-tools {pr}`51` ## [v0.2.2] + ### Added + - Enabled subsetting categories before mapping .obs values {pr}`46` ### Changed + - Updated the README a bit {pr}`44` - Updated tutorials to work with new parameter names {pr}`43` ### Fixed + - Fixed a small bug where hvg masks would not be propagated correctly to joint pca computation {pr}`48` ## [v0.2.1] + ### Changed + - Move some duplicated docstrings into a central _docs.py file {pr}`41` ### Added + - Added some tests for edge cases in the `MappingOperator` class {pr}`41` - Treat faiss-cpu and faiss-gpu separately {pr}`41` @@ -76,6 +91,7 @@ and this project adheres to [Semantic Versioning][]. ## [v0.2.0] ### Added + - Added a tutorial on same-modality query to reference mapping {pr}`38` - Added a tutorial on data smoothing {pr}`37` - Added an option to return the mapping probabilities for categorical `.obs` mapping {pr}`39` @@ -83,17 +99,21 @@ and this project adheres to [Semantic Versioning][]. - Add the `umap` method to compute symmetric k-NN connectivities in self-mapping mode {pr}`34` ### Changed + - Refectored the neighbors classes into a `Neighobrs` and a `Kernel` class and moved symmetrization into the `Kernel` class {pr}`36` ## [v0.1.4] + ### Changed + - Rename mapping methods to `map_obs`, `map_obsm`, and `map_layers`, and improve support for numerical `.obs` annotations {pr}`30`. ## [v0.1.3] ### Added + - Added a tutorial on spatial contextualization and niche identification {pr}`23`. - Implemented a self-mapping mode with only a query dataset {pr}`21`. - Allow importing a pre-computed dataset of transfered expression values {pr}`21`. @@ -104,6 +124,7 @@ and this project adheres to [Semantic Versioning][]. ## [v0.1.2] ### Added + - Included tests for the `check` module, and more tests for the main classes {pr}`15`. - Implemented the computation of presence scores, following HNOCA-tools {pr}`16`. - Added a `groupby` parameter to expression transfer evaluation {pr}`16`. @@ -113,10 +134,13 @@ and this project adheres to [Semantic Versioning][]. ## [v0.1.1] ### Changed + - Switched to `vcs`-based versioning {pr}`5`. ### Added + - Added PyPI badge. ## [v0.1.0] + Initial package release. diff --git a/README.md b/README.md index 10534f6..908e2b7 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ The core idea of `CellMapper` is to separate the method (k-NN graph with some ke You need to have 🐍 Python 3.12 or newer installed on your system. If you don't have Python installed, we recommend installing [uv][]. -There are two alternative options to install ``cellmapper``: +There are two alternative options to install `cellmapper`: - 🚀 Install the latest release from [PyPI][]: @@ -51,9 +51,9 @@ There are two alternative options to install ``cellmapper``: ## 🏁 Getting started -This package assumes that you have ``query`` and ``reference`` AnnData objects, with a joint embedding computed and stored in ``.obsm``. While we implement some baseline approaches to compute joint embeddings (PCA and a fast reimplementation of CCA), we typically expect you to provide a pre-computed joint embedding from some task-specific representation learning tools, e.g. [GimVI][] or [ENVI][] for spatial mapping, [GLUE][], [MIDAS][] and [MOFA+][] for modality translation, and [scVI][], [scANVI][] and [scArches][] for query-to-reference mapping - this is just a small selection! +This package assumes that you have `query` and `reference` AnnData objects, with a joint embedding computed and stored in `.obsm`. While we implement some baseline approaches to compute joint embeddings (PCA and a fast reimplementation of CCA), we typically expect you to provide a pre-computed joint embedding from some task-specific representation learning tools, e.g. [GimVI][] or [ENVI][] for spatial mapping, [GLUE][], [MIDAS][] and [MOFA+][] for modality translation, and [scVI][], [scANVI][] and [scArches][] for query-to-reference mapping - this is just a small selection! -With a joint embedding in ``.obsm["X_joint"]`` at hand, the simplest way to use ``CellMapper`` is as follows: +With a joint embedding in `.obsm["X_joint"]` at hand, the simplest way to use `CellMapper` is as follows: ```Python from cellmapper import CellMapper @@ -62,7 +62,7 @@ cmap = CellMapper(query, reference).map( ) ``` -This will transfer data from the reference to the query dataset, including celltype labels stored in ``reference.obs``, a UMAP embedding stored in ``reference.obsm``, and expression values stored in ``reference.X``. +This will transfer data from the reference to the query dataset, including celltype labels stored in `reference.obs`, a UMAP embedding stored in `reference.obsm`, and expression values stored in `reference.X`. There are many ways to customize this, e.g. use different ways to compute k-NN graphs and to turn them into mapping matrices, and we implement a few methods to evaluate whether your k-NN transfer was sucessful. The tool also implements a `self-mapping` mode (only a query object, no reference), which is useful for spatial contextualization and data denoising. Check out the 📚 [docs][] to learn more. @@ -75,6 +75,7 @@ See the [changelog][]. If you found a bug, please use the [issue tracker][]. ## 📖 Citation + Please use our [zenodo][] entry to cite this software. [uv]: https://github.com/astral-sh/uv @@ -89,15 +90,12 @@ Please use our [zenodo][] entry to cite this software. [pypi]: https://pypi.org/project/cellmapper/ [downloads]: https://pepy.tech/project/cellmapper [zenodo]: https://doi.org/10.5281/zenodo.15683594 - [faiss]: https://github.com/facebookresearch/faiss [pynndescent]: https://github.com/lmcinnes/pynndescent [sklearn]: https://scikit-learn.org/stable/modules/neighbors.html [rapids]: https://docs.rapids.ai/api/cuml/stable/api/#nearest-neighbors - [ingest]: https://scanpy.readthedocs.io/en/stable/generated/scanpy.tl.ingest.html [HNOCA-tools]: https://devsystemslab.github.io/HNOCA-tools/ - [GimVI]: https://docs.scvi-tools.org/en/stable/api/reference/scvi.external.GIMVI.html# [ENVI]: https://scenvi.readthedocs.io/en/latest/# [GLUE]: https://scglue.readthedocs.io/en/latest/ diff --git a/REVIEW_GUIDE.md b/REVIEW_GUIDE.md index c9267f2..b8372b7 100644 --- a/REVIEW_GUIDE.md +++ b/REVIEW_GUIDE.md @@ -29,25 +29,25 @@ Pointers only — see `AGENTS.md` for the actual invariants. Tests mirror the source tree. -| Changed path | Primary tests | -|--------------|---------------| -| `src/cellmapper/model/cellmapper.py` | `tests/model/test_query_to_reference_mapping.py`, `tests/model/test_self_mapping.py` | -| `src/cellmapper/model/kernel.py` | `tests/model/test_kernel.py` | -| `src/cellmapper/model/mapping_operator.py` | `tests/model/test_mapping_operator.py` | -| `src/cellmapper/model/neighbors.py` | `tests/model/test_neighbors.py` | -| `src/cellmapper/model/embedding.py` | `tests/model/test_embedding.py` | -| `src/cellmapper/model/evaluate.py` | `tests/model/test_evaluate.py` | -| `src/cellmapper/model/_knn_backend.py` | `tests/model/test_neighbors.py`, `tests/model/test_kernel.py` | -| `src/cellmapper/check.py` | `tests/test_check.py` | -| `src/cellmapper/utils.py` | `tests/test_utils.py` | -| End-to-end behavioral change | also `tests/test_basic.py` | -| Fixture changes | `tests/conftest.py`, `tests/data/` | +| Changed path | Primary tests | +| ------------------------------------------ | ------------------------------------------------------------------------------------ | +| `src/cellmapper/model/cellmapper.py` | `tests/model/test_query_to_reference_mapping.py`, `tests/model/test_self_mapping.py` | +| `src/cellmapper/model/kernel.py` | `tests/model/test_kernel.py` | +| `src/cellmapper/model/mapping_operator.py` | `tests/model/test_mapping_operator.py` | +| `src/cellmapper/model/neighbors.py` | `tests/model/test_neighbors.py` | +| `src/cellmapper/model/embedding.py` | `tests/model/test_embedding.py` | +| `src/cellmapper/model/evaluate.py` | `tests/model/test_evaluate.py` | +| `src/cellmapper/model/_knn_backend.py` | `tests/model/test_neighbors.py`, `tests/model/test_kernel.py` | +| `src/cellmapper/check.py` | `tests/test_check.py` | +| `src/cellmapper/utils.py` | `tests/test_utils.py` | +| End-to-end behavioral change | also `tests/test_basic.py` | +| Fixture changes | `tests/conftest.py`, `tests/data/` | ## Testing - **New code** should be covered. Reuse fixtures from `tests/conftest.py`; prefer `pytest.mark.parametrize`; favor few meaningful tests over many redundant ones. - **Failing CI** is not to be waved through. Distinguish critical regressions from flakes; escalate critical ones. -- **Modified tests** — scrutinize *how*. Relaxed tolerances, removed assertions, deleted cases, or loosened matrices are red flags. Require explicit justification in the PR body. +- **Modified tests** — scrutinize _how_. Relaxed tolerances, removed assertions, deleted cases, or loosened matrices are red flags. Require explicit justification in the PR body. ## Documentation Impact diff --git a/docs/contributing.md b/docs/contributing.md index 6455f44..3610ebf 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -11,7 +11,7 @@ the [scientific Python tutorials][], or the [scanpy developer guide][]. [scientific Python tutorials]: https://learn.scientific-python.org/development/tutorials/ [scanpy developer guide]: https://scanpy.readthedocs.io/en/latest/dev/index.html -:::{tip} The *hatch* project manager +:::{tip} The _hatch_ project manager We highly recommend to familiarize yourself with [`hatch`][hatch]. Hatch is a Python project manager that diff --git a/pyproject.toml b/pyproject.toml index 78ed1f6..65f0fab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", ] dynamic = [ "version" ] dependencies = [ @@ -209,11 +210,11 @@ strict = true testpaths = [ "tests" ] [tool.coverage] +run.source = [ "cellmapper" ] run.omit = [ "**/test_*.py", ] run.patch = [ "subprocess" ] -run.source = [ "cellmapper" ] [tool.cruft] skip = [