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.
Files changed (148) hide show
  1. senoquant/__init__.py +6 -0
  2. senoquant/_reader.py +7 -0
  3. senoquant/_widget.py +33 -0
  4. senoquant/napari.yaml +83 -0
  5. senoquant/reader/__init__.py +5 -0
  6. senoquant/reader/core.py +369 -0
  7. senoquant/tabs/__init__.py +15 -0
  8. senoquant/tabs/batch/__init__.py +10 -0
  9. senoquant/tabs/batch/backend.py +641 -0
  10. senoquant/tabs/batch/config.py +270 -0
  11. senoquant/tabs/batch/frontend.py +1283 -0
  12. senoquant/tabs/batch/io.py +326 -0
  13. senoquant/tabs/batch/layers.py +86 -0
  14. senoquant/tabs/quantification/__init__.py +1 -0
  15. senoquant/tabs/quantification/backend.py +228 -0
  16. senoquant/tabs/quantification/features/__init__.py +80 -0
  17. senoquant/tabs/quantification/features/base.py +142 -0
  18. senoquant/tabs/quantification/features/marker/__init__.py +5 -0
  19. senoquant/tabs/quantification/features/marker/config.py +69 -0
  20. senoquant/tabs/quantification/features/marker/dialog.py +437 -0
  21. senoquant/tabs/quantification/features/marker/export.py +879 -0
  22. senoquant/tabs/quantification/features/marker/feature.py +119 -0
  23. senoquant/tabs/quantification/features/marker/morphology.py +285 -0
  24. senoquant/tabs/quantification/features/marker/rows.py +654 -0
  25. senoquant/tabs/quantification/features/marker/thresholding.py +46 -0
  26. senoquant/tabs/quantification/features/roi.py +346 -0
  27. senoquant/tabs/quantification/features/spots/__init__.py +5 -0
  28. senoquant/tabs/quantification/features/spots/config.py +62 -0
  29. senoquant/tabs/quantification/features/spots/dialog.py +477 -0
  30. senoquant/tabs/quantification/features/spots/export.py +1292 -0
  31. senoquant/tabs/quantification/features/spots/feature.py +112 -0
  32. senoquant/tabs/quantification/features/spots/morphology.py +279 -0
  33. senoquant/tabs/quantification/features/spots/rows.py +241 -0
  34. senoquant/tabs/quantification/frontend.py +815 -0
  35. senoquant/tabs/segmentation/__init__.py +1 -0
  36. senoquant/tabs/segmentation/backend.py +131 -0
  37. senoquant/tabs/segmentation/frontend.py +1009 -0
  38. senoquant/tabs/segmentation/models/__init__.py +5 -0
  39. senoquant/tabs/segmentation/models/base.py +146 -0
  40. senoquant/tabs/segmentation/models/cpsam/details.json +65 -0
  41. senoquant/tabs/segmentation/models/cpsam/model.py +150 -0
  42. senoquant/tabs/segmentation/models/default_2d/details.json +69 -0
  43. senoquant/tabs/segmentation/models/default_2d/model.py +664 -0
  44. senoquant/tabs/segmentation/models/default_3d/details.json +69 -0
  45. senoquant/tabs/segmentation/models/default_3d/model.py +682 -0
  46. senoquant/tabs/segmentation/models/hf.py +71 -0
  47. senoquant/tabs/segmentation/models/nuclear_dilation/__init__.py +1 -0
  48. senoquant/tabs/segmentation/models/nuclear_dilation/details.json +26 -0
  49. senoquant/tabs/segmentation/models/nuclear_dilation/model.py +96 -0
  50. senoquant/tabs/segmentation/models/perinuclear_rings/__init__.py +1 -0
  51. senoquant/tabs/segmentation/models/perinuclear_rings/details.json +34 -0
  52. senoquant/tabs/segmentation/models/perinuclear_rings/model.py +132 -0
  53. senoquant/tabs/segmentation/stardist_onnx_utils/__init__.py +2 -0
  54. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/__init__.py +3 -0
  55. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/__init__.py +6 -0
  56. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/generate.py +470 -0
  57. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/prepare.py +273 -0
  58. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/rawdata.py +112 -0
  59. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/data/transform.py +384 -0
  60. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/__init__.py +0 -0
  61. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/blocks.py +184 -0
  62. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/losses.py +79 -0
  63. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/nets.py +165 -0
  64. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/predict.py +467 -0
  65. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/probability.py +67 -0
  66. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/internals/train.py +148 -0
  67. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/io/__init__.py +163 -0
  68. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/__init__.py +52 -0
  69. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/base_model.py +329 -0
  70. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/care_isotropic.py +160 -0
  71. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/care_projection.py +178 -0
  72. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/care_standard.py +446 -0
  73. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/care_upsampling.py +54 -0
  74. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/config.py +254 -0
  75. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/models/pretrained.py +119 -0
  76. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/scripts/__init__.py +0 -0
  77. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/scripts/care_predict.py +180 -0
  78. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/__init__.py +5 -0
  79. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/plot_utils.py +159 -0
  80. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/six.py +18 -0
  81. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/tf.py +644 -0
  82. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/utils/utils.py +272 -0
  83. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/csbdeep/version.py +1 -0
  84. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/docs/source/conf.py +368 -0
  85. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/setup.py +68 -0
  86. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tests/test_datagen.py +169 -0
  87. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tests/test_models.py +462 -0
  88. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tests/test_utils.py +166 -0
  89. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tools/create_zip_contents.py +34 -0
  90. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/__init__.py +30 -0
  91. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/big.py +624 -0
  92. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/bioimageio_utils.py +494 -0
  93. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/data/__init__.py +39 -0
  94. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/geometry/__init__.py +10 -0
  95. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/geometry/geom2d.py +215 -0
  96. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/geometry/geom3d.py +349 -0
  97. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/matching.py +483 -0
  98. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/models/__init__.py +28 -0
  99. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/models/base.py +1217 -0
  100. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/models/model2d.py +594 -0
  101. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/models/model3d.py +696 -0
  102. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/nms.py +384 -0
  103. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/plot/__init__.py +2 -0
  104. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/plot/plot.py +74 -0
  105. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/plot/render.py +298 -0
  106. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/rays3d.py +373 -0
  107. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/sample_patches.py +65 -0
  108. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/__init__.py +0 -0
  109. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/predict2d.py +90 -0
  110. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/predict3d.py +93 -0
  111. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/utils.py +408 -0
  112. senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/version.py +1 -0
  113. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/__init__.py +45 -0
  114. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/__init__.py +17 -0
  115. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/cli.py +55 -0
  116. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/core.py +285 -0
  117. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/__init__.py +15 -0
  118. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/cli.py +36 -0
  119. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/divisibility.py +193 -0
  120. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/probe.py +100 -0
  121. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/receptive_field.py +182 -0
  122. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/rf_cli.py +48 -0
  123. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/valid_sizes.py +278 -0
  124. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/post/__init__.py +8 -0
  125. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/post/core.py +157 -0
  126. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/pre/__init__.py +17 -0
  127. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/pre/core.py +226 -0
  128. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/predict/__init__.py +5 -0
  129. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/predict/core.py +401 -0
  130. senoquant/tabs/settings/__init__.py +1 -0
  131. senoquant/tabs/settings/backend.py +29 -0
  132. senoquant/tabs/settings/frontend.py +19 -0
  133. senoquant/tabs/spots/__init__.py +1 -0
  134. senoquant/tabs/spots/backend.py +139 -0
  135. senoquant/tabs/spots/frontend.py +800 -0
  136. senoquant/tabs/spots/models/__init__.py +5 -0
  137. senoquant/tabs/spots/models/base.py +94 -0
  138. senoquant/tabs/spots/models/rmp/details.json +61 -0
  139. senoquant/tabs/spots/models/rmp/model.py +499 -0
  140. senoquant/tabs/spots/models/udwt/details.json +103 -0
  141. senoquant/tabs/spots/models/udwt/model.py +482 -0
  142. senoquant/utils.py +25 -0
  143. senoquant-1.0.0b1.dist-info/METADATA +193 -0
  144. senoquant-1.0.0b1.dist-info/RECORD +148 -0
  145. senoquant-1.0.0b1.dist-info/WHEEL +5 -0
  146. senoquant-1.0.0b1.dist-info/entry_points.txt +2 -0
  147. senoquant-1.0.0b1.dist-info/licenses/LICENSE +28 -0
  148. 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,5 @@
1
+ """Marker feature UI package."""
2
+
3
+ from .feature import MarkerFeature
4
+
5
+ __all__ = ["MarkerFeature"]
@@ -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)