senoquant 1.0.0b1__py3-none-any.whl
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.
- senoquant/__init__.py +6 -0
- senoquant/_reader.py +7 -0
- senoquant/_widget.py +33 -0
- senoquant/napari.yaml +83 -0
- senoquant/reader/__init__.py +5 -0
- senoquant/reader/core.py +369 -0
- senoquant/tabs/__init__.py +15 -0
- senoquant/tabs/batch/__init__.py +10 -0
- senoquant/tabs/batch/backend.py +641 -0
- senoquant/tabs/batch/config.py +270 -0
- senoquant/tabs/batch/frontend.py +1283 -0
- senoquant/tabs/batch/io.py +326 -0
- senoquant/tabs/batch/layers.py +86 -0
- senoquant/tabs/quantification/__init__.py +1 -0
- senoquant/tabs/quantification/backend.py +228 -0
- senoquant/tabs/quantification/features/__init__.py +80 -0
- senoquant/tabs/quantification/features/base.py +142 -0
- senoquant/tabs/quantification/features/marker/__init__.py +5 -0
- senoquant/tabs/quantification/features/marker/config.py +69 -0
- senoquant/tabs/quantification/features/marker/dialog.py +437 -0
- senoquant/tabs/quantification/features/marker/export.py +879 -0
- senoquant/tabs/quantification/features/marker/feature.py +119 -0
- senoquant/tabs/quantification/features/marker/morphology.py +285 -0
- senoquant/tabs/quantification/features/marker/rows.py +654 -0
- senoquant/tabs/quantification/features/marker/thresholding.py +46 -0
- senoquant/tabs/quantification/features/roi.py +346 -0
- senoquant/tabs/quantification/features/spots/__init__.py +5 -0
- senoquant/tabs/quantification/features/spots/config.py +62 -0
- senoquant/tabs/quantification/features/spots/dialog.py +477 -0
- senoquant/tabs/quantification/features/spots/export.py +1292 -0
- senoquant/tabs/quantification/features/spots/feature.py +112 -0
- senoquant/tabs/quantification/features/spots/morphology.py +279 -0
- senoquant/tabs/quantification/features/spots/rows.py +241 -0
- senoquant/tabs/quantification/frontend.py +815 -0
- senoquant/tabs/segmentation/__init__.py +1 -0
- senoquant/tabs/segmentation/backend.py +131 -0
- senoquant/tabs/segmentation/frontend.py +1009 -0
- senoquant/tabs/segmentation/models/__init__.py +5 -0
- senoquant/tabs/segmentation/models/base.py +146 -0
- senoquant/tabs/segmentation/models/cpsam/details.json +65 -0
- senoquant/tabs/segmentation/models/cpsam/model.py +150 -0
- senoquant/tabs/segmentation/models/default_2d/details.json +69 -0
- senoquant/tabs/segmentation/models/default_2d/model.py +664 -0
- senoquant/tabs/segmentation/models/default_3d/details.json +69 -0
- senoquant/tabs/segmentation/models/default_3d/model.py +682 -0
- senoquant/tabs/segmentation/models/hf.py +71 -0
- senoquant/tabs/segmentation/models/nuclear_dilation/__init__.py +1 -0
- senoquant/tabs/segmentation/models/nuclear_dilation/details.json +26 -0
- senoquant/tabs/segmentation/models/nuclear_dilation/model.py +96 -0
- senoquant/tabs/segmentation/models/perinuclear_rings/__init__.py +1 -0
- senoquant/tabs/segmentation/models/perinuclear_rings/details.json +34 -0
- senoquant/tabs/segmentation/models/perinuclear_rings/model.py +132 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/__init__.py +2 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/__init__.py +3 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/__init__.py +6 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/generate.py +470 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/prepare.py +273 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/rawdata.py +112 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/transform.py +384 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/__init__.py +0 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/blocks.py +184 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/losses.py +79 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/nets.py +165 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/predict.py +467 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/probability.py +67 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/train.py +148 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/io/__init__.py +163 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/__init__.py +52 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/base_model.py +329 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/care_isotropic.py +160 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/care_projection.py +178 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/care_standard.py +446 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/care_upsampling.py +54 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/config.py +254 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/pretrained.py +119 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/scripts/__init__.py +0 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/scripts/care_predict.py +180 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/__init__.py +5 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/plot_utils.py +159 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/six.py +18 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/tf.py +644 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/utils.py +272 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/version.py +1 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/docs/source/conf.py +368 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/setup.py +68 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tests/test_datagen.py +169 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tests/test_models.py +462 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tests/test_utils.py +166 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tools/create_zip_contents.py +34 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/__init__.py +30 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/big.py +624 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/bioimageio_utils.py +494 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/data/__init__.py +39 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/geometry/__init__.py +10 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/geometry/geom2d.py +215 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/geometry/geom3d.py +349 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/matching.py +483 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/models/__init__.py +28 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/models/base.py +1217 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/models/model2d.py +594 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/models/model3d.py +696 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/nms.py +384 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/plot/__init__.py +2 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/plot/plot.py +74 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/plot/render.py +298 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/rays3d.py +373 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/sample_patches.py +65 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/__init__.py +0 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/predict2d.py +90 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/predict3d.py +93 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/utils.py +408 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/version.py +1 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/__init__.py +45 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/__init__.py +17 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/cli.py +55 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/core.py +285 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/__init__.py +15 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/cli.py +36 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/divisibility.py +193 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/probe.py +100 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/receptive_field.py +182 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/rf_cli.py +48 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/valid_sizes.py +278 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/post/__init__.py +8 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/post/core.py +157 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/pre/__init__.py +17 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/pre/core.py +226 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/predict/__init__.py +5 -0
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/predict/core.py +401 -0
- senoquant/tabs/settings/__init__.py +1 -0
- senoquant/tabs/settings/backend.py +29 -0
- senoquant/tabs/settings/frontend.py +19 -0
- senoquant/tabs/spots/__init__.py +1 -0
- senoquant/tabs/spots/backend.py +139 -0
- senoquant/tabs/spots/frontend.py +800 -0
- senoquant/tabs/spots/models/__init__.py +5 -0
- senoquant/tabs/spots/models/base.py +94 -0
- senoquant/tabs/spots/models/rmp/details.json +61 -0
- senoquant/tabs/spots/models/rmp/model.py +499 -0
- senoquant/tabs/spots/models/udwt/details.json +103 -0
- senoquant/tabs/spots/models/udwt/model.py +482 -0
- senoquant/utils.py +25 -0
- senoquant-1.0.0b1.dist-info/METADATA +193 -0
- senoquant-1.0.0b1.dist-info/RECORD +148 -0
- senoquant-1.0.0b1.dist-info/WHEEL +5 -0
- senoquant-1.0.0b1.dist-info/entry_points.txt +2 -0
- senoquant-1.0.0b1.dist-info/licenses/LICENSE +28 -0
- senoquant-1.0.0b1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Quantification feature UI components."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib
|
|
6
|
+
import pkgutil
|
|
7
|
+
from typing import Iterable
|
|
8
|
+
|
|
9
|
+
from .base import FeatureConfig, FeatureData, SenoQuantFeature
|
|
10
|
+
from .marker.config import MarkerFeatureData
|
|
11
|
+
from .spots.config import SpotsFeatureData
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _iter_subclasses(cls: type[SenoQuantFeature]) -> Iterable[type[SenoQuantFeature]]:
|
|
15
|
+
"""Yield all subclasses of a feature class recursively.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
cls : type[SenoQuantFeature]
|
|
20
|
+
Base class whose subclasses should be discovered.
|
|
21
|
+
|
|
22
|
+
Yields
|
|
23
|
+
------
|
|
24
|
+
type[SenoQuantFeature]
|
|
25
|
+
Feature subclass types.
|
|
26
|
+
"""
|
|
27
|
+
for subclass in cls.__subclasses__():
|
|
28
|
+
yield subclass
|
|
29
|
+
yield from _iter_subclasses(subclass)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_feature_registry() -> dict[str, type[SenoQuantFeature]]:
|
|
33
|
+
"""Discover feature classes and return a registry by name."""
|
|
34
|
+
for module in pkgutil.walk_packages(__path__, f"{__name__}."):
|
|
35
|
+
importlib.import_module(module.name)
|
|
36
|
+
|
|
37
|
+
registry: dict[str, type[SenoQuantFeature]] = {}
|
|
38
|
+
for feature_cls in _iter_subclasses(SenoQuantFeature):
|
|
39
|
+
feature_type = getattr(feature_cls, "feature_type", "")
|
|
40
|
+
if not feature_type:
|
|
41
|
+
continue
|
|
42
|
+
registry[feature_type] = feature_cls
|
|
43
|
+
|
|
44
|
+
return dict(
|
|
45
|
+
sorted(
|
|
46
|
+
registry.items(),
|
|
47
|
+
key=lambda item: getattr(item[1], "order", 0),
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
FEATURE_DATA_FACTORY: dict[str, type[FeatureData]] = {
|
|
52
|
+
"Markers": MarkerFeatureData,
|
|
53
|
+
"Spots": SpotsFeatureData,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def build_feature_data(feature_type: str) -> FeatureData:
|
|
58
|
+
"""Create a feature data instance for the specified feature type.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
feature_type : str
|
|
63
|
+
Feature type name.
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
FeatureData
|
|
68
|
+
Feature-specific configuration instance.
|
|
69
|
+
"""
|
|
70
|
+
data_cls = FEATURE_DATA_FACTORY.get(feature_type, FeatureData)
|
|
71
|
+
return data_cls()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
__all__ = [
|
|
75
|
+
"FeatureConfig",
|
|
76
|
+
"FeatureData",
|
|
77
|
+
"SenoQuantFeature",
|
|
78
|
+
"build_feature_data",
|
|
79
|
+
"get_feature_registry",
|
|
80
|
+
]
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Feature UI base classes for quantification."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING, Iterable
|
|
8
|
+
import uuid
|
|
9
|
+
|
|
10
|
+
from qtpy.QtWidgets import QComboBox
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..frontend import QuantificationTab
|
|
14
|
+
from ..frontend import FeatureUIContext
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FeatureData:
|
|
18
|
+
"""Base class for feature-specific configuration data.
|
|
19
|
+
|
|
20
|
+
Notes
|
|
21
|
+
-----
|
|
22
|
+
Concrete feature data classes should inherit from this class so they can
|
|
23
|
+
be stored on :class:`FeatureConfig`.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class FeatureConfig:
|
|
29
|
+
"""Configuration for a single quantification feature.
|
|
30
|
+
|
|
31
|
+
Attributes
|
|
32
|
+
----------
|
|
33
|
+
feature_id : str
|
|
34
|
+
Unique identifier for the feature instance.
|
|
35
|
+
name : str
|
|
36
|
+
User-facing name for the feature.
|
|
37
|
+
type_name : str
|
|
38
|
+
Feature type name (e.g., ``"Markers"``).
|
|
39
|
+
data : FeatureData
|
|
40
|
+
Feature-specific configuration payload.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
feature_id: str = field(default_factory=lambda: uuid.uuid4().hex)
|
|
44
|
+
name: str = ""
|
|
45
|
+
type_name: str = ""
|
|
46
|
+
data: FeatureData = field(default_factory=FeatureData)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class SenoQuantFeature:
|
|
50
|
+
"""Base class for quantification feature UI."""
|
|
51
|
+
|
|
52
|
+
feature_type: str = ""
|
|
53
|
+
order: int = 0
|
|
54
|
+
|
|
55
|
+
def __init__(self, tab: "QuantificationTab", context: "FeatureUIContext") -> None:
|
|
56
|
+
"""Initialize a feature with shared tab context.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
tab : QuantificationTab
|
|
61
|
+
Parent quantification tab instance.
|
|
62
|
+
context : FeatureUIContext
|
|
63
|
+
Feature UI context with configuration state.
|
|
64
|
+
"""
|
|
65
|
+
self._tab = tab
|
|
66
|
+
self._context = context
|
|
67
|
+
self._state = context.state
|
|
68
|
+
self._ui: dict[str, object] = {}
|
|
69
|
+
|
|
70
|
+
def build(self) -> None:
|
|
71
|
+
"""Build the UI for this feature."""
|
|
72
|
+
raise NotImplementedError
|
|
73
|
+
|
|
74
|
+
def export(self, temp_dir: Path, export_format: str) -> Iterable[Path]:
|
|
75
|
+
"""Export feature outputs into a temporary directory.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
temp_dir : Path
|
|
80
|
+
Temporary directory where outputs should be written.
|
|
81
|
+
export_format : str
|
|
82
|
+
File format requested by the user (``"csv"`` or ``"xlsx"``).
|
|
83
|
+
|
|
84
|
+
Returns
|
|
85
|
+
-------
|
|
86
|
+
iterable of Path
|
|
87
|
+
Paths to files produced by the export routine.
|
|
88
|
+
|
|
89
|
+
Notes
|
|
90
|
+
-----
|
|
91
|
+
Implementations may either return explicit file paths or simply
|
|
92
|
+
write outputs into ``temp_dir`` and return an empty iterable.
|
|
93
|
+
"""
|
|
94
|
+
return []
|
|
95
|
+
|
|
96
|
+
def on_features_changed(self, configs: list["FeatureUIContext"]) -> None:
|
|
97
|
+
"""Handle updates when the feature list changes.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
configs : list of FeatureUIContext
|
|
102
|
+
Current feature contexts.
|
|
103
|
+
"""
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def update_type_options(
|
|
108
|
+
cls, tab: "QuantificationTab", configs: list["FeatureUIContext"]
|
|
109
|
+
) -> None:
|
|
110
|
+
"""Update type availability in feature selectors.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
tab : QuantificationTab
|
|
115
|
+
Parent quantification tab instance.
|
|
116
|
+
configs : list of FeatureUIContext
|
|
117
|
+
Current feature contexts.
|
|
118
|
+
"""
|
|
119
|
+
return
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class RefreshingComboBox(QComboBox):
|
|
123
|
+
"""Combo box that refreshes its items when opened."""
|
|
124
|
+
|
|
125
|
+
def __init__(self, refresh_callback=None, parent=None) -> None:
|
|
126
|
+
"""Create a combo box that refreshes before showing its popup.
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
----------
|
|
130
|
+
refresh_callback : callable or None
|
|
131
|
+
Callback invoked before showing the popup.
|
|
132
|
+
parent : QWidget or None
|
|
133
|
+
Optional parent widget.
|
|
134
|
+
"""
|
|
135
|
+
super().__init__(parent)
|
|
136
|
+
self._refresh_callback = refresh_callback
|
|
137
|
+
|
|
138
|
+
def showPopup(self) -> None:
|
|
139
|
+
"""Refresh items before showing the popup."""
|
|
140
|
+
if self._refresh_callback is not None:
|
|
141
|
+
self._refresh_callback()
|
|
142
|
+
super().showPopup()
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Marker feature configuration models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from ..base import FeatureData
|
|
9
|
+
from ..roi import ROIConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class MarkerSegmentationConfig:
|
|
14
|
+
"""Configuration for a segmentation labels entry.
|
|
15
|
+
|
|
16
|
+
Attributes
|
|
17
|
+
----------
|
|
18
|
+
label : str
|
|
19
|
+
Name of the labels layer selected for this segmentation entry.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
label: str = ""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class MarkerChannelConfig:
|
|
27
|
+
"""Configuration for a marker channel entry.
|
|
28
|
+
|
|
29
|
+
Attributes
|
|
30
|
+
----------
|
|
31
|
+
name : str
|
|
32
|
+
User-friendly label for the channel entry.
|
|
33
|
+
channel : str
|
|
34
|
+
Selected image layer name.
|
|
35
|
+
threshold_enabled : bool
|
|
36
|
+
Whether threshold controls are active.
|
|
37
|
+
threshold_method : str
|
|
38
|
+
Automatic threshold method name.
|
|
39
|
+
threshold_min : float or None
|
|
40
|
+
Minimum threshold value.
|
|
41
|
+
threshold_max : float or None
|
|
42
|
+
Maximum threshold value.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
name: str = ""
|
|
46
|
+
channel: str = ""
|
|
47
|
+
threshold_enabled: bool = False
|
|
48
|
+
threshold_method: str = "Manual"
|
|
49
|
+
threshold_min: Optional[float] = None
|
|
50
|
+
threshold_max: Optional[float] = None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class MarkerFeatureData(FeatureData):
|
|
55
|
+
"""Configuration for marker feature inputs.
|
|
56
|
+
|
|
57
|
+
Attributes
|
|
58
|
+
----------
|
|
59
|
+
segmentations : list of MarkerSegmentationConfig
|
|
60
|
+
Segmentation label selections.
|
|
61
|
+
channels : list of MarkerChannelConfig
|
|
62
|
+
Channel configurations used for marker measurement.
|
|
63
|
+
rois : list of ROIConfig
|
|
64
|
+
ROI entries applied to this feature.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
segmentations: list[MarkerSegmentationConfig] = field(default_factory=list)
|
|
68
|
+
channels: list[MarkerChannelConfig] = field(default_factory=list)
|
|
69
|
+
rois: list[ROIConfig] = field(default_factory=list)
|