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,270 @@
1
+ """Batch job configuration and serialization helpers.
2
+
3
+ This module defines dataclasses used to capture batch settings from the UI
4
+ and persist them to JSON. The serialization format keeps feature configs
5
+ portable across sessions and mirrors the Quantification tab structures.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from dataclasses import dataclass, field, asdict
11
+ from typing import Iterable
12
+ import json
13
+
14
+ from senoquant.tabs.quantification.features import FeatureConfig
15
+ from senoquant.tabs.quantification.features.base import FeatureData
16
+ from senoquant.tabs.quantification.features.marker.config import (
17
+ MarkerChannelConfig,
18
+ MarkerFeatureData,
19
+ MarkerSegmentationConfig,
20
+ )
21
+ from senoquant.tabs.quantification.features.spots.config import (
22
+ SpotsChannelConfig,
23
+ SpotsFeatureData,
24
+ SpotsSegmentationConfig,
25
+ )
26
+ from senoquant.tabs.quantification.features.roi import ROIConfig
27
+
28
+
29
+ @dataclass(slots=True)
30
+ class BatchChannelConfig:
31
+ """Channel mapping configuration.
32
+
33
+ Attributes
34
+ ----------
35
+ name : str
36
+ User-facing channel name (used in UI and exports).
37
+ index : int
38
+ Zero-based channel index in the input image.
39
+ """
40
+
41
+ name: str
42
+ index: int
43
+
44
+
45
+ @dataclass(slots=True)
46
+ class BatchSegmentationConfig:
47
+ """Segmentation configuration for a single task."""
48
+ enabled: bool = False
49
+ model: str = ""
50
+ channel: str = ""
51
+ settings: dict = field(default_factory=dict)
52
+
53
+
54
+ @dataclass(slots=True)
55
+ class BatchCytoplasmicConfig:
56
+ """Cytoplasmic segmentation configuration."""
57
+ enabled: bool = False
58
+ model: str = ""
59
+ channel: str = ""
60
+ nuclear_channel: str = ""
61
+ settings: dict = field(default_factory=dict)
62
+
63
+
64
+ @dataclass(slots=True)
65
+ class BatchSpotsConfig:
66
+ """Spot detection configuration."""
67
+ enabled: bool = False
68
+ detector: str = ""
69
+ channels: list[str] = field(default_factory=list)
70
+ settings: dict = field(default_factory=dict)
71
+ min_size: int = 0
72
+ max_size: int = 0
73
+
74
+
75
+ @dataclass(slots=True)
76
+ class BatchQuantificationConfig:
77
+ """Quantification configuration."""
78
+ enabled: bool = False
79
+ format: str = "xlsx"
80
+ features: list[FeatureConfig] = field(default_factory=list)
81
+
82
+
83
+ @dataclass(slots=True)
84
+ class BatchJobConfig:
85
+ """Top-level batch configuration.
86
+
87
+ This structure is the single payload passed from the UI to the backend.
88
+ It is also the serialized representation used in batch profiles.
89
+ """
90
+ input_path: str = ""
91
+ output_path: str = ""
92
+ extensions: list[str] = field(default_factory=list)
93
+ include_subfolders: bool = False
94
+ process_all_scenes: bool = False
95
+ overwrite: bool = False
96
+ output_format: str = "tif"
97
+ channel_map: list[BatchChannelConfig] = field(default_factory=list)
98
+ nuclear: BatchSegmentationConfig = field(default_factory=BatchSegmentationConfig)
99
+ cytoplasmic: BatchCytoplasmicConfig = field(default_factory=BatchCytoplasmicConfig)
100
+ spots: BatchSpotsConfig = field(default_factory=BatchSpotsConfig)
101
+ quantification: BatchQuantificationConfig = field(default_factory=BatchQuantificationConfig)
102
+
103
+ def to_dict(self) -> dict:
104
+ """Serialize the job config to a JSON-friendly dictionary.
105
+
106
+ Returns
107
+ -------
108
+ dict
109
+ JSON-compatible representation of the batch config.
110
+ """
111
+ payload = asdict(self)
112
+ payload["quantification"]["features"] = [
113
+ _serialize_feature(feature)
114
+ for feature in self.quantification.features
115
+ ]
116
+ return payload
117
+
118
+ @classmethod
119
+ def from_dict(cls, payload: dict) -> "BatchJobConfig":
120
+ """Hydrate a job config from a JSON payload.
121
+
122
+ Parameters
123
+ ----------
124
+ payload : dict
125
+ JSON-compatible representation of the batch config.
126
+
127
+ Returns
128
+ -------
129
+ BatchJobConfig
130
+ Parsed configuration instance.
131
+ """
132
+ channel_map = [
133
+ BatchChannelConfig(**item)
134
+ for item in payload.get("channel_map", [])
135
+ ]
136
+ nuclear = BatchSegmentationConfig(
137
+ **payload.get("nuclear", {})
138
+ )
139
+ cytoplasmic = BatchCytoplasmicConfig(
140
+ **payload.get("cytoplasmic", {})
141
+ )
142
+ spots = BatchSpotsConfig(
143
+ **payload.get("spots", {})
144
+ )
145
+ quant_payload = payload.get("quantification", {})
146
+ features = [
147
+ _deserialize_feature(item)
148
+ for item in quant_payload.get("features", [])
149
+ ]
150
+ quantification = BatchQuantificationConfig(
151
+ enabled=bool(quant_payload.get("enabled", False)),
152
+ format=quant_payload.get("format", "xlsx"),
153
+ features=features,
154
+ )
155
+ return cls(
156
+ input_path=payload.get("input_path", ""),
157
+ output_path=payload.get("output_path", ""),
158
+ extensions=list(payload.get("extensions", [])),
159
+ include_subfolders=bool(payload.get("include_subfolders", False)),
160
+ process_all_scenes=bool(payload.get("process_all_scenes", False)),
161
+ overwrite=bool(payload.get("overwrite", False)),
162
+ output_format=payload.get("output_format", "tif"),
163
+ channel_map=channel_map,
164
+ nuclear=nuclear,
165
+ cytoplasmic=cytoplasmic,
166
+ spots=spots,
167
+ quantification=quantification,
168
+ )
169
+
170
+ def save(self, path: str) -> None:
171
+ """Persist the configuration to disk.
172
+
173
+ Parameters
174
+ ----------
175
+ path : str
176
+ Destination file path for the JSON profile.
177
+ """
178
+ with open(path, "w", encoding="utf-8") as handle:
179
+ json.dump(self.to_dict(), handle, indent=2)
180
+
181
+ @classmethod
182
+ def load(cls, path: str) -> "BatchJobConfig":
183
+ """Load a configuration from disk.
184
+
185
+ Parameters
186
+ ----------
187
+ path : str
188
+ Source JSON profile file.
189
+
190
+ Returns
191
+ -------
192
+ BatchJobConfig
193
+ Loaded configuration instance.
194
+ """
195
+ with open(path, "r", encoding="utf-8") as handle:
196
+ payload = json.load(handle)
197
+ return cls.from_dict(payload)
198
+
199
+
200
+ def _serialize_feature(feature: FeatureConfig) -> dict:
201
+ """Serialize a Quantification feature into a JSON payload."""
202
+ return {
203
+ "feature_id": feature.feature_id,
204
+ "name": feature.name,
205
+ "type_name": feature.type_name,
206
+ "data": _serialize_feature_data(feature.data),
207
+ }
208
+
209
+
210
+ def _serialize_feature_data(data_obj: object) -> dict:
211
+ """Serialize feature-specific data payloads."""
212
+ if isinstance(data_obj, MarkerFeatureData):
213
+ return {
214
+ "type": "Markers",
215
+ "payload": asdict(data_obj),
216
+ }
217
+ if isinstance(data_obj, SpotsFeatureData):
218
+ return {
219
+ "type": "Spots",
220
+ "payload": asdict(data_obj),
221
+ }
222
+ return {"type": "Unknown", "payload": {}}
223
+
224
+
225
+ def _deserialize_feature(payload: dict) -> FeatureConfig:
226
+ """Deserialize a feature payload into a FeatureConfig."""
227
+ feature_id = payload.get("feature_id", "")
228
+ name = payload.get("name", "")
229
+ type_name = payload.get("type_name", "")
230
+ data_payload = payload.get("data", {})
231
+ data_type = data_payload.get("type")
232
+ data_obj = _deserialize_feature_data(data_type, data_payload.get("payload", {}))
233
+ if feature_id:
234
+ return FeatureConfig(
235
+ feature_id=feature_id,
236
+ name=name,
237
+ type_name=type_name,
238
+ data=data_obj,
239
+ )
240
+ return FeatureConfig(name=name, type_name=type_name, data=data_obj)
241
+
242
+
243
+ def _deserialize_feature_data(data_type: str, payload: dict):
244
+ """Deserialize feature payloads into feature data objects."""
245
+ if data_type == "Markers":
246
+ return MarkerFeatureData(
247
+ segmentations=[
248
+ MarkerSegmentationConfig(**item)
249
+ for item in payload.get("segmentations", [])
250
+ ],
251
+ channels=[
252
+ MarkerChannelConfig(**item)
253
+ for item in payload.get("channels", [])
254
+ ],
255
+ rois=[ROIConfig(**item) for item in payload.get("rois", [])],
256
+ )
257
+ if data_type == "Spots":
258
+ return SpotsFeatureData(
259
+ segmentations=[
260
+ SpotsSegmentationConfig(**item)
261
+ for item in payload.get("segmentations", [])
262
+ ],
263
+ channels=[
264
+ SpotsChannelConfig(**item)
265
+ for item in payload.get("channels", [])
266
+ ],
267
+ rois=[ROIConfig(**item) for item in payload.get("rois", [])],
268
+ export_colocalization=bool(payload.get("export_colocalization", False)),
269
+ )
270
+ return FeatureData()