napari-spatialdata 0.7.1__tar.gz → 0.7.2__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.
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.pre-commit-config.yaml +3 -3
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/PKG-INFO +1 -1
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_model.py +0 -2
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_scatterwidgets.py +8 -16
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_sdata_widgets.py +57 -4
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_version.py +3 -3
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_view.py +5 -13
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_viewer.py +57 -14
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/utils/_utils.py +55 -10
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata.egg-info/PKG-INFO +1 -1
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata.egg-info/SOURCES.txt +2 -0
- napari_spatialdata-0.7.2/src/napari_spatialdata.egg-info/scm_file_list.json +92 -0
- napari_spatialdata-0.7.2/src/napari_spatialdata.egg-info/scm_version.json +8 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/conftest.py +57 -1
- napari_spatialdata-0.7.2/tests/test_3d_visualization.py +350 -0
- napari_spatialdata-0.7.1/tests/test_3d_visualization.py +0 -161
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.github/BENCHMARK_FAIL_TEMPLATE.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.github/dependabot.yml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.github/release.yml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.github/workflows/benchmarks.yml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.github/workflows/benchmarks_report.yml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.github/workflows/release.yml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.github/workflows/test.yml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.gitignore +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.mypy.ini +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.napari/DESCRIPTION.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/.readthedocs.yaml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/LICENSE +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/MANIFEST.in +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/README.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/asv.conf.json +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/benchmarks/Readme.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/benchmarks/__init__.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/benchmarks/benchmark.in +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/benchmarks/benchmark.txt +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/benchmarks/benchmark_model.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/benchmarks/benchmark_qt_widget.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/Makefile +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/_static/.gitkeep +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/_templates/.gitkeep +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/_templates/autosummary/class.rst +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/api.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/changelog.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/cli.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/conf.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/contributing.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/extensions/typed_returns.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/index.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/limitations.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/make.bat +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/notebooks/mibitof_analysis.ipynb +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/notebooks/nanostring_analysis.ipynb +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/notebooks/scatterwidget.ipynb +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/notebooks/scatterwidget_annotation.ipynb +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/notebooks/spatialdata.ipynb +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/references.bib +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/docs/references.md +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/examples/spatialdata_empty.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/examples/spatialdata_visium.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/pyproject.toml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/setup.cfg +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/__init__.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/__main__.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_annotationwidgets.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_interactive.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_reader.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_widgets.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/constants/__init__.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/constants/_constants.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/constants/_pkg_constants.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/constants/_utils.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/constants/config.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/napari.yaml +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/resources/exclamation.png +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/resources/icons8-home-48.png +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/resources/icons8-pencil-drawing-50.png +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/resources/icons8-polygon-80.png +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/resources/icons8-rectangle-48.png +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/utils/__init__.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/utils/_categoricals_utils.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/utils/_test_utils.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/utils/_viewer_utils.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata.egg-info/dependency_links.txt +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata.egg-info/entry_points.txt +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata.egg-info/requires.txt +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata.egg-info/top_level.txt +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/__init__.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/plots/groundtruth/Images_can_add_element_image.png +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/plots/groundtruth/Images_can_add_element_label.png +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/plots/groundtruth/Images_can_add_element_multiple.png +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/test_cli.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/test_interactive.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/test_scatterwidgets.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/test_spatialdata.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/test_utils.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/test_view.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/test_viewer.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tests/test_widgets.py +0 -0
- {napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/tox.ini +0 -0
|
@@ -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.
|
|
10
|
+
rev: v1.20.2
|
|
11
11
|
hooks:
|
|
12
12
|
- id: mypy
|
|
13
13
|
additional_dependencies: [numpy>=1.23]
|
|
14
14
|
exclude: docs
|
|
15
15
|
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
16
|
-
rev:
|
|
16
|
+
rev: 26.3.1
|
|
17
17
|
hooks:
|
|
18
18
|
- id: black
|
|
19
19
|
additional_dependencies: [toml]
|
|
@@ -49,7 +49,7 @@ repos:
|
|
|
49
49
|
hooks:
|
|
50
50
|
- id: blacken-docs
|
|
51
51
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
52
|
-
rev: v0.
|
|
52
|
+
rev: v0.15.12
|
|
53
53
|
hooks:
|
|
54
54
|
- id: ruff
|
|
55
55
|
args: [--fix, --exit-non-zero-on-fix]
|
|
@@ -28,8 +28,6 @@ class DataModel:
|
|
|
28
28
|
_layer: Layer = field(init=False, default=None, repr=True)
|
|
29
29
|
_adata: AnnData | None = field(init=False, default=None, repr=True)
|
|
30
30
|
_adata_layer: str | None = field(init=False, default=None, repr=False)
|
|
31
|
-
_region_key: str | None = field(default=None, repr=True)
|
|
32
|
-
_instance_key: str | None = field(default=None, repr=True)
|
|
33
31
|
_color_by: str = field(default="", repr=True, init=False)
|
|
34
32
|
_system_name: str | None = field(default=None, repr=True)
|
|
35
33
|
|
{napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_scatterwidgets.py
RENAMED
|
@@ -251,14 +251,12 @@ class DiscreteColorWidget(GraphicsWidget):
|
|
|
251
251
|
color_button = ColorButton(color=color)
|
|
252
252
|
color_button.setMinimumSize(60, 30)
|
|
253
253
|
color_button.setMaximumSize(60, 30)
|
|
254
|
-
color_button.setStyleSheet(
|
|
255
|
-
"""
|
|
254
|
+
color_button.setStyleSheet("""
|
|
256
255
|
QPushButton {
|
|
257
256
|
background-color: transparent;
|
|
258
257
|
border: none;
|
|
259
258
|
}
|
|
260
|
-
"""
|
|
261
|
-
)
|
|
259
|
+
""")
|
|
262
260
|
|
|
263
261
|
self.color_buttons[obj_category] = color_button
|
|
264
262
|
|
|
@@ -384,8 +382,7 @@ class PlotWidget(GraphicsLayoutWidget):
|
|
|
384
382
|
self.drawing_mode_button = QPushButton(self)
|
|
385
383
|
self.drawing_mode_button.setIcon(QIcon(str(Path(__file__).parent / "resources/icons8-polygon-80.png")))
|
|
386
384
|
self.drawing_mode_button.setIconSize(QSize(24, 24))
|
|
387
|
-
self.drawing_mode_button.setStyleSheet(
|
|
388
|
-
f"""
|
|
385
|
+
self.drawing_mode_button.setStyleSheet(f"""
|
|
389
386
|
QPushButton {{
|
|
390
387
|
background-color: transparent;
|
|
391
388
|
border: none;
|
|
@@ -393,8 +390,7 @@ class PlotWidget(GraphicsLayoutWidget):
|
|
|
393
390
|
QPushButton:checked {{
|
|
394
391
|
border: 1px solid rgb{self.color};
|
|
395
392
|
}}
|
|
396
|
-
"""
|
|
397
|
-
)
|
|
393
|
+
""")
|
|
398
394
|
self.drawing_mode_button.setCheckable(True)
|
|
399
395
|
self.drawing_mode_button.clicked.connect(self.toggle_drawing_mode)
|
|
400
396
|
self.drawing_mode_button.setToolTip("Add freehand ROIs.")
|
|
@@ -405,8 +401,7 @@ class PlotWidget(GraphicsLayoutWidget):
|
|
|
405
401
|
self.rectangle_mode_button = QPushButton(self)
|
|
406
402
|
self.rectangle_mode_button.setIcon(QIcon(str(Path(__file__).parent / "resources/icons8-rectangle-48.png")))
|
|
407
403
|
self.rectangle_mode_button.setIconSize(QSize(24, 24))
|
|
408
|
-
self.rectangle_mode_button.setStyleSheet(
|
|
409
|
-
f"""
|
|
404
|
+
self.rectangle_mode_button.setStyleSheet(f"""
|
|
410
405
|
QPushButton {{
|
|
411
406
|
background-color: transparent;
|
|
412
407
|
border: none;
|
|
@@ -414,8 +409,7 @@ class PlotWidget(GraphicsLayoutWidget):
|
|
|
414
409
|
QPushButton:checked {{
|
|
415
410
|
border: 1px solid rgb{self.color};
|
|
416
411
|
}}
|
|
417
|
-
"""
|
|
418
|
-
)
|
|
412
|
+
""")
|
|
419
413
|
self.rectangle_mode_button.setCheckable(True)
|
|
420
414
|
self.rectangle_mode_button.clicked.connect(self.toggle_rectangle_mode)
|
|
421
415
|
self.rectangle_mode_button.setToolTip("Add rectangular ROIs.")
|
|
@@ -873,14 +867,12 @@ class PlotWidget(GraphicsLayoutWidget):
|
|
|
873
867
|
# view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
|
|
874
868
|
# sets stle of the vertical slider
|
|
875
869
|
view.setStyleSheet(get_current_stylesheet())
|
|
876
|
-
view.setStyleSheet(
|
|
877
|
-
"""
|
|
870
|
+
view.setStyleSheet("""
|
|
878
871
|
QGraphicsView {
|
|
879
872
|
border: none;
|
|
880
873
|
background: rgb(0, 0, 0);
|
|
881
874
|
}
|
|
882
|
-
"""
|
|
883
|
-
)
|
|
875
|
+
""")
|
|
884
876
|
|
|
885
877
|
view.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
|
886
878
|
|
{napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/_sdata_widgets.py
RENAMED
|
@@ -5,7 +5,7 @@ from collections.abc import Iterable
|
|
|
5
5
|
from importlib.metadata import version
|
|
6
6
|
from operator import itemgetter
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import TYPE_CHECKING
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
9
|
|
|
10
10
|
import numpy as np
|
|
11
11
|
import shapely
|
|
@@ -15,11 +15,20 @@ from napari.utils.notifications import show_info
|
|
|
15
15
|
from packaging.version import parse as parse_version
|
|
16
16
|
from qtpy.QtCore import QThread, Signal
|
|
17
17
|
from qtpy.QtGui import QIcon
|
|
18
|
-
from qtpy.QtWidgets import
|
|
18
|
+
from qtpy.QtWidgets import (
|
|
19
|
+
QCheckBox,
|
|
20
|
+
QLabel,
|
|
21
|
+
QListWidget,
|
|
22
|
+
QListWidgetItem,
|
|
23
|
+
QProgressBar,
|
|
24
|
+
QVBoxLayout,
|
|
25
|
+
QWidget,
|
|
26
|
+
)
|
|
19
27
|
from spatialdata import SpatialData
|
|
20
28
|
from spatialdata.models._utils import DEFAULT_COORDINATE_SYSTEM
|
|
21
29
|
|
|
22
30
|
from napari_spatialdata._viewer import SpatialDataViewer
|
|
31
|
+
from napari_spatialdata.constants import config
|
|
23
32
|
from napari_spatialdata.constants.config import N_CIRCLES_WARNING_THRESHOLD, N_SHAPES_WARNING_THRESHOLD
|
|
24
33
|
from napari_spatialdata.utils._utils import _get_sdata_key, get_duplicate_element_names, get_elements_meta_mapping
|
|
25
34
|
|
|
@@ -174,11 +183,39 @@ class SdataWidget(QWidget):
|
|
|
174
183
|
self.slider.setRange(0, 0)
|
|
175
184
|
self.slider.setVisible(False)
|
|
176
185
|
|
|
186
|
+
self.discard_z_points = QCheckBox("Discard z for 3D points")
|
|
187
|
+
self.discard_z_points.setChecked(config.PROJECT_3D_POINTS_TO_2D)
|
|
188
|
+
self.discard_z_points.setToolTip(
|
|
189
|
+
"When checked, the z coordinate of new points layers is discarded so they are loaded in 2D. "
|
|
190
|
+
"Only applies to new layers; layers already displayed are not affected."
|
|
191
|
+
)
|
|
192
|
+
self.discard_z_points.toggled.connect(self._on_discard_z_points_toggled)
|
|
193
|
+
|
|
194
|
+
self.discard_z_shapes = QCheckBox("Discard z for 2.5D shapes")
|
|
195
|
+
self.discard_z_shapes.setChecked(config.PROJECT_2_5D_SHAPES_TO_2D)
|
|
196
|
+
self.discard_z_shapes.setToolTip(
|
|
197
|
+
"When checked, the z coordinate of new shapes layers is discarded so they are loaded in 2D. "
|
|
198
|
+
"Only applies to new layers; layers already displayed are not affected."
|
|
199
|
+
)
|
|
200
|
+
self.discard_z_shapes.toggled.connect(self._on_discard_z_shapes_toggled)
|
|
201
|
+
|
|
202
|
+
# The 3D toggles only matter when at least one element across the loaded
|
|
203
|
+
# SpatialData objects has a z axis. Otherwise we hide them to save screen
|
|
204
|
+
# real estate for users working with 2D-only data.
|
|
205
|
+
self._has_z_data = self._sdatas_have_z_axis(self._sdata)
|
|
206
|
+
self._three_d_settings_label = QLabel("3D Settings:")
|
|
207
|
+
self._three_d_settings_label.setVisible(self._has_z_data)
|
|
208
|
+
self.discard_z_points.setVisible(self._has_z_data)
|
|
209
|
+
self.discard_z_shapes.setVisible(self._has_z_data)
|
|
210
|
+
|
|
177
211
|
self.layout().addWidget(self.slider)
|
|
178
212
|
self.layout().addWidget(QLabel("Coordinate System:"))
|
|
179
213
|
self.layout().addWidget(self.coordinate_system_widget)
|
|
180
214
|
self.layout().addWidget(QLabel("Elements:"))
|
|
181
215
|
self.layout().addWidget(self.elements_widget)
|
|
216
|
+
self.layout().addWidget(self._three_d_settings_label)
|
|
217
|
+
self.layout().addWidget(self.discard_z_points)
|
|
218
|
+
self.layout().addWidget(self.discard_z_shapes)
|
|
182
219
|
self.elements_widget.itemDoubleClicked.connect(self._on_click_item)
|
|
183
220
|
self.coordinate_system_widget.currentItemChanged.connect(
|
|
184
221
|
lambda item: self.elements_widget._onItemChange(item.text())
|
|
@@ -219,8 +256,6 @@ class SdataWidget(QWidget):
|
|
|
219
256
|
}:
|
|
220
257
|
return
|
|
221
258
|
|
|
222
|
-
type_ = cast(str, type_)
|
|
223
|
-
|
|
224
259
|
self.worker_thread.load_data(type_, text, sdata, selected_cs, multi)
|
|
225
260
|
if not PROBLEMATIC_NUMPY_MACOS:
|
|
226
261
|
self.slider.setVisible(True)
|
|
@@ -258,6 +293,24 @@ class SdataWidget(QWidget):
|
|
|
258
293
|
layer.metadata["_active_in_cs"].add(coordinate_system)
|
|
259
294
|
layer.metadata["_current_cs"] = coordinate_system
|
|
260
295
|
|
|
296
|
+
def _on_discard_z_points_toggled(self, checked: bool) -> None:
|
|
297
|
+
config.PROJECT_3D_POINTS_TO_2D = checked
|
|
298
|
+
|
|
299
|
+
def _on_discard_z_shapes_toggled(self, checked: bool) -> None:
|
|
300
|
+
config.PROJECT_2_5D_SHAPES_TO_2D = checked
|
|
301
|
+
|
|
302
|
+
@staticmethod
|
|
303
|
+
def _sdatas_have_z_axis(sdatas: EventedList) -> bool:
|
|
304
|
+
"""Return ``True`` if any element across the given ``SpatialData`` objects has a z axis.
|
|
305
|
+
|
|
306
|
+
Used to decide whether to expose the 3D / 2.5D projection toggles in the widget.
|
|
307
|
+
"""
|
|
308
|
+
for sdata in sdatas:
|
|
309
|
+
for _, _, element in sdata._gen_elements():
|
|
310
|
+
if SpatialDataViewer._has_z_axis(element):
|
|
311
|
+
return True
|
|
312
|
+
return False
|
|
313
|
+
|
|
261
314
|
def _get_shapes(self, sdata: SpatialData, key: str, selected_cs: str, multi: bool) -> Shapes | Points:
|
|
262
315
|
original_name = key[: key.rfind("_")] if multi else key
|
|
263
316
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.7.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 7,
|
|
21
|
+
__version__ = version = '0.7.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 7, 2)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'ga1150de77'
|
|
@@ -65,9 +65,7 @@ class QtAdataScatterWidget(QWidget):
|
|
|
65
65
|
self._viewer = napari_viewer
|
|
66
66
|
|
|
67
67
|
self._model = (
|
|
68
|
-
model
|
|
69
|
-
if model is not None
|
|
70
|
-
else self._viewer.window._dock_widgets["SpatialData"].widget().viewer_model._model
|
|
68
|
+
model if model is not None else self._viewer.window.dock_widgets["SpatialData"].viewer_model._model
|
|
71
69
|
)
|
|
72
70
|
|
|
73
71
|
self._select_layer()
|
|
@@ -241,9 +239,8 @@ class QtAdataScatterWidget(QWidget):
|
|
|
241
239
|
|
|
242
240
|
# check that the view widget is present
|
|
243
241
|
# and trigger its update
|
|
244
|
-
if "View (napari-spatialdata)" in
|
|
245
|
-
|
|
246
|
-
qtAdataViewWidget = [x for x in view_widget.children() if isinstance(x, QtAdataViewWidget)][0]
|
|
242
|
+
if "View (napari-spatialdata)" in self._viewer.window.dock_widgets:
|
|
243
|
+
qtAdataViewWidget = self._viewer.window.dock_widgets["View (napari-spatialdata)"]
|
|
247
244
|
qtAdataViewWidget._on_layer_update()
|
|
248
245
|
|
|
249
246
|
# new annotation - update options
|
|
@@ -306,9 +303,7 @@ class QtAdataScatterWidget(QWidget):
|
|
|
306
303
|
selected_table = self.table_name_widget.currentText()
|
|
307
304
|
|
|
308
305
|
# trigger saving of the table
|
|
309
|
-
|
|
310
|
-
# it's used in the save_sdata method
|
|
311
|
-
self._viewer_model = self._viewer.window._dock_widgets["SpatialData"].widget().viewer_model
|
|
306
|
+
self._viewer_model = self._viewer.window.dock_widgets["SpatialData"].viewer_model
|
|
312
307
|
self._viewer_model._write_element_to_disk(
|
|
313
308
|
selected_layer.metadata["sdata"],
|
|
314
309
|
selected_table,
|
|
@@ -611,8 +606,6 @@ class QtAdataViewWidget(QWidget):
|
|
|
611
606
|
if self.model.adata.shape == (0, 0):
|
|
612
607
|
return
|
|
613
608
|
|
|
614
|
-
self.model._region_key = layer.metadata["region_key"] if isinstance(layer, Labels) else None
|
|
615
|
-
self.model._instance_key = layer.metadata["instance_key"] if isinstance(layer, Labels) else None
|
|
616
609
|
self.model.system_name = layer.metadata.get("name", None)
|
|
617
610
|
|
|
618
611
|
if hasattr(
|
|
@@ -695,8 +688,7 @@ class QtAdataAnnotationWidget(QWidget):
|
|
|
695
688
|
def __init__(self, napari_viewer: Viewer):
|
|
696
689
|
super().__init__()
|
|
697
690
|
self._viewer = napari_viewer
|
|
698
|
-
|
|
699
|
-
self._viewer_model = self._viewer.window._dock_widgets["SpatialData"].widget().viewer_model
|
|
691
|
+
self._viewer_model = self._viewer.window.dock_widgets["SpatialData"].viewer_model
|
|
700
692
|
|
|
701
693
|
self.setLayout(QGridLayout())
|
|
702
694
|
self._current_color = "#FFFFFF"
|
|
@@ -189,9 +189,6 @@ class SpatialDataViewer(QObject):
|
|
|
189
189
|
raise ValueError("Cannot export a points element with no points")
|
|
190
190
|
transformed_data = np.array([layer_to_save.data_to_world(xy) for xy in layer_to_save.data])
|
|
191
191
|
swap_data = np.fliplr(transformed_data)
|
|
192
|
-
# ignore z axis if present
|
|
193
|
-
if swap_data.shape[1] == 3:
|
|
194
|
-
swap_data = swap_data[:, :2]
|
|
195
192
|
parsed = PointsModel.parse(swap_data, transformations=transformation)
|
|
196
193
|
|
|
197
194
|
# saving to disk of points temporarily disabled until the interface update that will unify the view widget,
|
|
@@ -261,14 +258,21 @@ class SpatialDataViewer(QObject):
|
|
|
261
258
|
for shape in layer_to_save._data_view.shapes
|
|
262
259
|
]
|
|
263
260
|
|
|
264
|
-
|
|
265
|
-
remove_z = coords.shape[1] == 3
|
|
266
|
-
first_index = 1 if remove_z else 0
|
|
267
|
-
coords = coords[:, first_index::]
|
|
268
|
-
return np.fliplr(coords)
|
|
261
|
+
has_z = coords[0].shape[1] == 3
|
|
269
262
|
|
|
270
|
-
|
|
271
|
-
|
|
263
|
+
def _fix_coords(coords: ArrayLike) -> tuple[ArrayLike, float | None]:
|
|
264
|
+
if coords.shape[1] == 3:
|
|
265
|
+
z_val = float(coords[0, 0])
|
|
266
|
+
yx = coords[:, 1:]
|
|
267
|
+
return np.fliplr(yx), z_val
|
|
268
|
+
return np.fliplr(coords), None
|
|
269
|
+
|
|
270
|
+
fixed = [_fix_coords(p) for p in coords]
|
|
271
|
+
polygons: list[Polygon] = [Polygon(xy) for xy, _ in fixed]
|
|
272
|
+
gdf_dict: dict[str, Any] = {"geometry": polygons}
|
|
273
|
+
if has_z:
|
|
274
|
+
gdf_dict["z"] = [z_val for _, z_val in fixed]
|
|
275
|
+
gdf = GeoDataFrame(gdf_dict)
|
|
272
276
|
|
|
273
277
|
force_2d(gdf)
|
|
274
278
|
parsed = ShapesModel.parse(gdf, transformations=transformation)
|
|
@@ -514,11 +518,15 @@ class SpatialDataViewer(QObject):
|
|
|
514
518
|
original_name = original_name[: original_name.rfind("_")]
|
|
515
519
|
|
|
516
520
|
df = sdata.shapes[original_name]
|
|
517
|
-
|
|
521
|
+
axes = get_axes_names(df)
|
|
522
|
+
include_z = "z" in axes and not config.PROJECT_2_5D_SHAPES_TO_2D
|
|
523
|
+
affine = _get_transform(sdata.shapes[original_name], selected_cs, include_z=include_z)
|
|
518
524
|
|
|
519
|
-
# 2.5D circles not supported yet
|
|
520
525
|
xy = np.array([df.geometry.x, df.geometry.y]).T
|
|
521
526
|
yx = np.fliplr(xy)
|
|
527
|
+
if include_z:
|
|
528
|
+
z_vals = df["z"].to_numpy()
|
|
529
|
+
yx = np.column_stack([z_vals, yx])
|
|
522
530
|
radii = df.radius.to_numpy()
|
|
523
531
|
|
|
524
532
|
adata, table_name, table_names = self._get_table_data(sdata, original_name)
|
|
@@ -561,7 +569,7 @@ class SpatialDataViewer(QObject):
|
|
|
561
569
|
else:
|
|
562
570
|
kwargs |= {"border_color": "white"}
|
|
563
571
|
# useful code to have readily available to debug the correct radius of circles when represented as points
|
|
564
|
-
ellipses = _get_ellipses_from_circles(
|
|
572
|
+
ellipses = _get_ellipses_from_circles(coords=yx, radii=radii)
|
|
565
573
|
layer = Shapes(
|
|
566
574
|
ellipses,
|
|
567
575
|
shape_type="ellipse",
|
|
@@ -804,8 +812,43 @@ class SpatialDataViewer(QObject):
|
|
|
804
812
|
sdata = metadata["sdata"]
|
|
805
813
|
element_name = metadata["name"]
|
|
806
814
|
element_data = sdata[element_name]
|
|
807
|
-
|
|
815
|
+
include_z = self._should_include_z(element_data)
|
|
816
|
+
affine = _get_transform(element_data, coordinate_system, include_z=include_z)
|
|
808
817
|
if affine is not None:
|
|
809
818
|
layer.affine = affine
|
|
810
819
|
if layer._type_string == "points":
|
|
811
820
|
self._adjust_radii_of_points_layer(layer, affine)
|
|
821
|
+
|
|
822
|
+
@staticmethod
|
|
823
|
+
def _has_z_axis(element: Any) -> bool:
|
|
824
|
+
"""Return ``True`` if ``element`` exposes a ``z`` axis.
|
|
825
|
+
|
|
826
|
+
For raster elements (images / labels) the ``z`` axis is reported by
|
|
827
|
+
:func:`spatialdata.models.get_axes_names`. For vector elements (points
|
|
828
|
+
as :class:`~dask.dataframe.DataFrame`, shapes as
|
|
829
|
+
:class:`~geopandas.GeoDataFrame`) the same helper is used.
|
|
830
|
+
"""
|
|
831
|
+
from xarray import DataArray, DataTree
|
|
832
|
+
|
|
833
|
+
if not isinstance(element, DataArray | DataTree | DaskDataFrame | GeoDataFrame):
|
|
834
|
+
return False
|
|
835
|
+
return "z" in get_axes_names(element)
|
|
836
|
+
|
|
837
|
+
@staticmethod
|
|
838
|
+
def _should_include_z(element: DaskDataFrame | GeoDataFrame) -> bool:
|
|
839
|
+
"""Determine whether to include the z axis for a given spatial element.
|
|
840
|
+
|
|
841
|
+
For raster data (images, labels) z is always included when present.
|
|
842
|
+
For vector data (points, shapes) z inclusion depends on the user-facing
|
|
843
|
+
projection config flags.
|
|
844
|
+
"""
|
|
845
|
+
from xarray import DataArray, DataTree
|
|
846
|
+
|
|
847
|
+
if isinstance(element, DataArray | DataTree):
|
|
848
|
+
return True
|
|
849
|
+
axes = get_axes_names(element)
|
|
850
|
+
if "z" not in axes:
|
|
851
|
+
return False
|
|
852
|
+
if isinstance(element, DaskDataFrame):
|
|
853
|
+
return not config.PROJECT_3D_POINTS_TO_2D
|
|
854
|
+
return not config.PROJECT_2_5D_SHAPES_TO_2D
|
{napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata/utils/_utils.py
RENAMED
|
@@ -184,6 +184,32 @@ def _transform_coordinates(data: list[Any], f: Callable[..., Any]) -> list[Any]:
|
|
|
184
184
|
def _get_transform(
|
|
185
185
|
element: SpatialElement, coordinate_system_name: str | None = None, include_z: bool | None = None
|
|
186
186
|
) -> None | ArrayLike:
|
|
187
|
+
"""Return the affine matrix for ``element`` in the given coordinate system.
|
|
188
|
+
|
|
189
|
+
The z axis is included in the returned affine when **both**:
|
|
190
|
+
|
|
191
|
+
* ``include_z`` is truthy, **and**
|
|
192
|
+
* the element (and therefore its underlying transformation) has a ``z`` axis,
|
|
193
|
+
as reported by :func:`spatialdata.models.get_axes_names`.
|
|
194
|
+
|
|
195
|
+
If ``include_z`` is requested but the element / transformation does not expose a
|
|
196
|
+
``z`` axis, the flag is silently ignored and a 2D ``(y, x)`` affine is returned.
|
|
197
|
+
|
|
198
|
+
Parameters
|
|
199
|
+
----------
|
|
200
|
+
element
|
|
201
|
+
The :class:`spatialdata.models.SpatialElement` for which to compute the affine.
|
|
202
|
+
coordinate_system_name
|
|
203
|
+
Coordinate system to use. If ``None``, the first available is selected.
|
|
204
|
+
include_z
|
|
205
|
+
Whether to include the z axis in the affine. The z is only included when the
|
|
206
|
+
element / transformation also has a z axis; otherwise this flag is ignored.
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
The affine matrix as an ``ArrayLike`` (``(3, 3)`` for 2D and ``(4, 4)`` for 2.5D/3D),
|
|
211
|
+
or ``None`` if no transformation is defined for the requested coordinate system.
|
|
212
|
+
"""
|
|
187
213
|
if not isinstance(element, DataArray | DataTree | DaskDataFrame | GeoDataFrame):
|
|
188
214
|
raise RuntimeError("Cannot get transform for {type(element)}")
|
|
189
215
|
|
|
@@ -459,13 +485,17 @@ def generate_random_color_hex() -> str:
|
|
|
459
485
|
return f"#{randint(0, 255):02x}{randint(0, 255):02x}{randint(0, 255):02x}ff"
|
|
460
486
|
|
|
461
487
|
|
|
462
|
-
def _get_ellipses_from_circles(
|
|
488
|
+
def _get_ellipses_from_circles(coords: ArrayLike, radii: ArrayLike) -> ArrayLike:
|
|
463
489
|
"""Convert circles to ellipses.
|
|
464
490
|
|
|
491
|
+
Supports both 2D and 2.5D centroids. For 2.5D input the radius is applied only to
|
|
492
|
+
y and x while z is kept constant across the four corner vertices.
|
|
493
|
+
|
|
465
494
|
Parameters
|
|
466
495
|
----------
|
|
467
|
-
|
|
468
|
-
Centroids of the circles
|
|
496
|
+
coords
|
|
497
|
+
Centroids of the circles with shape ``(N, 2)`` in ``(y, x)`` order or ``(N, 3)``
|
|
498
|
+
in ``(z, y, x)`` order.
|
|
469
499
|
radii
|
|
470
500
|
Radii of the circles.
|
|
471
501
|
|
|
@@ -474,14 +504,29 @@ def _get_ellipses_from_circles(yx: ArrayLike, radii: ArrayLike) -> ArrayLike:
|
|
|
474
504
|
ArrayLike
|
|
475
505
|
Ellipses.
|
|
476
506
|
"""
|
|
477
|
-
ndim =
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
507
|
+
ndim = coords.shape[1]
|
|
508
|
+
if ndim not in (2, 3):
|
|
509
|
+
raise ValueError(f"Expected centroids with 2 or 3 columns (yx or zyx), got shape {coords.shape}.")
|
|
510
|
+
|
|
511
|
+
if ndim == 3:
|
|
512
|
+
z = coords[:, :1]
|
|
513
|
+
yx_2d = coords[:, 1:]
|
|
514
|
+
else:
|
|
515
|
+
yx_2d = coords
|
|
516
|
+
|
|
517
|
+
r = np.stack([radii, radii], axis=1)
|
|
518
|
+
lower_left = yx_2d - r
|
|
519
|
+
upper_right = yx_2d + r
|
|
482
520
|
r[:, 0] = -r[:, 0]
|
|
483
|
-
lower_right =
|
|
484
|
-
upper_left =
|
|
521
|
+
lower_right = yx_2d - r
|
|
522
|
+
upper_left = yx_2d + r
|
|
523
|
+
|
|
524
|
+
if ndim == 3:
|
|
525
|
+
lower_left = np.column_stack([z, lower_left])
|
|
526
|
+
lower_right = np.column_stack([z, lower_right])
|
|
527
|
+
upper_right = np.column_stack([z, upper_right])
|
|
528
|
+
upper_left = np.column_stack([z, upper_left])
|
|
529
|
+
|
|
485
530
|
ellipses = np.stack([lower_left, lower_right, upper_right, upper_left], axis=1)
|
|
486
531
|
assert isinstance(ellipses, np.ndarray)
|
|
487
532
|
return ellipses
|
{napari_spatialdata-0.7.1 → napari_spatialdata-0.7.2}/src/napari_spatialdata.egg-info/SOURCES.txt
RENAMED
|
@@ -63,6 +63,8 @@ src/napari_spatialdata.egg-info/SOURCES.txt
|
|
|
63
63
|
src/napari_spatialdata.egg-info/dependency_links.txt
|
|
64
64
|
src/napari_spatialdata.egg-info/entry_points.txt
|
|
65
65
|
src/napari_spatialdata.egg-info/requires.txt
|
|
66
|
+
src/napari_spatialdata.egg-info/scm_file_list.json
|
|
67
|
+
src/napari_spatialdata.egg-info/scm_version.json
|
|
66
68
|
src/napari_spatialdata.egg-info/top_level.txt
|
|
67
69
|
src/napari_spatialdata/constants/__init__.py
|
|
68
70
|
src/napari_spatialdata/constants/_constants.py
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"files": [
|
|
3
|
+
".pre-commit-config.yaml",
|
|
4
|
+
"README.md",
|
|
5
|
+
"setup.cfg",
|
|
6
|
+
"tox.ini",
|
|
7
|
+
"LICENSE",
|
|
8
|
+
"pyproject.toml",
|
|
9
|
+
"asv.conf.json",
|
|
10
|
+
".mypy.ini",
|
|
11
|
+
"MANIFEST.in",
|
|
12
|
+
".gitignore",
|
|
13
|
+
".readthedocs.yaml",
|
|
14
|
+
".napari/DESCRIPTION.md",
|
|
15
|
+
"docs/Makefile",
|
|
16
|
+
"docs/api.md",
|
|
17
|
+
"docs/references.md",
|
|
18
|
+
"docs/contributing.md",
|
|
19
|
+
"docs/limitations.md",
|
|
20
|
+
"docs/make.bat",
|
|
21
|
+
"docs/changelog.md",
|
|
22
|
+
"docs/cli.md",
|
|
23
|
+
"docs/references.bib",
|
|
24
|
+
"docs/conf.py",
|
|
25
|
+
"docs/index.md",
|
|
26
|
+
"docs/extensions/typed_returns.py",
|
|
27
|
+
"docs/_static/.gitkeep",
|
|
28
|
+
"docs/_templates/.gitkeep",
|
|
29
|
+
"docs/_templates/autosummary/class.rst",
|
|
30
|
+
"docs/notebooks/scatterwidget.ipynb",
|
|
31
|
+
"docs/notebooks/scatterwidget_annotation.ipynb",
|
|
32
|
+
"docs/notebooks/mibitof_analysis.ipynb",
|
|
33
|
+
"docs/notebooks/nanostring_analysis.ipynb",
|
|
34
|
+
"docs/notebooks/spatialdata.ipynb",
|
|
35
|
+
"src/napari_spatialdata/__init__.py",
|
|
36
|
+
"src/napari_spatialdata/_reader.py",
|
|
37
|
+
"src/napari_spatialdata/_interactive.py",
|
|
38
|
+
"src/napari_spatialdata/_scatterwidgets.py",
|
|
39
|
+
"src/napari_spatialdata/_view.py",
|
|
40
|
+
"src/napari_spatialdata/_annotationwidgets.py",
|
|
41
|
+
"src/napari_spatialdata/_widgets.py",
|
|
42
|
+
"src/napari_spatialdata/_viewer.py",
|
|
43
|
+
"src/napari_spatialdata/_sdata_widgets.py",
|
|
44
|
+
"src/napari_spatialdata/_model.py",
|
|
45
|
+
"src/napari_spatialdata/__main__.py",
|
|
46
|
+
"src/napari_spatialdata/napari.yaml",
|
|
47
|
+
"src/napari_spatialdata/resources/icons8-rectangle-48.png",
|
|
48
|
+
"src/napari_spatialdata/resources/icons8-home-48.png",
|
|
49
|
+
"src/napari_spatialdata/resources/icons8-polygon-80.png",
|
|
50
|
+
"src/napari_spatialdata/resources/exclamation.png",
|
|
51
|
+
"src/napari_spatialdata/resources/icons8-pencil-drawing-50.png",
|
|
52
|
+
"src/napari_spatialdata/constants/_pkg_constants.py",
|
|
53
|
+
"src/napari_spatialdata/constants/__init__.py",
|
|
54
|
+
"src/napari_spatialdata/constants/config.py",
|
|
55
|
+
"src/napari_spatialdata/constants/_constants.py",
|
|
56
|
+
"src/napari_spatialdata/constants/_utils.py",
|
|
57
|
+
"src/napari_spatialdata/utils/__init__.py",
|
|
58
|
+
"src/napari_spatialdata/utils/_test_utils.py",
|
|
59
|
+
"src/napari_spatialdata/utils/_utils.py",
|
|
60
|
+
"src/napari_spatialdata/utils/_viewer_utils.py",
|
|
61
|
+
"src/napari_spatialdata/utils/_categoricals_utils.py",
|
|
62
|
+
"tests/__init__.py",
|
|
63
|
+
"tests/test_utils.py",
|
|
64
|
+
"tests/test_spatialdata.py",
|
|
65
|
+
"tests/test_3d_visualization.py",
|
|
66
|
+
"tests/test_widgets.py",
|
|
67
|
+
"tests/test_interactive.py",
|
|
68
|
+
"tests/test_viewer.py",
|
|
69
|
+
"tests/test_view.py",
|
|
70
|
+
"tests/conftest.py",
|
|
71
|
+
"tests/test_cli.py",
|
|
72
|
+
"tests/test_scatterwidgets.py",
|
|
73
|
+
"tests/plots/groundtruth/Images_can_add_element_label.png",
|
|
74
|
+
"tests/plots/groundtruth/Images_can_add_element_multiple.png",
|
|
75
|
+
"tests/plots/groundtruth/Images_can_add_element_image.png",
|
|
76
|
+
"benchmarks/Readme.md",
|
|
77
|
+
"benchmarks/__init__.py",
|
|
78
|
+
"benchmarks/benchmark_qt_widget.py",
|
|
79
|
+
"benchmarks/benchmark_model.py",
|
|
80
|
+
"benchmarks/benchmark.in",
|
|
81
|
+
"benchmarks/benchmark.txt",
|
|
82
|
+
"examples/spatialdata_empty.py",
|
|
83
|
+
"examples/spatialdata_visium.py",
|
|
84
|
+
".github/release.yml",
|
|
85
|
+
".github/BENCHMARK_FAIL_TEMPLATE.md",
|
|
86
|
+
".github/dependabot.yml",
|
|
87
|
+
".github/workflows/test.yml",
|
|
88
|
+
".github/workflows/release.yml",
|
|
89
|
+
".github/workflows/benchmarks_report.yml",
|
|
90
|
+
".github/workflows/benchmarks.yml"
|
|
91
|
+
]
|
|
92
|
+
}
|