napari-spatialdata 0.5.2.post1__tar.gz → 0.5.3__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 (90) hide show
  1. napari_spatialdata-0.5.3/.github/BENCHMARK_FAIL_TEMPLATE.md +13 -0
  2. napari_spatialdata-0.5.3/.github/workflows/benchmarks.yml +194 -0
  3. napari_spatialdata-0.5.3/.github/workflows/benchmarks_report.yml +98 -0
  4. napari_spatialdata-0.5.3/.github/workflows/test.yml +128 -0
  5. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/.gitignore +1 -0
  6. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/CHANGELOG.md +7 -1
  7. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/PKG-INFO +2 -2
  8. napari_spatialdata-0.5.3/asv.conf.json +63 -0
  9. napari_spatialdata-0.5.3/benchmarks/Readme.md +45 -0
  10. napari_spatialdata-0.5.3/benchmarks/benchmark.in +3 -0
  11. napari_spatialdata-0.5.3/benchmarks/benchmark.txt +48 -0
  12. napari_spatialdata-0.5.3/benchmarks/benchmark_model.py +16 -0
  13. napari_spatialdata-0.5.3/benchmarks/benchmark_qt_widget.py +19 -0
  14. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/pyproject.toml +3 -2
  15. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/setup.cfg +1 -1
  16. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_model.py +31 -32
  17. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_scatterwidgets.py +2 -1
  18. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_sdata_widgets.py +2 -1
  19. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_version.py +2 -2
  20. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_view.py +43 -20
  21. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_viewer.py +23 -8
  22. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_widgets.py +31 -8
  23. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/constants/_utils.py +3 -3
  24. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/utils/_categoricals_utils.py +15 -13
  25. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/utils/_utils.py +5 -2
  26. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata.egg-info/PKG-INFO +2 -2
  27. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata.egg-info/SOURCES.txt +11 -0
  28. napari_spatialdata-0.5.3/tests/__init__.py +0 -0
  29. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/conftest.py +7 -5
  30. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/test_utils.py +2 -2
  31. napari_spatialdata-0.5.3/tests/test_view.py +103 -0
  32. napari_spatialdata-0.5.2.post1/.github/workflows/test.yml +0 -71
  33. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/.github/dependabot.yml +0 -0
  34. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/.github/workflows/release.yml +0 -0
  35. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/.mypy.ini +0 -0
  36. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/.napari/DESCRIPTION.md +0 -0
  37. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/.pre-commit-config.yaml +0 -0
  38. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/.readthedocs.yaml +0 -0
  39. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/LICENSE +0 -0
  40. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/MANIFEST.in +0 -0
  41. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/README.md +0 -0
  42. {napari_spatialdata-0.5.2.post1/src/napari_spatialdata/constants → napari_spatialdata-0.5.3/benchmarks}/__init__.py +0 -0
  43. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/Makefile +0 -0
  44. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/_static/.gitkeep +0 -0
  45. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/_templates/.gitkeep +0 -0
  46. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/_templates/autosummary/class.rst +0 -0
  47. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/api.md +0 -0
  48. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/cli.md +0 -0
  49. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/conf.py +0 -0
  50. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/contributing.md +0 -0
  51. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/extensions/typed_returns.py +0 -0
  52. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/index.md +0 -0
  53. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/make.bat +0 -0
  54. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/notebooks/mibitof_analysis.ipynb +0 -0
  55. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/notebooks/nanostring_analysis.ipynb +0 -0
  56. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/notebooks/scatterwidget.ipynb +0 -0
  57. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/notebooks/spatialdata.ipynb +0 -0
  58. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/references.bib +0 -0
  59. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/references.md +0 -0
  60. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/docs/template_usage.md +0 -0
  61. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/examples/spatialdata_empty.py +0 -0
  62. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/examples/spatialdata_visium.py +0 -0
  63. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/__init__.py +0 -0
  64. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/__main__.py +0 -0
  65. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_annotationwidgets.py +0 -0
  66. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_interactive.py +0 -0
  67. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/_reader.py +0 -0
  68. {napari_spatialdata-0.5.2.post1/src/napari_spatialdata/utils → napari_spatialdata-0.5.3/src/napari_spatialdata/constants}/__init__.py +0 -0
  69. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/constants/_constants.py +0 -0
  70. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/constants/_pkg_constants.py +0 -0
  71. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/constants/config.py +0 -0
  72. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/napari.yaml +0 -0
  73. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/resources/exclamation.png +0 -0
  74. {napari_spatialdata-0.5.2.post1/tests → napari_spatialdata-0.5.3/src/napari_spatialdata/utils}/__init__.py +0 -0
  75. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/utils/_test_utils.py +0 -0
  76. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata/utils/_viewer_utils.py +0 -0
  77. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata.egg-info/dependency_links.txt +0 -0
  78. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata.egg-info/entry_points.txt +0 -0
  79. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata.egg-info/requires.txt +0 -0
  80. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/src/napari_spatialdata.egg-info/top_level.txt +0 -0
  81. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/plots/groundtruth/Images_can_add_element_image.png +0 -0
  82. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/plots/groundtruth/Images_can_add_element_label.png +0 -0
  83. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/plots/groundtruth/Images_can_add_element_multiple.png +0 -0
  84. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/test_cli.py +0 -0
  85. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/test_interactive.py +0 -0
  86. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/test_scatterwidgets.py +0 -0
  87. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/test_spatialdata.py +0 -0
  88. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/test_viewer.py +0 -0
  89. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tests/test_widgets.py +0 -0
  90. {napari_spatialdata-0.5.2.post1 → napari_spatialdata-0.5.3}/tox.ini +0 -0
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: "{{ env.TITLE }}"
3
+ labels: [bug]
4
+ ---
5
+
6
+ The {{ workflow }} workflow failed on {{ date | date("YYYY-MM-DD HH:mm") }} UTC
7
+
8
+ The most recent failing benchmark was on {{ env.PLATFORM }} py{{ env.PYTHON }} {{ env.BACKEND }}
9
+ with commit: {{ sha }}
10
+
11
+ Full run: https://github.com/scverse/napari-spatialdata/actions/runs/{{ env.RUN_ID }}
12
+
13
+ (This post will be updated if another test fails, as long as this issue remains open.)
@@ -0,0 +1,194 @@
1
+ # This CI configuration for relative benchmarks is based on the research done
2
+ # for scikit-image's implementation available here:
3
+ # https://github.com/scikit-image/scikit-image/blob/9bdd010a8/.github/workflows/benchmarks.yml#L1
4
+ # Blog post with the rationale: https://labs.quansight.org/blog/2021/08/github-actions-benchmarks/
5
+
6
+ name: Benchmarks
7
+
8
+ on:
9
+ pull_request:
10
+ types: [labeled]
11
+ schedule:
12
+ - cron: "6 6 * * 0" # every sunday
13
+ workflow_dispatch:
14
+ inputs:
15
+ base_ref:
16
+ description: "Baseline commit or git reference"
17
+ required: true
18
+ contender_ref:
19
+ description: "Contender commit or git reference"
20
+ required: true
21
+
22
+ # This is the main configuration section that needs to be fine tuned to napari's needs
23
+ # All the *_THREADS options is just to make the benchmarks more robust by not using parallelism
24
+ env:
25
+ OPENBLAS_NUM_THREADS: "1"
26
+ MKL_NUM_THREADS: "1"
27
+ OMP_NUM_THREADS: "1"
28
+ ASV_OPTIONS: "--split --show-stderr --factor 1.5 --attribute timeout=900"
29
+ # --split -> split final reports in tables
30
+ # --show-stderr -> print tracebacks if errors occur
31
+ # --factor 1.5 -> report anomaly if tested timings are beyond 1.5x base timings
32
+ # --attribute timeout=300 -> override timeout attribute (default=60s) to allow slow tests to run
33
+ # see https://asv.readthedocs.io/en/stable/commands.html#asv-continuous for more details!
34
+
35
+ jobs:
36
+ benchmark:
37
+ if: ${{ github.event.label.name == 'run-benchmarks' && github.event_name == 'pull_request' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
38
+ name: ${{ matrix.benchmark-name }}
39
+ runs-on: ${{ matrix.runs-on }}
40
+ permissions:
41
+ contents: read
42
+ issues: write
43
+ strategy:
44
+ fail-fast: false
45
+ matrix:
46
+ include:
47
+ - benchmark-name: Qt
48
+ asv-command: continuous
49
+ selection-regex: "^benchmark_qt_.*"
50
+ runs-on: macos-latest
51
+ # Qt tests run on macOS to avoid using Xvfb business
52
+ # xvfb makes everything run, but some tests segfault :shrug:
53
+ # Fortunately, macOS graphics stack does not need xvfb!
54
+ - benchmark-name: non-Qt
55
+ asv-command: continuous
56
+ selection-regex: "^benchmark_(?!qt_).*"
57
+ runs-on: ubuntu-latest
58
+
59
+ steps:
60
+ # We need the full repo to avoid this issue
61
+ # https://github.com/actions/checkout/issues/23
62
+ - uses: actions/checkout@v4
63
+ with:
64
+ fetch-depth: 0
65
+
66
+ - uses: actions/setup-python@v5
67
+ name: Install Python
68
+ with:
69
+ python-version: "3.11"
70
+ cache-dependency-path: pyproject.toml
71
+
72
+ - uses: tlambert03/setup-qt-libs@v1
73
+
74
+ - name: Setup asv
75
+ run: python -m pip install "asv[virtualenv]"
76
+ env:
77
+ PIP_CONSTRAINT: ${{ github.workspace }}/benchmarks/benchmark.txt
78
+
79
+ - uses: octokit/request-action@v2.x
80
+ id: latest_release
81
+ with:
82
+ route: GET /repos/{owner}/{repo}/releases/latest
83
+ owner: scverse
84
+ repo: napari-spatialdata
85
+ env:
86
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
87
+
88
+ - name: Run ${{ matrix.benchmark-name }} benchmarks
89
+ id: run_benchmark
90
+ env:
91
+ # asv will checkout commits, which might contain LFS artifacts; ignore those errors since
92
+ # they are probably just documentation PNGs not needed here anyway
93
+ GIT_LFS_SKIP_SMUDGE: 1
94
+ HEAD_LABEL: ${{ github.event.pull_request.head.label }}
95
+ PIP_CONSTRAINT: ${{ github.workspace }}/benchmarks/benchmark.txt
96
+ run: |
97
+ set -euxo pipefail
98
+ read -ra cmd_options <<< "$ASV_OPTIONS"
99
+
100
+ # ID this runner
101
+ asv machine --yes
102
+
103
+ if [[ $GITHUB_EVENT_NAME == pull_request ]]; then
104
+ EVENT_NAME="PR #${{ github.event.pull_request.number }}"
105
+ BASE_REF=${{ github.event.pull_request.base.sha }}
106
+ CONTENDER_REF=${GITHUB_SHA}
107
+ echo "Baseline: ${BASE_REF} (${{ github.event.pull_request.base.label }})"
108
+ echo "Contender: ${CONTENDER_REF} ($HEAD_LABEL)"
109
+ elif [[ $GITHUB_EVENT_NAME == schedule ]]; then
110
+ EVENT_NAME="cronjob"
111
+ BASE_REF="${{ fromJSON(steps.latest_release.outputs.data).target_commitish }}"
112
+ CONTENDER_REF="${GITHUB_SHA}"
113
+ echo "Baseline: ${BASE_REF} (${{ fromJSON(steps.latest_release.outputs.data).tag_name }})"
114
+ echo "Contender: ${CONTENDER_REF} (current main)"
115
+ elif [[ $GITHUB_EVENT_NAME == workflow_dispatch ]]; then
116
+ EVENT_NAME="manual trigger"
117
+ BASE_REF="${{ github.event.inputs.base_ref }}"
118
+ CONTENDER_REF="${{ github.event.inputs.contender_ref }}"
119
+ echo "Baseline: ${BASE_REF} (workflow input)"
120
+ echo "Contender: ${CONTENDER_REF} (workflow input)"
121
+ fi
122
+
123
+ echo "EVENT_NAME=$EVENT_NAME" >> "$GITHUB_ENV"
124
+ echo "BASE_REF=$BASE_REF" >> "$GITHUB_ENV"
125
+ echo "CONTENDER_REF=$CONTENDER_REF" >> "$GITHUB_ENV"
126
+
127
+ # Run benchmarks for current commit against base
128
+ asv continuous "${cmd_options[@]}" -b "${{ matrix.selection-regex }}" "${BASE_REF}" "${CONTENDER_REF}" \
129
+ | sed -E "/Traceback | failed$|PERFORMANCE DECREASED/ s/^/::error:: /" \
130
+ | tee asv_continuous.log
131
+
132
+ # Report and export results for subsequent steps
133
+ if grep "Traceback \|failed\|PERFORMANCE DECREASED" asv_continuous.log > /dev/null ; then
134
+ exit 1
135
+ fi
136
+
137
+ - name: Report Failures as Issue
138
+ if: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && failure() }}
139
+ uses: JasonEtco/create-an-issue@v2
140
+ env:
141
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
142
+ PLATFORM: ${{ matrix.runs-on }}
143
+ PYTHON: "3.9"
144
+ BACKEND: ${{ matrix.benchmark-name }}
145
+ RUN_ID: ${{ github.run_id }}
146
+ TITLE: "[test-bot] Benchmark tests failing"
147
+ with:
148
+ filename: .github/BENCHMARK_FAIL_TEMPLATE.md
149
+ update_existing: true
150
+
151
+ - name: Add more info to artifact
152
+ if: always()
153
+ run: |
154
+ # Copy the full `asv continuous` log
155
+ cp asv_continuous.log .asv/results/asv_continuous_${{ matrix.benchmark-name }}.log
156
+ # ensure that even if this isn't a PR, the benchmark_report workflow can run without error
157
+ touch .asv/results/message_${{ matrix.benchmark-name }}.txt
158
+
159
+ # Add the message that might be posted as a comment on the PR
160
+ # We delegate the actual comment to `benchmarks_report.yml` due to
161
+ # potential token permissions issues
162
+ if [[ $GITHUB_EVENT_NAME == pull_request ]]; then
163
+
164
+ echo "${{ github.event.pull_request.number }}" > .asv/results/pr_number
165
+ echo \
166
+ "The ${{ matrix.benchmark-name }} benchmark run requested by $EVENT_NAME ($CONTENDER_REF vs $BASE_REF) has" \
167
+ "finished with status '${{ steps.run_benchmark.outcome }}'. See the" \
168
+ "[CI logs and artifacts](||BENCHMARK_CI_LOGS_URL||) for further details." \
169
+ > .asv/results/message_${{ matrix.benchmark-name }}.txt
170
+
171
+ fi
172
+
173
+ - uses: actions/upload-artifact@v4
174
+ if: always()
175
+ with:
176
+ name: asv-benchmark-results-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}-${{ matrix.benchmark-name }}
177
+ path: .asv/results
178
+
179
+ combine-artifacts:
180
+ runs-on: ubuntu-latest
181
+ needs: benchmark
182
+ if: always()
183
+ steps:
184
+ - name: Download artifact
185
+ uses: actions/download-artifact@v4
186
+ with:
187
+ pattern: asv-benchmark-results*
188
+ path: asv_result
189
+ merge-multiple: true
190
+ - name: Upload artifact
191
+ uses: actions/upload-artifact@v4
192
+ with:
193
+ name: asv-benchmark-results-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}
194
+ path: asv_result
@@ -0,0 +1,98 @@
1
+ # Report benchmark results to the PR
2
+ # We need a dual workflow to make sure the token has the needed permissions to post comments
3
+ # See https://stackoverflow.com/a/71683208 for more details
4
+
5
+ # When this workflow is triggered, it pulls the latest version of this file on
6
+ # the default branch. Changes to this file won't be reflected until after the
7
+ # PR is merged.
8
+ # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run
9
+
10
+ name: "Benchmarks - Report"
11
+
12
+ on:
13
+ workflow_run:
14
+ workflows: [Benchmarks]
15
+ types:
16
+ - completed
17
+
18
+ permissions:
19
+ pull-requests: write
20
+ issues: write
21
+
22
+ jobs:
23
+ download:
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - name: "Download artifact"
27
+ uses: actions/github-script@v7
28
+ with:
29
+ script: |
30
+ let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
31
+ owner: context.repo.owner,
32
+ repo: context.repo.repo,
33
+ run_id: context.payload.workflow_run.id,
34
+ });
35
+ let artifactName = `asv-benchmark-results-${context.payload.workflow_run.id}-${context.payload.workflow_run.run_number}-${context.payload.workflow_run.run_attempt}`
36
+ console.log(`Artifact name: ${artifactName}`);
37
+ console.log(`All artifacts: ${JSON.stringify(allArtifacts.data.artifacts)}`);
38
+ let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
39
+ return artifact.name == artifactName
40
+ })[0];
41
+ if (matchArtifact === undefined) {
42
+ throw TypeError('Build Artifact not found!');
43
+ }
44
+ let download = await github.rest.actions.downloadArtifact({
45
+ owner: context.repo.owner,
46
+ repo: context.repo.repo,
47
+ artifact_id: matchArtifact.id,
48
+ archive_format: 'zip',
49
+ });
50
+ let fs = require('fs');
51
+ fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/asv_results.zip`, Buffer.from(download.data));
52
+
53
+ - name: Unzip and prepare data
54
+ run: |
55
+ unzip asv_results.zip
56
+ # combine the Qt and non-Qt messages
57
+ cat message_Qt.txt message_non-Qt.txt > message.txt
58
+
59
+ - name: Replace URLs
60
+ run: |
61
+ sed -i 's@||BENCHMARK_CI_LOGS_URL||@${{ github.event.workflow_run.html_url }}@g' message.txt
62
+
63
+ - name: Collect PR number if available
64
+ run: |
65
+ if [[ -f pr_number ]]; then
66
+ echo "PR_NUMBER=$(cat pr_number)" >> "$GITHUB_ENV"
67
+ fi
68
+
69
+ - name: "Comment on PR"
70
+ if: env.PR_NUMBER != ''
71
+ uses: actions/github-script@v7
72
+ with:
73
+ github-token: ${{ secrets.GITHUB_TOKEN }}
74
+ script: |
75
+ let fs = require('fs');
76
+ let issue_number = Number(process.env.PR_NUMBER);
77
+ let body = fs.readFileSync('message.txt', 'utf8');
78
+ await github.rest.issues.createComment({
79
+ owner: context.repo.owner,
80
+ repo: context.repo.repo,
81
+ issue_number: issue_number,
82
+ body: body,
83
+ });
84
+
85
+ - name: "Remove run-benchmarks label"
86
+ if: env.PR_NUMBER != ''
87
+ uses: actions/github-script@v7
88
+ with:
89
+ github-token: ${{ secrets.GITHUB_TOKEN }}
90
+ script: |
91
+ let fs = require('fs');
92
+ let issue_number = Number(process.env.PR_NUMBER);
93
+ await github.rest.issues.removeLabel({
94
+ owner: context.repo.owner,
95
+ repo: context.repo.repo,
96
+ issue_number: issue_number,
97
+ name: 'run-benchmarks',
98
+ });
@@ -0,0 +1,128 @@
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
+ matrix:
25
+ platform: [ubuntu-latest, macos-latest] # [ubuntu-latest, windows-latest, macos-latest]
26
+ python-version: ["3.9", "3.11"]
27
+
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - name: Set up Python ${{ matrix.python-version }}
32
+ uses: actions/setup-python@v5
33
+ with:
34
+ python-version: ${{ matrix.python-version }}
35
+
36
+ # these libraries enable testing on Qt on linux
37
+ - uses: tlambert03/setup-qt-libs@v1
38
+
39
+ # strategy borrowed from vispy for installing opengl libs on windows
40
+ - name: Install Windows OpenGL
41
+ if: runner.os == 'Windows'
42
+ run: |
43
+ git clone --depth 1 https://github.com/pyvista/gl-ci-helpers.git
44
+ powershell gl-ci-helpers/appveyor/install_opengl.ps1
45
+
46
+ # note: if you need dependencies from conda, considering using
47
+ # setup-miniconda: https://github.com/conda-incubator/setup-miniconda
48
+ # and
49
+ # tox-conda: https://github.com/tox-dev/tox-conda
50
+ - name: Install dependencies
51
+ run: |
52
+ python -m pip install --upgrade pip
53
+ python -m pip install setuptools tox tox-gh-actions
54
+
55
+ # this runs the platform-specific tests declared in tox.ini
56
+ - name: Test with tox
57
+ uses: coactions/setup-xvfb@v1
58
+ with:
59
+ run: python -m tox
60
+ env:
61
+ PLATFORM: ${{ matrix.platform }}
62
+
63
+ - name: Coverage
64
+ uses: codecov/codecov-action@v4
65
+
66
+ - name: Archive figures generated during testing
67
+ if: always()
68
+ uses: actions/upload-artifact@v4
69
+ with:
70
+ name: plotting-results-${{ matrix.python-version }}-${{ matrix.platform }}
71
+ path: /home/runner/work/napari-spatialdata/napari-spatialdata/tests/plots/*
72
+
73
+ test_benchmarks:
74
+ name: test benchmarks
75
+ runs-on: ubuntu-latest
76
+ timeout-minutes: 60
77
+ env:
78
+ GIT_LFS_SKIP_SMUDGE: 1
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+ with:
82
+ fetch-depth: 0
83
+
84
+ - uses: actions/setup-python@v5
85
+ with:
86
+ python-version: 3.11
87
+ cache-dependency-path: pyproject.toml
88
+
89
+ - uses: tlambert03/setup-qt-libs@v1
90
+
91
+ - uses: octokit/request-action@v2.x
92
+ # here we get hash of the latest release commit to compare with PR
93
+ id: latest_release
94
+ with:
95
+ route: GET /repos/{owner}/{repo}/releases/latest
96
+ owner: scverse
97
+ repo: napari-spatialdata
98
+ env:
99
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
100
+
101
+ - name: install dependencies
102
+ run: |
103
+ pip install --upgrade pip
104
+ pip install "asv[virtualenv]"
105
+ env:
106
+ PIP_CONSTRAINT: benchmarks/benchmark.txt
107
+
108
+ - name: asv machine
109
+ run: asv machine --yes
110
+
111
+ - name: Run benchmarks PR
112
+ uses: aganders3/headless-gui@v2
113
+ with:
114
+ run: |
115
+ asv run --show-stderr --quick --attribute timeout=300 HEAD^!
116
+ env:
117
+ PR: 1 # prevents asv from running very compute-intensive benchmarks
118
+ PIP_CONSTRAINT: ${{ github.workspace }}/benchmarks/benchmark.txt
119
+
120
+ - name: Run benchmarks latest release
121
+ # here we check if the benchmark on the latest release is not broken
122
+ uses: aganders3/headless-gui@v2
123
+ with:
124
+ run: |
125
+ asv run --show-stderr --quick --attribute timeout=300 ${{ fromJSON(steps.latest_release.outputs.data).target_commitish }}^!
126
+ env:
127
+ PR: 1 # prevents asv from running very compute-intensive benchmarks
128
+ PIP_CONSTRAINT: ${{ github.workspace }}/benchmarks/benchmark.txt
@@ -1,3 +1,4 @@
1
+ .asv
1
2
  data/
2
3
 
3
4
  # Byte-compiled / optimized / DLL files
@@ -8,7 +8,13 @@ and this project adheres to [Semantic Versioning][].
8
8
  [keep a changelog]: https://keepachangelog.com/en/1.0.0/
9
9
  [semantic versioning]: https://semver.org/spec/v2.0.0.html
10
10
 
11
- ## [0.x.x] - 2024-xx-xx
11
+ ## [0.5.3] - 2024-09-25
12
+
13
+ ### Fixed
14
+
15
+ - Bug table was not reset after an element without table was added #317
16
+ - Bug when changing channel for a multichannel image #301 #302
17
+ - Bug when plotting catgorical annotations on points #304
12
18
 
13
19
  ## [0.5.2] - 2024-08-16
14
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: napari-spatialdata
3
- Version: 0.5.2.post1
3
+ Version: 0.5.3
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
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.9
20
20
  Classifier: Programming Language :: Python :: 3.10
21
21
  Classifier: Operating System :: OS Independent
22
22
  Classifier: License :: OSI Approved :: BSD License
23
- Requires-Python: >=3.9
23
+ Requires-Python: >=3.9.2
24
24
  Description-Content-Type: text/markdown
25
25
  License-File: LICENSE
26
26
  Requires-Dist: anndata
@@ -0,0 +1,63 @@
1
+ {
2
+ // The version of the config file format. Do not change, unless
3
+ // you know what you are doing.
4
+ "version": 1,
5
+
6
+ // The name of the project being benchmarked
7
+ "project": "napari-spatialdata",
8
+
9
+ // The project's homepage
10
+ "project_url": "http://napari.org/",
11
+
12
+ // The URL or local path of the source code repository for the
13
+ // project being benchmarked
14
+ "repo": ".",
15
+
16
+ // Install using default qt install
17
+ "build_command": ["python -V"], // skip build stage
18
+ "install_command": [
19
+ "in-dir={env_dir} python -m pip install {build_dir}[all,test]"
20
+ ],
21
+ "uninstall_command": [
22
+ "in-dir={env_dir} python -m pip uninstall -y {project}"
23
+ ],
24
+
25
+ // List of branches to benchmark
26
+ "branches": ["main"],
27
+
28
+ // The tool to use to create environments.
29
+ "environment_type": "virtualenv",
30
+
31
+ // timeout in seconds for installing any dependencies in environment
32
+ "install_timeout": 600,
33
+
34
+ // the base URL to show a commit for the project.
35
+ "show_commit_url": "http://github.com/napari/napari/commit/",
36
+
37
+ // The Pythons you'd like to test against.
38
+ "pythons": ["3.11"],
39
+
40
+ // The directory (relative to the current directory) to cache the Python
41
+ // environments in.
42
+ "env_dir": ".asv/env",
43
+
44
+ // The directory (relative to the current directory) that raw benchmark
45
+ // results are stored in.
46
+ "results_dir": ".asv/results",
47
+
48
+ // The directory (relative to the current directory) that the html tree
49
+ // should be written to.
50
+ "html_dir": ".asv/html",
51
+
52
+ // The directory (relative to the current directory) where the benchmarks
53
+ // are stored
54
+ "benchmark_dir": "benchmarks",
55
+
56
+ // The number of characters to retain in the commit hashes.
57
+ "hash_length": 8,
58
+
59
+ // `asv` will cache results of the recent builds in each
60
+ // environment, making them faster to install next time. This is
61
+ // the number of builds to keep, per environment.
62
+ "build_cache_size": 2
63
+ }
@@ -0,0 +1,45 @@
1
+ # Benchmarks
2
+
3
+ This are benchmarks for napari-spatialdata project.
4
+ Benchmarks are required for early detection of performance regressions.
5
+
6
+ Here we use `asv` to run benchmarks. Webpage https://asv.readthedocs.io
7
+
8
+ It is generally better to run benchmarks on linux runner (cheaper, more available).
9
+ However benchmarking of gui applications requires to have a display server.
10
+ For normal tests we use `xvfb` to run tests without display server,
11
+ but it impact performance of GUI applications in unpredictable way.
12
+ So we run GUI benchmarks on macOS runner.
13
+
14
+ To distinguish between gui and non-gui benchmarks we use `qt` in benchmark file name.
15
+
16
+ So any benchmark file starting with `benchamrk_qt` gui benchmark,
17
+ all other benchmarks are non-gui benchmarks.
18
+
19
+ ## Running benchmarks
20
+
21
+ To run benchmarks locally there is a need to have `asv` installed and
22
+ python 3.11 available in the PATH.
23
+ First run requires to run `asv machine --yes` to collect machine metadata.
24
+
25
+ To quick run all benchmarks use `PR=1 asv run --show-stderr --quick --attribute timeout=300 HEAD^!`
26
+ Quick run allow to check if benchmarks are running without errors.
27
+ `PR=1` environment variable is used to allow skip long running benchmarks cases.
28
+
29
+ To run all benchmarks and get more accurate statistics
30
+ use `asv run --show-stderr --attribute timeout=300 HEAD^!`
31
+
32
+ Each time you create a PR, benchmarks will be executed on the PR with PR=1 environment variable.
33
+
34
+ ## Adding new benchmarks
35
+
36
+ To add a new benchmark first check if it fit into existing benchmark file.
37
+ If not create a new benchmark file, but remember to use `benchmark_qt` in file name prefix
38
+ if it is a gui benchmark.
39
+
40
+ ## Maintaining benchmarks
41
+
42
+ To keep more reproducible results, the `asv` is pinning python to a specific
43
+ version in its configuration file (`asv.conf.json`).
44
+ If you want to update the python version it need to be bumped in both
45
+ `asv.conf.json` and `.github/workflows/benchmarks.yml` files.
@@ -0,0 +1,3 @@
1
+ asv[virtualenv]
2
+ pympler!=1.1
3
+ mamba
@@ -0,0 +1,48 @@
1
+ # This file was autogenerated by uv via the following command:
2
+ # uv pip compile benchmark.in -o benchmark.txt
3
+ args==0.1.0
4
+ # via clint
5
+ asv==0.6.3
6
+ # via -r benchmark.in
7
+ asv-runner==0.2.1
8
+ # via asv
9
+ build==1.2.1
10
+ # via asv
11
+ clint==0.5.1
12
+ # via mamba
13
+ coverage==7.6.1
14
+ # via mamba
15
+ distlib==0.3.8
16
+ # via virtualenv
17
+ filelock==3.15.4
18
+ # via virtualenv
19
+ importlib-metadata==8.0.0
20
+ # via asv-runner
21
+ json5==0.9.25
22
+ # via asv
23
+ mamba==0.11.3
24
+ # via -r benchmark.in
25
+ packaging==24.1
26
+ # via
27
+ # asv
28
+ # build
29
+ platformdirs==4.2.2
30
+ # via virtualenv
31
+ pympler==1.0.1
32
+ # via
33
+ # -r benchmark.in
34
+ # asv
35
+ pyproject-hooks==1.1.0
36
+ # via build
37
+ pyyaml==6.0.1
38
+ # via asv
39
+ tabulate==0.9.0
40
+ # via asv
41
+ tomli==2.0.1
42
+ # via
43
+ # asv
44
+ # build
45
+ virtualenv==20.26.3
46
+ # via asv
47
+ zipp==3.19.2
48
+ # via importlib-metadata
@@ -0,0 +1,16 @@
1
+ import os
2
+
3
+ from napari_spatialdata._model import DataModel
4
+
5
+
6
+ class DataModelSuite:
7
+ params = [1] if "PR" in os.environ else [1, 10]
8
+
9
+ def setup(self, _n: int) -> None:
10
+ self.model = DataModel()
11
+
12
+ def mem_model(self, _n: int) -> DataModel:
13
+ return self.model
14
+
15
+ def time_model_get_items(self, _n: int) -> None:
16
+ self.model.get_items("columns_df")
@@ -0,0 +1,19 @@
1
+ import numpy as np
2
+ from napari import Viewer
3
+ from napari.layers import Image
4
+ from napari.utils.events import EventedList
5
+ from napari_spatialdata._sdata_widgets import SdataWidget
6
+
7
+
8
+ class SdataWidgetSuite:
9
+ def setup(self) -> None:
10
+ self.viewer = Viewer()
11
+ self.evented_list = EventedList()
12
+ self.widget = SdataWidget(self.viewer, self.evented_list)
13
+ self.image = Image(np.zeros((10, 10)))
14
+
15
+ def time_create_widget(self) -> None:
16
+ SdataWidget(self.viewer, self.evented_list)
17
+
18
+ def time_layer_added(self) -> None:
19
+ self.viewer.add_layer(self.image)