senoquant 1.0.0b2__py3-none-any.whl → 1.0.0b3__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 (47) hide show
  1. senoquant/__init__.py +6 -2
  2. senoquant/_reader.py +1 -1
  3. senoquant/reader/core.py +201 -18
  4. senoquant/tabs/batch/backend.py +18 -3
  5. senoquant/tabs/batch/frontend.py +8 -4
  6. senoquant/tabs/quantification/features/marker/dialog.py +26 -6
  7. senoquant/tabs/quantification/features/marker/export.py +97 -24
  8. senoquant/tabs/quantification/features/marker/rows.py +2 -2
  9. senoquant/tabs/quantification/features/spots/dialog.py +41 -11
  10. senoquant/tabs/quantification/features/spots/export.py +163 -10
  11. senoquant/tabs/quantification/frontend.py +2 -2
  12. senoquant/tabs/segmentation/frontend.py +46 -9
  13. senoquant/tabs/segmentation/models/cpsam/model.py +1 -1
  14. senoquant/tabs/segmentation/models/default_2d/model.py +22 -77
  15. senoquant/tabs/segmentation/models/default_3d/model.py +8 -74
  16. senoquant/tabs/segmentation/stardist_onnx_utils/_csbdeep/tools/create_zip_contents.py +0 -0
  17. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/probe.py +13 -13
  18. senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/stardist_libs.py +171 -0
  19. senoquant/tabs/spots/frontend.py +42 -5
  20. senoquant/tabs/spots/models/ufish/details.json +17 -0
  21. senoquant/tabs/spots/models/ufish/model.py +129 -0
  22. senoquant/tabs/spots/ufish_utils/__init__.py +13 -0
  23. senoquant/tabs/spots/ufish_utils/core.py +357 -0
  24. senoquant/utils.py +1 -1
  25. senoquant-1.0.0b3.dist-info/METADATA +161 -0
  26. {senoquant-1.0.0b2.dist-info → senoquant-1.0.0b3.dist-info}/RECORD +41 -28
  27. {senoquant-1.0.0b2.dist-info → senoquant-1.0.0b3.dist-info}/top_level.txt +1 -0
  28. ufish/__init__.py +1 -0
  29. ufish/api.py +778 -0
  30. ufish/model/__init__.py +0 -0
  31. ufish/model/loss.py +62 -0
  32. ufish/model/network/__init__.py +0 -0
  33. ufish/model/network/spot_learn.py +50 -0
  34. ufish/model/network/ufish_net.py +204 -0
  35. ufish/model/train.py +175 -0
  36. ufish/utils/__init__.py +0 -0
  37. ufish/utils/img.py +418 -0
  38. ufish/utils/log.py +8 -0
  39. ufish/utils/spot_calling.py +115 -0
  40. senoquant/tabs/spots/models/rmp/details.json +0 -61
  41. senoquant/tabs/spots/models/rmp/model.py +0 -499
  42. senoquant/tabs/spots/models/udwt/details.json +0 -103
  43. senoquant/tabs/spots/models/udwt/model.py +0 -482
  44. senoquant-1.0.0b2.dist-info/METADATA +0 -193
  45. {senoquant-1.0.0b2.dist-info → senoquant-1.0.0b3.dist-info}/WHEEL +0 -0
  46. {senoquant-1.0.0b2.dist-info → senoquant-1.0.0b3.dist-info}/entry_points.txt +0 -0
  47. {senoquant-1.0.0b2.dist-info → senoquant-1.0.0b3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,357 @@
1
+ """UFish-based spot enhancement utilities.
2
+
3
+ This module wraps UFish inference for SenoQuant spot detection workflows.
4
+ It handles:
5
+
6
+ - optional import of UFish from site-packages or vendored sources,
7
+ - ONNX Runtime execution-provider selection,
8
+ - model/weights caching between calls, and
9
+ - default ONNX weight retrieval from the SenoQuant Hugging Face model repo.
10
+
11
+ Notes
12
+ -----
13
+ Weight loading priority is:
14
+
15
+ 1. explicit ``UFishConfig.weights_path``,
16
+ 2. legacy ``UFishConfig.load_from_internet``, then
17
+ 3. default ``ufish.onnx`` resolved via :func:`ensure_hf_model`.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from dataclasses import dataclass
23
+ from pathlib import Path
24
+ import sys
25
+ from types import MethodType
26
+ from typing import TYPE_CHECKING, Any, cast
27
+
28
+ import numpy as np
29
+
30
+ from senoquant.tabs.segmentation.models.hf import (
31
+ DEFAULT_REPO_ID,
32
+ ensure_hf_model,
33
+ )
34
+
35
+ try: # pragma: no cover - optional dependency
36
+ from ufish.api import UFish
37
+ except ImportError: # pragma: no cover - optional dependency
38
+ _repo_root = Path(__file__).resolve().parents[5]
39
+ _vendored_root = _repo_root / "_vendor" / "ufish"
40
+ if _vendored_root.exists():
41
+ vendored_root = str(_vendored_root)
42
+ if vendored_root not in sys.path:
43
+ sys.path.insert(0, vendored_root)
44
+ try:
45
+ from ufish.api import UFish
46
+ except ImportError:
47
+ UFish = None
48
+ else:
49
+ UFish = None
50
+
51
+ try: # pragma: no cover - optional dependency
52
+ import onnxruntime as ort
53
+ except ImportError: # pragma: no cover - optional dependency
54
+ ort = None
55
+
56
+ if TYPE_CHECKING: # pragma: no cover - typing only
57
+ from ufish.api import UFish as UFishType
58
+
59
+
60
+ @dataclass(slots=True)
61
+ class UFishConfig:
62
+ """Configuration for UFish enhancement.
63
+
64
+ Parameters
65
+ ----------
66
+ weights_path : str or None, optional
67
+ Explicit local path to ONNX/PyTorch weights. When provided, this path
68
+ is used directly and takes precedence over all other loading modes.
69
+ load_from_internet : bool, optional
70
+ Legacy compatibility mode that calls
71
+ ``UFish.load_weights_from_internet()`` directly.
72
+ device : {"cuda", "dml", "mps"} or None, optional
73
+ Preferred accelerator mode used to influence ONNX Runtime provider
74
+ ordering when constructing UFish sessions.
75
+ """
76
+
77
+ weights_path: str | None = None
78
+ load_from_internet: bool = False
79
+ device: str | None = None
80
+
81
+
82
+ class _UFishState:
83
+ """In-process cache for the UFish model and loaded weights."""
84
+
85
+ def __init__(self) -> None:
86
+ """Initialize empty cached state."""
87
+ self.model: UFishType | None = None
88
+ self.weights_loaded = False
89
+ self.device: str | None = None
90
+ self.weights_path: str | None = None
91
+
92
+
93
+ _UFISH_STATE = _UFishState()
94
+ _UFISH_HF_FILENAME = "ufish.onnx"
95
+
96
+
97
+ def _ensure_ufish_available() -> None:
98
+ """Raise a helpful error when UFish cannot be imported.
99
+
100
+ Raises
101
+ ------
102
+ ImportError
103
+ If the ``ufish`` package is unavailable from both normal and vendored
104
+ import locations.
105
+ """
106
+ if UFish is None: # pragma: no cover - import guard
107
+ msg = "ufish is required for spot enhancement."
108
+ raise ImportError(msg)
109
+
110
+
111
+ def _resolve_default_weights_path() -> Path:
112
+ """Resolve the default UFish ONNX path.
113
+
114
+ Returns
115
+ -------
116
+ pathlib.Path
117
+ Local path to ``ufish.onnx``. The file is downloaded to the
118
+ ``ufish_utils`` directory if it does not already exist.
119
+
120
+ Raises
121
+ ------
122
+ RuntimeError
123
+ If the Hugging Face download helper is unavailable or download fails.
124
+ """
125
+ target_dir = Path(__file__).resolve().parent
126
+ return ensure_hf_model(
127
+ _UFISH_HF_FILENAME,
128
+ target_dir,
129
+ repo_id=DEFAULT_REPO_ID,
130
+ )
131
+
132
+
133
+ def _preferred_providers() -> list[str]:
134
+ """Return ONNX Runtime providers ordered by GPU preference.
135
+
136
+ Returns
137
+ -------
138
+ list[str]
139
+ Providers available in the current runtime, ordered from most
140
+ preferred accelerator to CPU fallback.
141
+ """
142
+ if ort is None:
143
+ return []
144
+ available = set(ort.get_available_providers())
145
+ preferred = [
146
+ "CUDAExecutionProvider",
147
+ "ROCMExecutionProvider",
148
+ "DmlExecutionProvider",
149
+ "DirectMLExecutionProvider",
150
+ "CoreMLExecutionProvider",
151
+ "CPUExecutionProvider",
152
+ ]
153
+ providers = [provider for provider in preferred if provider in available]
154
+ return providers or list(available)
155
+
156
+
157
+ def _select_onnx_providers(device: str | None) -> list[str]:
158
+ """Choose execution providers for a requested device hint.
159
+
160
+ Parameters
161
+ ----------
162
+ device : str or None
163
+ Device hint from :class:`UFishConfig`.
164
+
165
+ Returns
166
+ -------
167
+ list[str]
168
+ Provider names to pass to ``onnxruntime.InferenceSession``.
169
+ """
170
+ preferred = _preferred_providers()
171
+ if not device:
172
+ return preferred
173
+ if device == "cuda":
174
+ return [
175
+ p
176
+ for p in preferred
177
+ if p in {"CUDAExecutionProvider", "CPUExecutionProvider"}
178
+ ]
179
+ if device == "dml":
180
+ return [
181
+ p
182
+ for p in preferred
183
+ if p
184
+ in {
185
+ "DmlExecutionProvider",
186
+ "DirectMLExecutionProvider",
187
+ "CPUExecutionProvider",
188
+ }
189
+ ]
190
+ if device == "mps":
191
+ return [
192
+ p
193
+ for p in preferred
194
+ if p in {"CoreMLExecutionProvider", "CPUExecutionProvider"}
195
+ ]
196
+ return preferred
197
+
198
+
199
+ def _patch_onnx_loader(model: UFishType) -> None:
200
+ """Monkey-patch UFish ONNX loader to use SenoQuant provider selection.
201
+
202
+ Parameters
203
+ ----------
204
+ model : UFishType
205
+ UFish instance whose private ``_load_onnx`` method will be replaced.
206
+ """
207
+ if ort is None:
208
+ return
209
+ ort_any = cast("Any", ort)
210
+
211
+ def _load_onnx(
212
+ self: UFishType,
213
+ onnx_path: str,
214
+ providers: list[str] | None = None,
215
+ ) -> None:
216
+ providers = providers or _select_onnx_providers(
217
+ getattr(self, "_device", None),
218
+ )
219
+ self.ort_session = ort_any.InferenceSession(
220
+ str(onnx_path),
221
+ providers=providers,
222
+ )
223
+ self.model = None
224
+
225
+ model._load_onnx = MethodType(_load_onnx, model) # noqa: SLF001
226
+
227
+
228
+ def _get_ufish(config: UFishConfig) -> UFishType:
229
+ """Return a cached UFish instance for the requested configuration.
230
+
231
+ Parameters
232
+ ----------
233
+ config : UFishConfig
234
+ Runtime configuration used to determine whether the cached model can be
235
+ reused or must be re-instantiated.
236
+
237
+ Returns
238
+ -------
239
+ UFishType
240
+ Ready-to-use UFish instance with patched ONNX loading behavior.
241
+ """
242
+ _ensure_ufish_available()
243
+ if _UFISH_STATE.model is None or _UFISH_STATE.device != config.device:
244
+ ufish_cls = cast("type[UFishType]", UFish)
245
+ ufish_any = cast("Any", ufish_cls)
246
+ if config.device:
247
+ _UFISH_STATE.model = ufish_any(device=config.device)
248
+ else:
249
+ _UFISH_STATE.model = ufish_any()
250
+ _patch_onnx_loader(cast("UFishType", _UFISH_STATE.model))
251
+ _UFISH_STATE.weights_loaded = False
252
+ _UFISH_STATE.device = config.device
253
+ _UFISH_STATE.weights_path = None
254
+ return cast("UFishType", _UFISH_STATE.model)
255
+
256
+
257
+ def _ensure_weights(model: UFishType, config: UFishConfig) -> None:
258
+ """Ensure model weights are loaded according to configuration.
259
+
260
+ Parameters
261
+ ----------
262
+ model : UFishType
263
+ Active UFish model instance.
264
+ config : UFishConfig
265
+ Weight source and device settings.
266
+
267
+ Raises
268
+ ------
269
+ RuntimeError
270
+ If neither Hugging Face/default loading nor fallback loading succeeds.
271
+ """
272
+ if config.weights_path:
273
+ weights_path = Path(config.weights_path).expanduser().resolve()
274
+ resolved_path = str(weights_path)
275
+ if _UFISH_STATE.weights_loaded and _UFISH_STATE.weights_path == resolved_path:
276
+ return
277
+ model.load_weights(resolved_path)
278
+ _UFISH_STATE.weights_loaded = True
279
+ _UFISH_STATE.weights_path = resolved_path
280
+ return
281
+
282
+ if config.load_from_internet:
283
+ if _UFISH_STATE.weights_loaded and _UFISH_STATE.weights_path == "internet":
284
+ return
285
+ model.load_weights_from_internet()
286
+ _UFISH_STATE.weights_loaded = True
287
+ _UFISH_STATE.weights_path = "internet"
288
+ return
289
+
290
+ try:
291
+ weights_path = _resolve_default_weights_path()
292
+ except RuntimeError:
293
+ # Keep legacy behavior when HF download dependencies are unavailable.
294
+ if _UFISH_STATE.weights_loaded and _UFISH_STATE.weights_path == "default":
295
+ return
296
+ model.load_weights()
297
+ _UFISH_STATE.weights_loaded = True
298
+ _UFISH_STATE.weights_path = "default"
299
+ return
300
+ except Exception as exc:
301
+ try:
302
+ if _UFISH_STATE.weights_loaded and _UFISH_STATE.weights_path == "default":
303
+ return
304
+ model.load_weights()
305
+ _UFISH_STATE.weights_loaded = True
306
+ _UFISH_STATE.weights_path = "default"
307
+ return
308
+ except Exception:
309
+ msg = (
310
+ "Could not load UFish weights from local default or Hugging Face. "
311
+ "Provide UFishConfig(weights_path=...) or ensure model download access."
312
+ )
313
+ raise RuntimeError(msg) from exc
314
+
315
+ resolved_path = str(weights_path)
316
+ if _UFISH_STATE.weights_loaded and _UFISH_STATE.weights_path == resolved_path:
317
+ return
318
+ model.load_weights(resolved_path)
319
+ _UFISH_STATE.weights_loaded = True
320
+ _UFISH_STATE.weights_path = resolved_path
321
+
322
+
323
+ def enhance_image(
324
+ image: np.ndarray,
325
+ *,
326
+ config: UFishConfig | None = None,
327
+ ) -> np.ndarray:
328
+ """Enhance an image using UFish.
329
+
330
+ Parameters
331
+ ----------
332
+ image : numpy.ndarray
333
+ Input image array. UFish supports 2D images and common 3D stack
334
+ layouts handled by UFish internally.
335
+ config : UFishConfig or None, optional
336
+ Optional runtime configuration. If omitted, default behavior is used.
337
+
338
+ Returns
339
+ -------
340
+ numpy.ndarray
341
+ Enhanced image produced by UFish with the same dimensionality as the
342
+ input image.
343
+
344
+ Raises
345
+ ------
346
+ ImportError
347
+ If UFish cannot be imported.
348
+ RuntimeError
349
+ If weights cannot be loaded from configured/default sources.
350
+ """
351
+ if config is None:
352
+ config = UFishConfig()
353
+ model = _get_ufish(config)
354
+ _ensure_weights(model, config)
355
+ image = np.asarray(image)
356
+ _pred_spots, enhanced = model.predict(image)
357
+ return np.asarray(enhanced)
senoquant/utils.py CHANGED
@@ -11,7 +11,7 @@ def layer_data_asarray(layer, *, squeeze: bool = True) -> np.ndarray:
11
11
  Parameters
12
12
  ----------
13
13
  layer : object
14
- Napari layer instance providing a ``data`` attribute.
14
+ napari layer instance providing a ``data`` attribute.
15
15
  squeeze : bool, optional
16
16
  Whether to remove singleton dimensions.
17
17
 
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: senoquant
3
+ Version: 1.0.0b3
4
+ Summary: napari plugin for spatial quantification of senescence markers in tissue imaging
5
+ Author: SenoQuant Contributors
6
+ Maintainer: SenoQuant Contributors
7
+ License: BSD-3-Clause
8
+ Project-URL: Homepage, https://github.com/HaamsRee/senoquant
9
+ Project-URL: Documentation, https://haamsree.github.io/senoquant/
10
+ Project-URL: Repository, https://github.com/HaamsRee/senoquant
11
+ Project-URL: Bug Tracker, https://github.com/HaamsRee/senoquant/issues
12
+ Keywords: napari,plugin,senescence,quantification,microscopy,image analysis,segmentation,spot detection
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Framework :: napari
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: BSD License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
22
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: bioio>=3.2.0
27
+ Requires-Dist: bioio-czi>=2.4.2
28
+ Requires-Dist: bioio-dv>=1.2.0
29
+ Requires-Dist: bioio-imageio>=1.3.0
30
+ Requires-Dist: bioio-lif>=1.4.0
31
+ Requires-Dist: bioio-nd2>=1.6.0
32
+ Requires-Dist: bioio-ome-tiff>=1.4.0
33
+ Requires-Dist: bioio-ome-zarr>=3.2.1
34
+ Requires-Dist: bioio-sldy>=1.4.0
35
+ Requires-Dist: bioio-tifffile>=1.3.0
36
+ Requires-Dist: bioio-tiff-glob>=1.2.0
37
+ Requires-Dist: numpy<=1.26.4,>=1.23
38
+ Requires-Dist: pandas>=2.0
39
+ Requires-Dist: cellpose==4.0.8
40
+ Requires-Dist: onnx>=1.16
41
+ Requires-Dist: onnxruntime>=1.21.0; platform_system == "Darwin"
42
+ Requires-Dist: onnxruntime-gpu>=1.21.0; platform_system != "Darwin"
43
+ Requires-Dist: openpyxl>=3.1
44
+ Requires-Dist: huggingface_hub>=0.23.0
45
+ Requires-Dist: scikit-image<0.25,>=0.22
46
+ Requires-Dist: scipy>=1.8
47
+ Requires-Dist: senoquant-stardist-ext>=0.1.1
48
+ Requires-Dist: dask[array]>=2024.4
49
+ Requires-Dist: dask[distributed]>=2024.4
50
+ Provides-Extra: gpu
51
+ Requires-Dist: cupy-cuda12x>=12.0; extra == "gpu"
52
+ Requires-Dist: cucim>=23.4; extra == "gpu"
53
+ Provides-Extra: all
54
+ Requires-Dist: napari[all]; extra == "all"
55
+ Requires-Dist: bioio>=3.2.0; extra == "all"
56
+ Requires-Dist: bioio-czi>=2.4.2; extra == "all"
57
+ Requires-Dist: bioio-dv>=1.2.0; extra == "all"
58
+ Requires-Dist: bioio-imageio>=1.3.0; extra == "all"
59
+ Requires-Dist: bioio-lif>=1.4.0; extra == "all"
60
+ Requires-Dist: bioio-nd2>=1.6.0; extra == "all"
61
+ Requires-Dist: bioio-ome-tiff>=1.4.0; extra == "all"
62
+ Requires-Dist: bioio-ome-zarr>=3.2.1; extra == "all"
63
+ Requires-Dist: bioio-sldy>=1.4.0; extra == "all"
64
+ Requires-Dist: bioio-tifffile>=1.3.0; extra == "all"
65
+ Requires-Dist: bioio-tiff-glob>=1.2.0; extra == "all"
66
+ Requires-Dist: numpy<=1.26.4,>=1.23; extra == "all"
67
+ Requires-Dist: pandas>=2.0; extra == "all"
68
+ Requires-Dist: cellpose==4.0.8; extra == "all"
69
+ Requires-Dist: onnx>=1.16; extra == "all"
70
+ Requires-Dist: onnxruntime>=1.21.0; platform_system == "Darwin" and extra == "all"
71
+ Requires-Dist: onnxruntime-gpu>=1.21.0; platform_system != "Darwin" and extra == "all"
72
+ Requires-Dist: openpyxl>=3.1; extra == "all"
73
+ Requires-Dist: huggingface_hub>=0.23.0; extra == "all"
74
+ Requires-Dist: scikit-image<0.25,>=0.22; extra == "all"
75
+ Requires-Dist: scipy>=1.8; extra == "all"
76
+ Requires-Dist: senoquant-stardist-ext>=0.1.1; extra == "all"
77
+ Requires-Dist: dask[array]>=2024.4; extra == "all"
78
+ Requires-Dist: dask[distributed]>=2024.4; extra == "all"
79
+ Requires-Dist: cupy-cuda12x>=12.0; extra == "all"
80
+ Requires-Dist: cucim>=23.4; extra == "all"
81
+ Dynamic: license-file
82
+
83
+ # SenoQuant
84
+
85
+ ![tests](https://github.com/HaamsRee/senoquant/actions/workflows/tests.yml/badge.svg)
86
+ [![PyPI version](https://badge.fury.io/py/senoquant.svg)](https://badge.fury.io/py/senoquant)
87
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
88
+ [![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
89
+
90
+ SenoQuant is a versatile [napari](https://napari.org/stable/index.html) plugin designed for comprehensive, accurate,
91
+ and unbiased spatial quantification and prediction of senescence markers
92
+ across diverse tissue contexts.
93
+
94
+ ## Features
95
+
96
+ - Segment nuclei and cytoplasm with built-in models, including StarDist ONNX, Cellpose SAM, and morphology-based models.
97
+ - Detect punctate spots with a U-FISH-based detector.
98
+ - Quantify marker intensity, morphology, spot counts, and spot colocalization.
99
+ - Run batch workflows across folders, including profile save/load and multi-scene support.
100
+ - Read microscopy formats via BioIO, including OME-TIFF, ND2, LIF, CZI, Zarr, and more.
101
+ - *Upcoming*: Integrate custom models for predicting senescence markers.
102
+
103
+ ## Installation
104
+
105
+ ### Installer (recommended)
106
+
107
+ #### Windows
108
+
109
+ Download the Windows installer (`.exe`) from the [latest release](https://github.com/HaamsRee/senoquant/releases/latest).
110
+
111
+ #### macOS
112
+
113
+ Download the macOS installer (`.pkg`) from the [latest release](https://github.com/HaamsRee/senoquant/releases/latest).
114
+
115
+ #### Linux
116
+
117
+ Installer support for Linux is under construction.
118
+
119
+ ### Manual installation
120
+
121
+ For conda/pip/uv setup, see the [developer installation guide](https://haamsree.github.io/senoquant/developer/installation/).
122
+
123
+ ## Quick start
124
+
125
+ Use the documentation workflow for the most up-to-date instructions.
126
+
127
+ - Start with the [installation guide](https://haamsree.github.io/senoquant/user/installation/).
128
+ - Follow the [quick start guide](https://haamsree.github.io/senoquant/user/quickstart/).
129
+ - Then use tab-specific guides for [segmentation](https://haamsree.github.io/senoquant/user/segmentation/), [spots](https://haamsree.github.io/senoquant/user/spots/), [quantification](https://haamsree.github.io/senoquant/user/quantification/), and [batch](https://haamsree.github.io/senoquant/user/batch/).
130
+
131
+ ## Documentation
132
+
133
+ Full documentation is available at [https://haamsree.github.io/senoquant/](https://haamsree.github.io/senoquant/).
134
+
135
+ - [Installation guide](https://haamsree.github.io/senoquant/user/installation/).
136
+ - [Quick start tutorial](https://haamsree.github.io/senoquant/user/quickstart/).
137
+ - [Segmentation models](https://haamsree.github.io/senoquant/user/segmentation/).
138
+ - [Spot detection](https://haamsree.github.io/senoquant/user/spots/).
139
+ - [Quantification features](https://haamsree.github.io/senoquant/user/quantification/).
140
+ - [Batch processing](https://haamsree.github.io/senoquant/user/batch/).
141
+ - [API reference](https://haamsree.github.io/senoquant/api/).
142
+
143
+ ## Development
144
+
145
+ See the [contributing guide](https://haamsree.github.io/senoquant/developer/contributing/) for development setup instructions.
146
+
147
+ ## How to cite
148
+
149
+ If you use SenoQuant in your research, please cite it using the metadata in `CITATION.cff`.
150
+
151
+ On GitHub, open the repository page and click `Cite this repository` in the right sidebar to copy a formatted citation.
152
+
153
+ ## Acknowledgements
154
+
155
+ SenoQuant builds on and integrates excellent open-source projects.
156
+
157
+ - [napari](https://napari.org/).
158
+ - [StarDist](https://github.com/stardist/stardist).
159
+ - [Cellpose](https://github.com/MouseLand/cellpose).
160
+ - [U-FISH](https://github.com/UFISH-Team/U-FISH).
161
+ - [BioIO](https://github.com/bioio-devs/bioio).
@@ -1,50 +1,50 @@
1
- senoquant/__init__.py,sha256=wuZx1cvZLPaNnraFygnXsvfwrIQaNk65ke-N2HZpQ40,132
2
- senoquant/_reader.py,sha256=4klOi8rQ77pK-DdyE17cTTwv7_DYxMecQc0KMYwwQWc,154
1
+ senoquant/__init__.py,sha256=mNRYmhG-SXPlokw7tiuHYRGLzqtfECSRH-QIpZiEJbk,269
2
+ senoquant/_reader.py,sha256=HVGhwQTuuDbvNM9tEkUpE6js_Lzh7vTHXdYfDCqvvXk,154
3
3
  senoquant/_widget.py,sha256=nuNaKvWAx7aKXORAipOUf7sUI5I3DvZazXnwrJcBqcw,1102
4
4
  senoquant/napari.yaml,sha256=2r1EpZcV1B3mLv0z3FwjS8e1T-yIMzoWvNj2SBqmftI,1664
5
- senoquant/utils.py,sha256=JAE1S_UUkrcNrEg2JKDB33VPqt4UWOFtH45hY5uPrbo,641
5
+ senoquant/utils.py,sha256=XpvJjaoN_9DMD-cxURCStFccBYNccttdJtGnFO6PD2E,641
6
6
  senoquant/reader/__init__.py,sha256=3lDuOpQC8TGUdfXdpLrr7MaszOVCqKMYM9YaTdq3DVQ,92
7
- senoquant/reader/core.py,sha256=C1BycDll6dgalqd6ikF28-KiI3gI2e0fonR60SZdpx8,10226
7
+ senoquant/reader/core.py,sha256=GGEU_FVFohhWR0KkbuTl50wdS04WzroBBC67gbwfLtA,15809
8
8
  senoquant/tabs/__init__.py,sha256=DnIT3E7XRSw2CmlZ-Ma4aYpoUFSFjF-66kMDNPaZEmU,371
9
9
  senoquant/tabs/batch/__init__.py,sha256=0-xDYyAEEch9Yq7OhGeTkgoXus52Y_SQjqvtIbI-I20,291
10
- senoquant/tabs/batch/backend.py,sha256=rFjpObFsnF4rpYxrcrctE7UGy9qSah_V1v1AlyL4KSw,24166
10
+ senoquant/tabs/batch/backend.py,sha256=R8cSMkPL8sf49-vNc7PnvWrLA3FQ_1KJ9KQHSUnd0Os,24727
11
11
  senoquant/tabs/batch/config.py,sha256=w6DR0Nw6BL0hrFacQPIAHb-wCirYnogYJgmAPy2j9zo,8639
12
- senoquant/tabs/batch/frontend.py,sha256=dFubaU1uvqRCKMAyx2owyTPERjkiRIrfXBkdZvujgUw,51811
12
+ senoquant/tabs/batch/frontend.py,sha256=_zhv2H7UneeMtB8jZ6YZhFGaqu6DhuAB6Q7BtHS3fxA,51987
13
13
  senoquant/tabs/batch/io.py,sha256=mggktbDDsGr4hQvpu4oj1eJcxG-xiPwfquO7QBesdDk,8382
14
14
  senoquant/tabs/batch/layers.py,sha256=JjWS6WVZ3YOd-KZ4AjqstRF0qTPwOxOgGHd5FXrer08,2078
15
15
  senoquant/tabs/quantification/__init__.py,sha256=iCqW7cg9QFfUdnYF7JSwOEus_tm66IZXdxSShy7RxwA,34
16
16
  senoquant/tabs/quantification/backend.py,sha256=uEHV-JNEXddj5jptKDSrz6Lnt3MIYTzmBu0aV0vjLDY,7337
17
- senoquant/tabs/quantification/frontend.py,sha256=HKMlkzUf5b8_N9OA5Ki6J5hW02JouBgr4IGtI6AUulQ,29068
17
+ senoquant/tabs/quantification/frontend.py,sha256=veDnWxwyVkXt60fdq85Nrv8XZJTowNxX5mpxaMO8qQA,29068
18
18
  senoquant/tabs/quantification/features/__init__.py,sha256=XR8nPIAGuVpDT8bqWH0qaI-GeZGp9JOKUD7F77dOd7s,2076
19
19
  senoquant/tabs/quantification/features/base.py,sha256=OIH_qwKYyKbTwXGhjQzgwNzoabMURActvmA-gUEoU_8,4018
20
20
  senoquant/tabs/quantification/features/roi.py,sha256=wLvFJJ1a2W5x4BOUDrLvou_rje1KmDzUp5nwQvzooTU,11397
21
21
  senoquant/tabs/quantification/features/marker/__init__.py,sha256=8twYCiUtoau-6rfcLCVndyKkaG1i9v9fGo6IfQ_Eyuo,98
22
22
  senoquant/tabs/quantification/features/marker/config.py,sha256=H0n4xY8ZFSVDIKmsDnQZr_nW0zPpL4PLyKMCtYOrprE,1793
23
- senoquant/tabs/quantification/features/marker/dialog.py,sha256=pnQVzt2RGSjAQ6oqswr2WY7sMk0skMSsLOj55hXFBw0,14886
24
- senoquant/tabs/quantification/features/marker/export.py,sha256=Tbk-TvK2cLCg-x8YH4F2jNXEXW2jOJ8-4-PqvZGJGXA,27210
23
+ senoquant/tabs/quantification/features/marker/dialog.py,sha256=89q5OjHAPG8wjoPKtdNLuFYRDAzLR1ysGJrxhcAJ7wU,15616
24
+ senoquant/tabs/quantification/features/marker/export.py,sha256=SNChfDTyr3rTwLmEs2sfYkLZ_EbdqTofKgbZeUyhJbI,29874
25
25
  senoquant/tabs/quantification/features/marker/feature.py,sha256=cWZqUm_KTR-vdQpVXK5FiHKCdMlSkJJ8IJjV3bhLUpM,3917
26
26
  senoquant/tabs/quantification/features/marker/morphology.py,sha256=eIwhZgTIoPXtJOUHLR9GJ4okaSCVBoJ3NFSzTQycZiI,8676
27
- senoquant/tabs/quantification/features/marker/rows.py,sha256=Uycekb1O5g7YXggUusgsL6rhJNJhT7IjEZUbKM6LcWI,23528
27
+ senoquant/tabs/quantification/features/marker/rows.py,sha256=PyvXVRodq3DjPuRj1o4IlqMzZh-N8bRT8Dy_fXiWjJQ,23528
28
28
  senoquant/tabs/quantification/features/marker/thresholding.py,sha256=jwyc_G774NgmWXElI29Z8j4cX0A8CPqs4PtsobCHCxc,1213
29
29
  senoquant/tabs/quantification/features/spots/__init__.py,sha256=XpfiHRHNCmCeaBWuTZsyy_qybswkYYVS_Y4oY885xe0,95
30
30
  senoquant/tabs/quantification/features/spots/config.py,sha256=wLSnDvYFWZRN7_D2ih4aCugSlTtNaC5CW3NzGKYoyCM,1616
31
- senoquant/tabs/quantification/features/spots/dialog.py,sha256=Ho5cgolzY9YPba4LdaAeE4IeJaMEV4TAUvPc0Gn68m0,15965
32
- senoquant/tabs/quantification/features/spots/export.py,sha256=e67oHcWg6v2wYUoFOGUROLVPSZictLVlEVAB6SbEiYA,42127
31
+ senoquant/tabs/quantification/features/spots/dialog.py,sha256=SzVR2je0HwrluK3KPOjoy-YBN4t6cevIvdFC8rJpfIg,17025
32
+ senoquant/tabs/quantification/features/spots/export.py,sha256=6f4BJEpTZYfDZlWH8aYhTdOzBYolb3KLc8YF-fj5R6Y,47525
33
33
  senoquant/tabs/quantification/features/spots/feature.py,sha256=8Zk-SbJDA-Ge9kx46oEisacVVrCJL3cb7LA_zivqWkw,3896
34
34
  senoquant/tabs/quantification/features/spots/morphology.py,sha256=toK9exTD3CDX3vEKFN2CcT14f-03ASTJxSpQv8ZfC1M,8498
35
35
  senoquant/tabs/quantification/features/spots/rows.py,sha256=9FPrWmNLN6MPeVKpi3knPakkwJ8kR0b4sW0WIMLgaoM,7291
36
36
  senoquant/tabs/segmentation/__init__.py,sha256=YKSbKlgW372MFEA7xxY3_CUUkXfKX6VSwdoHh_btIaU,32
37
37
  senoquant/tabs/segmentation/backend.py,sha256=9DCVEUEFG0zdl0c_IXa7vAiwLCZetkfGJVK_zdrXsIQ,4295
38
- senoquant/tabs/segmentation/frontend.py,sha256=CVvCbbErVaOG5y-Ds4Ot9y2_0YDYAiCH0-TOtmy-GtI,36560
38
+ senoquant/tabs/segmentation/frontend.py,sha256=8hJeyC9h-sjWso25A5SOIgaut0khXljI1uN2HpFOEq0,37987
39
39
  senoquant/tabs/segmentation/models/__init__.py,sha256=0_Jxlyc6wGeOoCPhLxKtcfWa8MqFhFm4-_3ca0zDhME,138
40
40
  senoquant/tabs/segmentation/models/base.py,sha256=ND518fqg0XuBNT2AWdlf796LEx8xOX9Jq2Ofcf-MsDY,4335
41
41
  senoquant/tabs/segmentation/models/hf.py,sha256=Ns9o3slFSq7Ipyj3u1KrJbJ9zKxykh8A6kjxkzH1A58,1845
42
42
  senoquant/tabs/segmentation/models/cpsam/details.json,sha256=A_obIZzrnSLw_JPCPX5wq2ZtqYuo0QE6Ctn_BpgwBC4,1239
43
- senoquant/tabs/segmentation/models/cpsam/model.py,sha256=U-NiFbci3xLx0e1OKcEq_AYtGAOY0_E-YTrJxvLPFAo,5175
43
+ senoquant/tabs/segmentation/models/cpsam/model.py,sha256=-Y4sqVH67LEj0A8C16aeDhj8KU5BUUbb75QYXRRg23I,5175
44
44
  senoquant/tabs/segmentation/models/default_2d/details.json,sha256=S5H14Fk2_dmQNI2_TsXyB6j8PxspmjWC7tNh23VnG80,1338
45
- senoquant/tabs/segmentation/models/default_2d/model.py,sha256=naNlaFMksND0iSjs2Q-sL-E49eIgsOL1LJxImiy1JA0,23619
45
+ senoquant/tabs/segmentation/models/default_2d/model.py,sha256=LzGyo_X3flZHjprHM4i5qkAry-dJJ-OXwD6l8w6az6Q,21647
46
46
  senoquant/tabs/segmentation/models/default_3d/details.json,sha256=a-5YI9Po-IYTG9qHylPd4MMm7ydkRZj2s3EV9sxwGLY,1348
47
- senoquant/tabs/segmentation/models/default_3d/model.py,sha256=oeJzb5G5Mgox1s8ddglxS6CVCQgVxLzj0E03pxeZ-mI,24196
47
+ senoquant/tabs/segmentation/models/default_3d/model.py,sha256=x8zBcoEXXLMMkS2cYGYnZTnl33n9_OjTHJzRJV3aAeM,21758
48
48
  senoquant/tabs/segmentation/models/nuclear_dilation/__init__.py,sha256=5rgBUSDK5ZoD6tKVSzF0OUtF2bbBA29HMffJ_CjPJkA,43
49
49
  senoquant/tabs/segmentation/models/nuclear_dilation/details.json,sha256=Vx3XY7PvgrM3EMwhRDeFTr9i7GdWohzO2If1eJ-oQoU,510
50
50
  senoquant/tabs/segmentation/models/nuclear_dilation/model.py,sha256=onLX1R9U-n0s3Dc64jmBbYBuyTRvems3czclgbqHAP4,3048
@@ -112,13 +112,14 @@ senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/__init__.py,sh
112
112
  senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/predict2d.py,sha256=h2eywW4LQZJTaktncG0LOuWr9DdR344O8aOzM6_RTqw,3442
113
113
  senoquant/tabs/segmentation/stardist_onnx_utils/_stardist/scripts/predict3d.py,sha256=rpdnoA5XPDjRQ-imu1GO4unbfaO5w8PlFLqd_5lAjvY,3581
114
114
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/__init__.py,sha256=uyQVHS-vUdONhvI1CDR718AmWPzMXPl9-6F0bL7sFBU,1430
115
+ senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/stardist_libs.py,sha256=caM1arDjZE4vfJVp61AkH2vqbrXUHssHHcTcL7eKu1I,5788
115
116
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/__init__.py,sha256=uimduhVV20E3qfJHjSXZlztQfODxdXm5hO4O7dnbsJc,349
116
117
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/cli.py,sha256=l4u5YhqO_aYVm-uNxfTUrndhmphBXvPDR7hCxTk2nYE,1356
117
118
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/convert/core.py,sha256=eRx2psv-jjBa5LThNZgxSEI9UjhRtyyWdxDutg3elQE,9038
118
119
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/__init__.py,sha256=bYIgnsxd_5Ek9XS5sHWuA5WMIpMpoQshId95FWPUm2I,438
119
120
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/cli.py,sha256=WlpZOHVqENkpUWMLHnH6AkmW5U6BAOQJaY0Nqlka_tQ,1082
120
121
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/divisibility.py,sha256=OwOpWxui47XI3J1xZTEJdu6El7qqqMSLDeEdIZTTMds,7212
121
- senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/probe.py,sha256=gf-y55GBI50n94UkCGijH9kVa-OZgeOAs5KwXVvLE9g,3220
122
+ senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/probe.py,sha256=9iDqCc_XAXXS9LQyT3vucCTB9TjnJcOpMssNKIHUFos,3219
122
123
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/receptive_field.py,sha256=XfwzLZaKX16Y6ybvUggRpsrXcWdFOHUpORhnD694r7Q,6213
123
124
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/rf_cli.py,sha256=mZ5TkHSWWEM8WKNQ-I7qVAOmS0mQ81n7CmsjzBejJzY,1325
124
125
  senoquant/tabs/segmentation/stardist_onnx_utils/onnx_framework/inspect/valid_sizes.py,sha256=Zec8DPn5EWgXwuiQ0Tw907Y-kxlRCTx5YUgRpbyevGI,7913
@@ -133,16 +134,28 @@ senoquant/tabs/settings/backend.py,sha256=ZVtmrUYNsox7DiVMlcS666XRyLG7GksgC818oo
133
134
  senoquant/tabs/settings/frontend.py,sha256=_hTWJHZeEtU6n6qke31R6Es63knKeHhWZYUZj0ep79s,721
134
135
  senoquant/tabs/spots/__init__.py,sha256=dYrAIzX3A5w4TOLRRadxL2agOte_Z0ennuEIOCbJD5w,25
135
136
  senoquant/tabs/spots/backend.py,sha256=LZdkNzw-bpK0NClbeLttpg4C_8AqnIFg1W4NaxepTSs,4547
136
- senoquant/tabs/spots/frontend.py,sha256=34rq06tOw1gBcuc6NGzM73QWvKbwLUxKLAAifruUGOY,26816
137
+ senoquant/tabs/spots/frontend.py,sha256=IGyT-rWbX_vVgaIiDkxkijt6EoAPdnkW2dKOvL2Ziwg,28151
137
138
  senoquant/tabs/spots/models/__init__.py,sha256=OKnBIi-aaBsuXmwQNeg4EKeV66gSscedXyZ1-O3cJhY,123
138
139
  senoquant/tabs/spots/models/base.py,sha256=VABmb2E7xvWOW8J60ZZkog0ZEG4XyW96qeXJMZVuKT8,2786
139
- senoquant/tabs/spots/models/rmp/details.json,sha256=ocSkURk8jrwZQidQhU6cwcpPukErmpq1RwLkyGn4-Nc,1243
140
- senoquant/tabs/spots/models/rmp/model.py,sha256=VwJluYX5NlF4crMsKfzncE9c5cPzX8c9x1l3xi7_pP4,17022
141
- senoquant/tabs/spots/models/udwt/details.json,sha256=wlZLTFdDFC2JD9Za5D-4fgIAbnZGRO6bSnV2j0pz9nE,2209
142
- senoquant/tabs/spots/models/udwt/model.py,sha256=Erg-HeFbz773rVyP28I8CAZ1UhbqNWpA4XwQhtWVjJU,14046
143
- senoquant-1.0.0b2.dist-info/licenses/LICENSE,sha256=wJjNEZJA6A7m6ozqNeq3tXi4X5gzbEGraFm2jw5ahG0,1509
144
- senoquant-1.0.0b2.dist-info/METADATA,sha256=SaAvLT9BIRXBWOGrb_VE8eBS5oH2twOmFgCWxvdT1AI,7279
145
- senoquant-1.0.0b2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
146
- senoquant-1.0.0b2.dist-info/entry_points.txt,sha256=_HUyyJcDeBQVdUKjY3ZW9fqvHLWFn2mPXS_9KBPIzuU,52
147
- senoquant-1.0.0b2.dist-info/top_level.txt,sha256=zD3JsHkIEr7T58xOr2E7mnQ7fqeju6swI2kSkKUPfX4,10
148
- senoquant-1.0.0b2.dist-info/RECORD,,
140
+ senoquant/tabs/spots/models/ufish/details.json,sha256=126sbAoU1SMCLCCphUKcTqh4HtKbPYDdgm41cNifMmA,312
141
+ senoquant/tabs/spots/models/ufish/model.py,sha256=iOxdQizYmQ8Fj-CvFjMkAEjFBKpwqC5gjxmHc9jfGBI,4236
142
+ senoquant/tabs/spots/ufish_utils/__init__.py,sha256=QH8ReVcWtg2_Mgx2Oxg6OZbcQ8ntp42lOMlaJoT3ZSE,394
143
+ senoquant/tabs/spots/ufish_utils/core.py,sha256=ZuJU8tkY3KJ9N-jMqMeYjsCcfhaZon44e1CcjxLR51Q,10649
144
+ senoquant-1.0.0b3.dist-info/licenses/LICENSE,sha256=wJjNEZJA6A7m6ozqNeq3tXi4X5gzbEGraFm2jw5ahG0,1509
145
+ ufish/__init__.py,sha256=ls1camlIoMxEZz9gSkZ1OJo-MXqHWwKPtdPbZJmwp7E,22
146
+ ufish/api.py,sha256=Nezcny6yTGMwdmB8qZv5dyCAeDq1RCSvMcAiZmGcn1s,29658
147
+ ufish/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
148
+ ufish/model/loss.py,sha256=J6Oj2Fg1Zt04NneBhdjTpvb0BBvDc4wWfSsAf5cY8RA,1707
149
+ ufish/model/train.py,sha256=jt4kciKbtnrRyHcu9x8RXvvKk3L01_KA_U7xxgQjZlY,6025
150
+ ufish/model/network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
151
+ ufish/model/network/spot_learn.py,sha256=yvyqXwqNHuc4bISo812GS7t6oJ_ZKcUuhlmpLYPeRek,1619
152
+ ufish/model/network/ufish_net.py,sha256=ssxuV1qoa7Iod1KiNwQDtnYR41_fOH9cuAroco_sRcw,6424
153
+ ufish/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
+ ufish/utils/img.py,sha256=8CkEZyWCKriCFuSq_qPphwmj-WPUrFMDyMGnRPQCA3k,12904
155
+ ufish/utils/log.py,sha256=_nF9sJJAMFqQJvvIUYI5o2ffAMTHmQhDVkp2EI3rsvc,280
156
+ ufish/utils/spot_calling.py,sha256=y7lSWOuxG7ca1nFz2uKC7x7aSzocqQu2p3tCijvvLSI,3970
157
+ senoquant-1.0.0b3.dist-info/METADATA,sha256=pY9mFrZO9gi6IBl4MGxM7y9XWrSN9pueFvzfh0nc6us,7269
158
+ senoquant-1.0.0b3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
159
+ senoquant-1.0.0b3.dist-info/entry_points.txt,sha256=_HUyyJcDeBQVdUKjY3ZW9fqvHLWFn2mPXS_9KBPIzuU,52
160
+ senoquant-1.0.0b3.dist-info/top_level.txt,sha256=n-FXEO-BsEDOq-ur29UIHcQLD-PgvSbN2eV1onngiSU,16
161
+ senoquant-1.0.0b3.dist-info/RECORD,,
ufish/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = '0.1.1'