napari-spatialdata 0.6.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.github/workflows/benchmarks.yml +8 -8
  2. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.github/workflows/benchmarks_report.yml +3 -3
  3. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.github/workflows/release.yml +2 -2
  4. napari_spatialdata-0.7.0/.github/workflows/test.yml +72 -0
  5. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.gitignore +1 -0
  6. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.pre-commit-config.yaml +6 -6
  7. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.readthedocs.yaml +1 -1
  8. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/PKG-INFO +11 -11
  9. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/asv.conf.json +1 -1
  10. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/benchmarks/benchmark.txt +1 -1
  11. napari_spatialdata-0.7.0/docs/contributing.md +25 -0
  12. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/setup.cfg +10 -10
  13. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_scatterwidgets.py +42 -3
  14. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_version.py +3 -3
  15. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_viewer.py +18 -13
  16. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_widgets.py +17 -3
  17. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/constants/config.py +2 -0
  18. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/utils/_utils.py +7 -2
  19. napari_spatialdata-0.7.0/src/napari_spatialdata/utils/_viewer_utils.py +37 -0
  20. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata.egg-info/PKG-INFO +11 -11
  21. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata.egg-info/SOURCES.txt +1 -1
  22. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata.egg-info/requires.txt +8 -8
  23. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/conftest.py +79 -7
  24. napari_spatialdata-0.7.0/tests/test_3d_visualization.py +161 -0
  25. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/test_scatterwidgets.py +3 -2
  26. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/test_spatialdata.py +2 -0
  27. napari_spatialdata-0.6.0/.github/workflows/test.yml +0 -147
  28. napari_spatialdata-0.6.0/docs/contributing.md +0 -3
  29. napari_spatialdata-0.6.0/src/napari_spatialdata/utils/_viewer_utils.py +0 -18
  30. napari_spatialdata-0.6.0/tests/test_aaa.py +0 -25
  31. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.github/BENCHMARK_FAIL_TEMPLATE.md +0 -0
  32. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.github/dependabot.yml +0 -0
  33. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.github/release.yml +0 -0
  34. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.mypy.ini +0 -0
  35. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/.napari/DESCRIPTION.md +0 -0
  36. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/LICENSE +0 -0
  37. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/MANIFEST.in +0 -0
  38. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/README.md +0 -0
  39. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/benchmarks/Readme.md +0 -0
  40. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/benchmarks/__init__.py +0 -0
  41. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/benchmarks/benchmark.in +0 -0
  42. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/benchmarks/benchmark_model.py +0 -0
  43. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/benchmarks/benchmark_qt_widget.py +0 -0
  44. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/Makefile +0 -0
  45. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/_static/.gitkeep +0 -0
  46. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/_templates/.gitkeep +0 -0
  47. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/_templates/autosummary/class.rst +0 -0
  48. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/api.md +0 -0
  49. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/changelog.md +0 -0
  50. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/cli.md +0 -0
  51. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/conf.py +0 -0
  52. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/extensions/typed_returns.py +0 -0
  53. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/index.md +0 -0
  54. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/limitations.md +0 -0
  55. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/make.bat +0 -0
  56. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/notebooks/mibitof_analysis.ipynb +0 -0
  57. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/notebooks/nanostring_analysis.ipynb +0 -0
  58. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/notebooks/scatterwidget.ipynb +0 -0
  59. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/notebooks/scatterwidget_annotation.ipynb +0 -0
  60. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/notebooks/spatialdata.ipynb +0 -0
  61. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/references.bib +0 -0
  62. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/docs/references.md +0 -0
  63. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/examples/spatialdata_empty.py +0 -0
  64. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/examples/spatialdata_visium.py +0 -0
  65. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/pyproject.toml +0 -0
  66. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/__init__.py +0 -0
  67. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/__main__.py +0 -0
  68. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_annotationwidgets.py +0 -0
  69. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_interactive.py +0 -0
  70. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_model.py +0 -0
  71. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_reader.py +0 -0
  72. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_sdata_widgets.py +0 -0
  73. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/_view.py +0 -0
  74. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/constants/__init__.py +0 -0
  75. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/constants/_constants.py +0 -0
  76. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/constants/_pkg_constants.py +0 -0
  77. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/constants/_utils.py +0 -0
  78. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/napari.yaml +0 -0
  79. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/resources/exclamation.png +0 -0
  80. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/resources/icons8-home-48.png +0 -0
  81. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/resources/icons8-pencil-drawing-50.png +0 -0
  82. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/resources/icons8-polygon-80.png +0 -0
  83. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/resources/icons8-rectangle-48.png +0 -0
  84. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/utils/__init__.py +0 -0
  85. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/utils/_categoricals_utils.py +0 -0
  86. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata/utils/_test_utils.py +0 -0
  87. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata.egg-info/dependency_links.txt +0 -0
  88. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata.egg-info/entry_points.txt +0 -0
  89. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/src/napari_spatialdata.egg-info/top_level.txt +0 -0
  90. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/__init__.py +0 -0
  91. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/plots/groundtruth/Images_can_add_element_image.png +0 -0
  92. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/plots/groundtruth/Images_can_add_element_label.png +0 -0
  93. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/plots/groundtruth/Images_can_add_element_multiple.png +0 -0
  94. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/test_cli.py +0 -0
  95. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/test_interactive.py +0 -0
  96. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/test_utils.py +0 -0
  97. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/test_view.py +0 -0
  98. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/test_viewer.py +0 -0
  99. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tests/test_widgets.py +0 -0
  100. {napari_spatialdata-0.6.0 → napari_spatialdata-0.7.0}/tox.ini +0 -0
@@ -8,8 +8,8 @@ name: Benchmarks
8
8
  on:
9
9
  pull_request:
10
10
  types: [labeled]
11
- schedule:
12
- - cron: "6 6 * * 0" # every sunday
11
+ # schedule:
12
+ # - cron: "6 6 * * 0" # every sunday
13
13
  workflow_dispatch:
14
14
  inputs:
15
15
  base_ref:
@@ -59,11 +59,11 @@ jobs:
59
59
  steps:
60
60
  # We need the full repo to avoid this issue
61
61
  # https://github.com/actions/checkout/issues/23
62
- - uses: actions/checkout@v4
62
+ - uses: actions/checkout@v6
63
63
  with:
64
64
  fetch-depth: 0
65
65
 
66
- - uses: actions/setup-python@v5
66
+ - uses: actions/setup-python@v6
67
67
  name: Install Python
68
68
  with:
69
69
  python-version: "3.11"
@@ -140,7 +140,7 @@ jobs:
140
140
  env:
141
141
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
142
142
  PLATFORM: ${{ matrix.runs-on }}
143
- PYTHON: "3.9"
143
+ PYTHON: "3.11"
144
144
  BACKEND: ${{ matrix.benchmark-name }}
145
145
  RUN_ID: ${{ github.run_id }}
146
146
  TITLE: "[test-bot] Benchmark tests failing"
@@ -170,7 +170,7 @@ jobs:
170
170
 
171
171
  fi
172
172
 
173
- - uses: actions/upload-artifact@v4
173
+ - uses: actions/upload-artifact@v5
174
174
  if: always()
175
175
  with:
176
176
  name: asv-benchmark-results-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}-${{ matrix.benchmark-name }}
@@ -182,13 +182,13 @@ jobs:
182
182
  if: always()
183
183
  steps:
184
184
  - name: Download artifact
185
- uses: actions/download-artifact@v4
185
+ uses: actions/download-artifact@v6
186
186
  with:
187
187
  pattern: asv-benchmark-results*
188
188
  path: asv_result
189
189
  merge-multiple: true
190
190
  - name: Upload artifact
191
- uses: actions/upload-artifact@v4
191
+ uses: actions/upload-artifact@v5
192
192
  with:
193
193
  name: asv-benchmark-results-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
194
194
  path: asv_result
@@ -24,7 +24,7 @@ jobs:
24
24
  runs-on: ubuntu-latest
25
25
  steps:
26
26
  - name: "Download artifact"
27
- uses: actions/github-script@v7
27
+ uses: actions/github-script@v8
28
28
  with:
29
29
  script: |
30
30
  let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
@@ -68,7 +68,7 @@ jobs:
68
68
 
69
69
  - name: "Comment on PR"
70
70
  if: env.PR_NUMBER != ''
71
- uses: actions/github-script@v7
71
+ uses: actions/github-script@v8
72
72
  with:
73
73
  github-token: ${{ secrets.GITHUB_TOKEN }}
74
74
  script: |
@@ -84,7 +84,7 @@ jobs:
84
84
 
85
85
  - name: "Remove run-benchmarks label"
86
86
  if: env.PR_NUMBER != ''
87
- uses: actions/github-script@v7
87
+ uses: actions/github-script@v8
88
88
  with:
89
89
  github-token: ${{ secrets.GITHUB_TOKEN }}
90
90
  script: |
@@ -10,7 +10,7 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
  if: startsWith(github.ref, 'refs/tags/v')
12
12
  steps:
13
- - uses: actions/checkout@v4
13
+ - uses: actions/checkout@v6
14
14
  - uses: hynek/build-and-inspect-python-package@v2
15
15
 
16
16
  upload-to-pypi:
@@ -21,7 +21,7 @@ jobs:
21
21
 
22
22
  steps:
23
23
  - name: Download built artifact to dist/
24
- uses: actions/download-artifact@v4
24
+ uses: actions/download-artifact@v6
25
25
  with:
26
26
  name: Packages
27
27
  path: dist
@@ -0,0 +1,72 @@
1
+ # This workflows will upload a Python Package using Twine when a release is created
2
+ # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
3
+
4
+ name: tests
5
+
6
+ on:
7
+ push:
8
+ branches:
9
+ - main
10
+ - npe2
11
+ tags:
12
+ - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
13
+ pull_request:
14
+ branches:
15
+ - main
16
+ - npe2
17
+ workflow_dispatch:
18
+
19
+ jobs:
20
+ test:
21
+ name: ${{ matrix.platform }} py${{ matrix.python-version }}
22
+ runs-on: ${{ matrix.platform }}
23
+ strategy:
24
+ fail-fast: false
25
+ matrix:
26
+ platform: [ubuntu-latest, macos-latest] # [ubuntu-latest, windows-latest, macos-latest]
27
+ python-version: ["3.11", "3.13"]
28
+
29
+ steps:
30
+ - uses: actions/checkout@v6
31
+
32
+ - name: Set up Python ${{ matrix.python-version }}
33
+ uses: actions/setup-python@v6
34
+ with:
35
+ python-version: ${{ matrix.python-version }}
36
+
37
+ # these libraries enable testing on Qt on linux
38
+ - uses: tlambert03/setup-qt-libs@v1
39
+
40
+ # strategy borrowed from vispy for installing opengl libs on windows
41
+ - name: Install Windows OpenGL
42
+ if: runner.os == 'Windows'
43
+ run: |
44
+ git clone --depth 1 https://github.com/pyvista/gl-ci-helpers.git
45
+ powershell gl-ci-helpers/appveyor/install_opengl.ps1
46
+
47
+ # note: if you need dependencies from conda, considering using
48
+ # setup-miniconda: https://github.com/conda-incubator/setup-miniconda
49
+ # and
50
+ # tox-conda: https://github.com/tox-dev/tox-conda
51
+ - name: Install dependencies
52
+ run: |
53
+ python -m pip install --upgrade pip
54
+ python -m pip install setuptools tox tox-gh-actions
55
+
56
+ # this runs the platform-specific tests declared in tox.ini
57
+ - name: Test with tox
58
+ uses: coactions/setup-xvfb@v1
59
+ with:
60
+ run: python -m tox
61
+ env:
62
+ PLATFORM: ${{ matrix.platform }}
63
+
64
+ - name: Coverage
65
+ uses: codecov/codecov-action@v5
66
+
67
+ - name: Archive figures generated during testing
68
+ if: always()
69
+ uses: actions/upload-artifact@v5
70
+ with:
71
+ name: plotting-results-${{ matrix.python-version }}-${{ matrix.platform }}
72
+ path: /Users/runner/work/napari-spatialdata/napari-spatialdata/tests/plots/generated/*
@@ -117,3 +117,4 @@ tests/plots/generated
117
117
 
118
118
  # Local temp script for testing user bugs (Luca)
119
119
  temp/
120
+ uv.lock
@@ -7,13 +7,13 @@ default_stages:
7
7
  minimum_pre_commit_version: 2.9.3
8
8
  repos:
9
9
  - repo: https://github.com/pre-commit/mirrors-mypy
10
- rev: v1.17.1
10
+ rev: v1.19.1
11
11
  hooks:
12
12
  - id: mypy
13
13
  additional_dependencies: [numpy>=1.23]
14
14
  exclude: docs
15
- - repo: https://github.com/psf/black
16
- rev: 25.1.0
15
+ - repo: https://github.com/psf/black-pre-commit-mirror
16
+ rev: 25.12.0
17
17
  hooks:
18
18
  - id: black
19
19
  additional_dependencies: [toml]
@@ -45,15 +45,15 @@ repos:
45
45
  - id: check-toml
46
46
  - id: requirements-txt-fixer
47
47
  - repo: https://github.com/asottile/blacken-docs
48
- rev: 1.19.1
48
+ rev: 1.20.0
49
49
  hooks:
50
50
  - id: blacken-docs
51
51
  - repo: https://github.com/astral-sh/ruff-pre-commit
52
- rev: v0.12.8
52
+ rev: v0.14.10
53
53
  hooks:
54
54
  - id: ruff
55
55
  args: [--fix, --exit-non-zero-on-fix]
56
56
  - repo: https://github.com/asottile/pyupgrade
57
- rev: v3.20.0
57
+ rev: v3.21.2
58
58
  hooks:
59
59
  - id: pyupgrade
@@ -3,7 +3,7 @@ version: 2
3
3
  build:
4
4
  os: ubuntu-22.04
5
5
  tools:
6
- python: "3.10"
6
+ python: "3.11"
7
7
  sphinx:
8
8
  configuration: docs/conf.py
9
9
  fail_on_warning: false
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: napari-spatialdata
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Interactive visualization of spatial omics data with napari
5
5
  Home-page: https://github.com/scverse/napari-spatialdata.git
6
6
  Author: giovanni palla
@@ -16,23 +16,23 @@ Classifier: Framework :: napari
16
16
  Classifier: Topic :: Software Development :: Testing
17
17
  Classifier: Programming Language :: Python
18
18
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.10
20
19
  Classifier: Programming Language :: Python :: 3.11
21
20
  Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
22
  Classifier: Operating System :: OS Independent
23
23
  Classifier: License :: OSI Approved :: BSD License
24
- Requires-Python: >=3.10
24
+ Requires-Python: >=3.11
25
25
  Description-Content-Type: text/markdown
26
26
  License-File: LICENSE
27
- Requires-Dist: anndata
27
+ Requires-Dist: anndata>=0.12.0
28
28
  Requires-Dist: click
29
29
  Requires-Dist: cycler
30
- Requires-Dist: dask<=2024.11.2,>=2024.4.1
30
+ Requires-Dist: dask>=2025.2.0
31
31
  Requires-Dist: geopandas
32
32
  Requires-Dist: loguru
33
33
  Requires-Dist: matplotlib
34
34
  Requires-Dist: napari>=0.6.2
35
- Requires-Dist: napari-matplotlib
35
+ Requires-Dist: napari-matplotlib>=3.0.2
36
36
  Requires-Dist: numba
37
37
  Requires-Dist: numpy
38
38
  Requires-Dist: packaging
@@ -44,7 +44,7 @@ Requires-Dist: scanpy
44
44
  Requires-Dist: scipy
45
45
  Requires-Dist: shapely
46
46
  Requires-Dist: scikit-learn
47
- Requires-Dist: spatialdata>=0.2.6
47
+ Requires-Dist: spatialdata>=0.7.0dev1
48
48
  Requires-Dist: superqt
49
49
  Requires-Dist: typing_extensions>=4.8.0
50
50
  Requires-Dist: vispy
@@ -62,8 +62,8 @@ Requires-Dist: pre-commit>=2.9.0; extra == "test"
62
62
  Provides-Extra: doc
63
63
  Requires-Dist: sphinx>=4.5; extra == "doc"
64
64
  Requires-Dist: sphinx-book-theme>=1.0.0; extra == "doc"
65
- Requires-Dist: myst-parser; extra == "doc"
66
- Requires-Dist: sphinxcontrib-bibtex>=1.0.0; extra == "doc"
65
+ Requires-Dist: myst-parser>=2.0.0; extra == "doc"
66
+ Requires-Dist: sphinxcontrib-bibtex>=2.5.0; extra == "doc"
67
67
  Requires-Dist: sphinx-autodoc-typehints>=1.11.0; extra == "doc"
68
68
  Requires-Dist: sphinx-autobuild; extra == "doc"
69
69
  Requires-Dist: scanpydoc; extra == "doc"
@@ -71,12 +71,12 @@ Requires-Dist: ipykernel; extra == "doc"
71
71
  Requires-Dist: ipython; extra == "doc"
72
72
  Requires-Dist: sphinx-copybutton; extra == "doc"
73
73
  Requires-Dist: sphinx-qt-documentation; extra == "doc"
74
- Requires-Dist: myst-nb; extra == "doc"
74
+ Requires-Dist: myst-nb>=1.0.0; extra == "doc"
75
75
  Requires-Dist: squidpy; extra == "doc"
76
76
  Provides-Extra: readthedocs
77
77
  Requires-Dist: pydantic>2; extra == "readthedocs"
78
78
  Provides-Extra: pre
79
- Requires-Dist: spatialdata>=0.1.0-pre0; extra == "pre"
79
+ Requires-Dist: spatialdata>=0.7.0dev0; extra == "pre"
80
80
  Provides-Extra: all
81
81
  Requires-Dist: napari[pyqt5]; extra == "all"
82
82
  Dynamic: license-file
@@ -16,7 +16,7 @@
16
16
  // Install using default qt install
17
17
  "build_command": ["python -V"], // skip build stage
18
18
  "install_command": [
19
- "in-dir={env_dir} python -m pip install {build_dir}[all,test]"
19
+ "in-dir={env_dir} python -m pip install --pre {build_dir}[all,test,pre]"
20
20
  ],
21
21
  "uninstall_command": [
22
22
  "in-dir={env_dir} python -m pip uninstall -y {project}"
@@ -22,7 +22,7 @@ json5==0.9.25
22
22
  # via asv
23
23
  mamba==0.11.3
24
24
  # via -r benchmark.in
25
- packaging==24.1
25
+ packaging>=24.2
26
26
  # via
27
27
  # asv
28
28
  # build
@@ -0,0 +1,25 @@
1
+ # Contributing guide
2
+
3
+ Please refer to the [contribution guide from the `spatialdata` repository](https://github.com/scverse/spatialdata/blob/main/docs/contributing.md).
4
+
5
+ ## Debugging napari GUI tests
6
+
7
+ To visually inspect what a test is rendering in napari:
8
+
9
+ 1. Change `make_napari_viewer()` to `make_napari_viewer(show=True)`
10
+ 2. Add `napari.run()` before the end of the test (before the assertions)
11
+
12
+ Example:
13
+
14
+ ```python
15
+ import napari
16
+
17
+
18
+ def test_my_visualization(make_napari_viewer):
19
+ viewer = make_napari_viewer(show=True)
20
+ # ... setup code ...
21
+ napari.run()
22
+ # assertions...
23
+ ```
24
+
25
+ Remember to revert these changes before committing.
@@ -19,27 +19,27 @@ classifiers =
19
19
  Topic :: Software Development :: Testing
20
20
  Programming Language :: Python
21
21
  Programming Language :: Python :: 3
22
- Programming Language :: Python :: 3.10
23
22
  Programming Language :: Python :: 3.11
24
23
  Programming Language :: Python :: 3.12
24
+ Programming Language :: Python :: 3.13
25
25
  Operating System :: OS Independent
26
26
  License :: OSI Approved :: BSD License
27
27
 
28
28
  [options]
29
29
  packages = find:
30
30
  include_package_data = True
31
- python_requires = >=3.10
31
+ python_requires = >=3.11
32
32
  setup_requires = setuptools_scm
33
33
  install_requires =
34
- anndata
34
+ anndata>=0.12.0
35
35
  click
36
36
  cycler
37
- dask>=2024.4.1,<=2024.11.2
37
+ dask>=2025.2.0
38
38
  geopandas
39
39
  loguru
40
40
  matplotlib
41
41
  napari>=0.6.2
42
- napari-matplotlib
42
+ napari-matplotlib>=3.0.2
43
43
  numba
44
44
  numpy
45
45
  packaging
@@ -51,7 +51,7 @@ install_requires =
51
51
  scipy
52
52
  shapely
53
53
  scikit-learn
54
- spatialdata>=0.2.6
54
+ spatialdata>=0.7.0dev1
55
55
  superqt
56
56
  typing_extensions>=4.8.0
57
57
  vispy
@@ -73,8 +73,8 @@ test =
73
73
  doc =
74
74
  sphinx>=4.5
75
75
  sphinx-book-theme>=1.0.0
76
- myst-parser
77
- sphinxcontrib-bibtex>=1.0.0
76
+ myst-parser>=2.0.0
77
+ sphinxcontrib-bibtex>=2.5.0
78
78
  sphinx-autodoc-typehints>=1.11.0
79
79
  sphinx-autobuild
80
80
  scanpydoc
@@ -82,12 +82,12 @@ doc =
82
82
  ipython
83
83
  sphinx-copybutton
84
84
  sphinx-qt-documentation
85
- myst-nb
85
+ myst-nb>=1.0.0
86
86
  squidpy
87
87
  readthedocs =
88
88
  pydantic>2
89
89
  pre =
90
- spatialdata>=0.1.0-pre0
90
+ spatialdata>=0.7.0dev0
91
91
  all =
92
92
  napari[pyqt5]
93
93
 
@@ -19,14 +19,14 @@ from pyqtgraph.Qt.QtCore import pyqtSignal
19
19
  from pyqtgraph.widgets.ColorButton import ColorButton
20
20
  from qtpy.QtCore import QSize, Qt, Signal
21
21
  from qtpy.QtGui import QColor, QIcon
22
- from qtpy.QtWidgets import QPushButton
22
+ from qtpy.QtWidgets import QLabel, QPushButton, QSpinBox
23
23
  from scipy.spatial import cKDTree
24
24
  from shapely.geometry import Point, Polygon
25
25
  from spatialdata._types import ArrayLike
26
26
 
27
+ import napari_spatialdata.constants.config
27
28
  from napari_spatialdata._model import DataModel
28
29
  from napari_spatialdata._widgets import AListWidget, ComponentWidget
29
- from napari_spatialdata.constants.config import POINT_SIZE_SCATTERPLOT_WIDGET
30
30
 
31
31
  __all__ = [
32
32
  "PlotWidget",
@@ -334,6 +334,7 @@ class PlotWidget(GraphicsLayoutWidget):
334
334
  self.lut: pg.HistogramLUTItem | None = None
335
335
  self.discrete_color_widget: DiscreteColorWidget | None = None
336
336
  self.wrapped_widget: QtWidgets.QGraphicsProxyWidget | None = None
337
+ self._point_size: int = napari_spatialdata.constants.config.POINT_SIZE_SCATTERPLOT_WIDGET
337
338
 
338
339
  self.scatter_plot = self.addPlot(title="")
339
340
  self.scatter_plot.setLabel("bottom", self.x_label)
@@ -344,7 +345,10 @@ class PlotWidget(GraphicsLayoutWidget):
344
345
 
345
346
  # Create a separate ScatterPlotItem for the highlighted point
346
347
  self.hovered_point = pg.ScatterPlotItem(
347
- pen=pg.mkPen("r", width=2), symbol="o", size=POINT_SIZE_SCATTERPLOT_WIDGET, brush=pg.mkBrush(255, 0, 0)
348
+ pen=pg.mkPen("r", width=2),
349
+ symbol="o",
350
+ size=self._point_size + 2,
351
+ brush=pg.mkBrush(255, 0, 0),
348
352
  )
349
353
  self.scatter_plot.addItem(self.hovered_point)
350
354
 
@@ -417,6 +421,19 @@ class PlotWidget(GraphicsLayoutWidget):
417
421
  self.rectangle_mode_button.setToolTip("Add rectangular ROIs.")
418
422
  self.rectangle_mode_button.move(50, 10) # Adjust position as needed
419
423
 
424
+ # Point size control
425
+ self.point_size_label = QLabel("Size:", self)
426
+ self.point_size_label.setStyleSheet(f"QLabel {{ color: rgb{self.color}; background-color: transparent; }}")
427
+ self.point_size_label.move(130, 14)
428
+
429
+ self.point_size_spinbox = QSpinBox(self)
430
+ self.point_size_spinbox.setRange(1, 50)
431
+ self.point_size_spinbox.setValue(self._point_size)
432
+ self.point_size_spinbox.setFixedWidth(50)
433
+ self.point_size_spinbox.setToolTip("Adjust point size in scatter plot")
434
+ self.point_size_spinbox.valueChanged.connect(self._on_point_size_changed)
435
+ self.point_size_spinbox.move(165, 10)
436
+
420
437
  # Connect mouse events
421
438
  self.scatter_plot.setMouseEnabled(x=True, y=True)
422
439
  self.scatter_plot.scene().sigMouseMoved.connect(self.mouseMoveEvent)
@@ -461,6 +478,25 @@ class PlotWidget(GraphicsLayoutWidget):
461
478
  logger.debug("Updating proximity sensitivity...")
462
479
  self.dist_threshold = [x * 15 for x in self.scatter.pixelSize()] # Adjust this factor as needed
463
480
 
481
+ @property
482
+ def point_size(self) -> int:
483
+ """Get the current point size for the scatter plot."""
484
+ return self._point_size
485
+
486
+ @point_size.setter
487
+ def point_size(self, value: int) -> None:
488
+ """Set the point size for the scatter plot."""
489
+ self._point_size = value
490
+ self.point_size_spinbox.setValue(value)
491
+
492
+ def _on_point_size_changed(self, value: int) -> None:
493
+ """Handle point size spinbox value change."""
494
+ self._point_size = value
495
+ # Update hovered point indicator size to be slightly larger
496
+ self.hovered_point.setSize(value + 2)
497
+ if self.scatter is not None:
498
+ self.plot()
499
+
464
500
  def update_hover_highlight(self, x: float, y: float) -> None:
465
501
  """Update the hover highlight based on the cursor position."""
466
502
  if self.kd_tree is not None and self.x_data is not None and self.y_data is not None:
@@ -759,6 +795,7 @@ class PlotWidget(GraphicsLayoutWidget):
759
795
  pen=None,
760
796
  symbolPen=self.symbolPen,
761
797
  symbol="o",
798
+ symbolSize=self._point_size,
762
799
  clear=True,
763
800
  symbolBrush=self.brushes,
764
801
  )
@@ -773,6 +810,7 @@ class PlotWidget(GraphicsLayoutWidget):
773
810
  fillLevel=0,
774
811
  pen=None,
775
812
  symbolPen=self.symbolPen,
813
+ symbolSize=self._point_size,
776
814
  symbolBrush=self.brushes,
777
815
  clear=True,
778
816
  )
@@ -785,6 +823,7 @@ class PlotWidget(GraphicsLayoutWidget):
785
823
  fillLevel=0,
786
824
  pen=None,
787
825
  symbolPen=self.symbolPen,
826
+ symbolSize=self._point_size,
788
827
  symbolBrush=self.brushes,
789
828
  clear=True,
790
829
  )
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.6.0'
32
- __version_tuple__ = version_tuple = (0, 6, 0)
31
+ __version__ = version = '0.7.0'
32
+ __version_tuple__ = version_tuple = (0, 7, 0)
33
33
 
34
- __commit_id__ = commit_id = 'gc95e3e271'
34
+ __commit_id__ = commit_id = 'g6747bf035'
@@ -18,12 +18,11 @@ from shapely import Polygon
18
18
  from spatialdata import get_element_annotators, get_element_instances
19
19
  from spatialdata._core.query.relational_query import _left_join_spatialelement_table
20
20
  from spatialdata._types import ArrayLike
21
- from spatialdata.models import PointsModel, ShapesModel, TableModel, force_2d, get_channel_names
21
+ from spatialdata.models import PointsModel, ShapesModel, TableModel, force_2d, get_axes_names, get_channel_names
22
22
  from spatialdata.transformations import Affine, Identity
23
23
 
24
24
  from napari_spatialdata._model import DataModel
25
25
  from napari_spatialdata.constants import config
26
- from napari_spatialdata.constants.config import CIRCLES_AS_POINTS
27
26
  from napari_spatialdata.utils._utils import (
28
27
  _adjust_channels_order,
29
28
  _get_ellipses_from_circles,
@@ -470,7 +469,7 @@ class SpatialDataViewer(QObject):
470
469
  if multi:
471
470
  original_name = original_name[: original_name.rfind("_")]
472
471
 
473
- affine = _get_transform(sdata.images[original_name], selected_cs)
472
+ affine = _get_transform(sdata.images[original_name], selected_cs, include_z=True)
474
473
  rgb_image, rgb = _adjust_channels_order(element=sdata.images[original_name])
475
474
 
476
475
  channels = ("RGB(A)",) if rgb else get_channel_names(sdata.images[original_name])
@@ -517,6 +516,7 @@ class SpatialDataViewer(QObject):
517
516
  df = sdata.shapes[original_name]
518
517
  affine = _get_transform(sdata.shapes[original_name], selected_cs)
519
518
 
519
+ # 2.5D circles not supported yet
520
520
  xy = np.array([df.geometry.x, df.geometry.y]).T
521
521
  yx = np.fliplr(xy)
522
522
  radii = df.radius.to_numpy()
@@ -541,10 +541,10 @@ class SpatialDataViewer(QObject):
541
541
  version = get_napari_version()
542
542
  kwargs: dict[str, Any] = (
543
543
  {"edge_width": 0.0}
544
- if version <= packaging.version.parse("0.4.20") or not CIRCLES_AS_POINTS
544
+ if version <= packaging.version.parse("0.4.20") or not config.CIRCLES_AS_POINTS
545
545
  else {"border_width": 0.0}
546
546
  )
547
- if CIRCLES_AS_POINTS:
547
+ if config.CIRCLES_AS_POINTS:
548
548
  layer = Points(
549
549
  yx,
550
550
  name=key,
@@ -556,7 +556,7 @@ class SpatialDataViewer(QObject):
556
556
  assert affine is not None
557
557
  self._adjust_radii_of_points_layer(layer=layer, affine=affine)
558
558
  else:
559
- if version <= packaging.version.parse("0.4.20") or not CIRCLES_AS_POINTS:
559
+ if version <= packaging.version.parse("0.4.20") or not config.CIRCLES_AS_POINTS:
560
560
  kwargs |= {"edge_color": "white"}
561
561
  else:
562
562
  kwargs |= {"border_color": "white"}
@@ -597,7 +597,8 @@ class SpatialDataViewer(QObject):
597
597
  original_name = original_name[: original_name.rfind("_")]
598
598
 
599
599
  df = sdata.shapes[original_name]
600
- affine = _get_transform(sdata.shapes[original_name], selected_cs)
600
+ include_z = not config.PROJECT_2_5D_SHAPES_TO_2D
601
+ affine = _get_transform(sdata.shapes[original_name], selected_cs, include_z=include_z)
601
602
 
602
603
  # when mulitpolygons are present, we select the largest ones
603
604
  if "MultiPolygon" in np.unique(df.geometry.type):
@@ -609,7 +610,7 @@ class SpatialDataViewer(QObject):
609
610
  df = df.sort_index() # reset the index to the first order
610
611
 
611
612
  simplify = len(df) > config.POLYGON_THRESHOLD
612
- polygons, indices = _get_polygons_properties(df, simplify)
613
+ polygons, indices = _get_polygons_properties(df, simplify, include_z=include_z)
613
614
 
614
615
  # this will only work for polygons and not for multipolygons
615
616
  polygons = _transform_coordinates(polygons, f=lambda x: x[::-1])
@@ -662,7 +663,7 @@ class SpatialDataViewer(QObject):
662
663
  original_name = original_name[: original_name.rfind("_")]
663
664
 
664
665
  indices = get_element_instances(sdata.labels[original_name])
665
- affine = _get_transform(sdata.labels[original_name], selected_cs)
666
+ affine = _get_transform(sdata.labels[original_name], selected_cs, include_z=True)
666
667
  rgb_labels, _ = _adjust_channels_order(element=sdata.labels[original_name])
667
668
 
668
669
  adata, table_name, table_names = self._get_table_data(sdata, original_name)
@@ -706,8 +707,10 @@ class SpatialDataViewer(QObject):
706
707
  if multi:
707
708
  original_name = original_name[: original_name.rfind("_")]
708
709
 
710
+ axes = get_axes_names(sdata.points[original_name])
709
711
  points = sdata.points[original_name].compute()
710
- affine = _get_transform(sdata.points[original_name], selected_cs)
712
+ include_z = "z" in axes and not config.PROJECT_3D_POINTS_TO_2D
713
+ affine = _get_transform(sdata.points[original_name], selected_cs, include_z=include_z)
711
714
  adata, table_name, table_names = self._get_table_data(sdata, original_name)
712
715
 
713
716
  if len(points) < config.POINT_THRESHOLD:
@@ -727,14 +730,16 @@ class SpatialDataViewer(QObject):
727
730
  _, adata = _left_join_spatialelement_table(
728
731
  {"points": {original_name: subsample_points}}, sdata[table_name], match_rows="left"
729
732
  )
730
- xy = subsample_points[["y", "x"]].values
731
- np.fliplr(xy)
733
+ axes = sorted(axes, reverse=True)
734
+ if not include_z and "z" in axes:
735
+ axes.remove("z")
736
+ coords = subsample_points[axes].values
732
737
  # radii_size = _calc_default_radii(self.viewer, sdata, selected_cs)
733
738
  radii_size = 3
734
739
  version = get_napari_version()
735
740
  kwargs = {"edge_width": 0.0} if version <= packaging.version.parse("0.4.20") else {"border_width": 0.0}
736
741
  layer = Points(
737
- xy,
742
+ coords,
738
743
  name=key,
739
744
  size=radii_size * 2,
740
745
  affine=affine,