celldetective 1.4.2__py3-none-any.whl → 1.5.0b0__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 (151) hide show
  1. celldetective/__init__.py +25 -0
  2. celldetective/__main__.py +62 -43
  3. celldetective/_version.py +1 -1
  4. celldetective/extra_properties.py +477 -399
  5. celldetective/filters.py +192 -97
  6. celldetective/gui/InitWindow.py +541 -411
  7. celldetective/gui/__init__.py +0 -15
  8. celldetective/gui/about.py +44 -39
  9. celldetective/gui/analyze_block.py +120 -84
  10. celldetective/gui/base/__init__.py +0 -0
  11. celldetective/gui/base/channel_norm_generator.py +335 -0
  12. celldetective/gui/base/components.py +249 -0
  13. celldetective/gui/base/feature_choice.py +92 -0
  14. celldetective/gui/base/figure_canvas.py +52 -0
  15. celldetective/gui/base/list_widget.py +133 -0
  16. celldetective/gui/{styles.py → base/styles.py} +92 -36
  17. celldetective/gui/base/utils.py +33 -0
  18. celldetective/gui/base_annotator.py +900 -767
  19. celldetective/gui/classifier_widget.py +6 -22
  20. celldetective/gui/configure_new_exp.py +777 -671
  21. celldetective/gui/control_panel.py +635 -524
  22. celldetective/gui/dynamic_progress.py +449 -0
  23. celldetective/gui/event_annotator.py +2023 -1662
  24. celldetective/gui/generic_signal_plot.py +1292 -944
  25. celldetective/gui/gui_utils.py +899 -1289
  26. celldetective/gui/interactions_block.py +658 -0
  27. celldetective/gui/interactive_timeseries_viewer.py +447 -0
  28. celldetective/gui/json_readers.py +48 -15
  29. celldetective/gui/layouts/__init__.py +5 -0
  30. celldetective/gui/layouts/background_model_free_layout.py +537 -0
  31. celldetective/gui/layouts/channel_offset_layout.py +134 -0
  32. celldetective/gui/layouts/local_correction_layout.py +91 -0
  33. celldetective/gui/layouts/model_fit_layout.py +372 -0
  34. celldetective/gui/layouts/operation_layout.py +68 -0
  35. celldetective/gui/layouts/protocol_designer_layout.py +96 -0
  36. celldetective/gui/pair_event_annotator.py +3130 -2435
  37. celldetective/gui/plot_measurements.py +586 -267
  38. celldetective/gui/plot_signals_ui.py +724 -506
  39. celldetective/gui/preprocessing_block.py +395 -0
  40. celldetective/gui/process_block.py +1678 -1831
  41. celldetective/gui/seg_model_loader.py +580 -473
  42. celldetective/gui/settings/__init__.py +0 -7
  43. celldetective/gui/settings/_cellpose_model_params.py +181 -0
  44. celldetective/gui/settings/_event_detection_model_params.py +95 -0
  45. celldetective/gui/settings/_segmentation_model_params.py +159 -0
  46. celldetective/gui/settings/_settings_base.py +77 -65
  47. celldetective/gui/settings/_settings_event_model_training.py +752 -526
  48. celldetective/gui/settings/_settings_measurements.py +1133 -964
  49. celldetective/gui/settings/_settings_neighborhood.py +574 -488
  50. celldetective/gui/settings/_settings_segmentation_model_training.py +779 -564
  51. celldetective/gui/settings/_settings_signal_annotator.py +329 -305
  52. celldetective/gui/settings/_settings_tracking.py +1304 -1094
  53. celldetective/gui/settings/_stardist_model_params.py +98 -0
  54. celldetective/gui/survival_ui.py +422 -312
  55. celldetective/gui/tableUI.py +1665 -1701
  56. celldetective/gui/table_ops/_maths.py +295 -0
  57. celldetective/gui/table_ops/_merge_groups.py +140 -0
  58. celldetective/gui/table_ops/_merge_one_hot.py +95 -0
  59. celldetective/gui/table_ops/_query_table.py +43 -0
  60. celldetective/gui/table_ops/_rename_col.py +44 -0
  61. celldetective/gui/thresholds_gui.py +382 -179
  62. celldetective/gui/viewers/__init__.py +0 -0
  63. celldetective/gui/viewers/base_viewer.py +700 -0
  64. celldetective/gui/viewers/channel_offset_viewer.py +331 -0
  65. celldetective/gui/viewers/contour_viewer.py +394 -0
  66. celldetective/gui/viewers/size_viewer.py +153 -0
  67. celldetective/gui/viewers/spot_detection_viewer.py +341 -0
  68. celldetective/gui/viewers/threshold_viewer.py +309 -0
  69. celldetective/gui/workers.py +304 -126
  70. celldetective/log_manager.py +92 -0
  71. celldetective/measure.py +1895 -1478
  72. celldetective/napari/__init__.py +0 -0
  73. celldetective/napari/utils.py +1025 -0
  74. celldetective/neighborhood.py +1914 -1448
  75. celldetective/preprocessing.py +1620 -1220
  76. celldetective/processes/__init__.py +0 -0
  77. celldetective/processes/background_correction.py +271 -0
  78. celldetective/processes/compute_neighborhood.py +894 -0
  79. celldetective/processes/detect_events.py +246 -0
  80. celldetective/processes/measure_cells.py +565 -0
  81. celldetective/processes/segment_cells.py +760 -0
  82. celldetective/processes/track_cells.py +435 -0
  83. celldetective/processes/train_segmentation_model.py +694 -0
  84. celldetective/processes/train_signal_model.py +265 -0
  85. celldetective/processes/unified_process.py +292 -0
  86. celldetective/regionprops/_regionprops.py +358 -317
  87. celldetective/relative_measurements.py +987 -710
  88. celldetective/scripts/measure_cells.py +313 -212
  89. celldetective/scripts/measure_relative.py +90 -46
  90. celldetective/scripts/segment_cells.py +165 -104
  91. celldetective/scripts/segment_cells_thresholds.py +96 -68
  92. celldetective/scripts/track_cells.py +198 -149
  93. celldetective/scripts/train_segmentation_model.py +324 -201
  94. celldetective/scripts/train_signal_model.py +87 -45
  95. celldetective/segmentation.py +844 -749
  96. celldetective/signals.py +3514 -2861
  97. celldetective/tracking.py +30 -15
  98. celldetective/utils/__init__.py +0 -0
  99. celldetective/utils/cellpose_utils/__init__.py +133 -0
  100. celldetective/utils/color_mappings.py +42 -0
  101. celldetective/utils/data_cleaning.py +630 -0
  102. celldetective/utils/data_loaders.py +450 -0
  103. celldetective/utils/dataset_helpers.py +207 -0
  104. celldetective/utils/downloaders.py +197 -0
  105. celldetective/utils/event_detection/__init__.py +8 -0
  106. celldetective/utils/experiment.py +1782 -0
  107. celldetective/utils/image_augmenters.py +308 -0
  108. celldetective/utils/image_cleaning.py +74 -0
  109. celldetective/utils/image_loaders.py +926 -0
  110. celldetective/utils/image_transforms.py +335 -0
  111. celldetective/utils/io.py +62 -0
  112. celldetective/utils/mask_cleaning.py +348 -0
  113. celldetective/utils/mask_transforms.py +5 -0
  114. celldetective/utils/masks.py +184 -0
  115. celldetective/utils/maths.py +351 -0
  116. celldetective/utils/model_getters.py +325 -0
  117. celldetective/utils/model_loaders.py +296 -0
  118. celldetective/utils/normalization.py +380 -0
  119. celldetective/utils/parsing.py +465 -0
  120. celldetective/utils/plots/__init__.py +0 -0
  121. celldetective/utils/plots/regression.py +53 -0
  122. celldetective/utils/resources.py +34 -0
  123. celldetective/utils/stardist_utils/__init__.py +104 -0
  124. celldetective/utils/stats.py +90 -0
  125. celldetective/utils/types.py +21 -0
  126. {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/METADATA +1 -1
  127. celldetective-1.5.0b0.dist-info/RECORD +187 -0
  128. {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/WHEEL +1 -1
  129. tests/gui/test_new_project.py +129 -117
  130. tests/gui/test_project.py +127 -79
  131. tests/test_filters.py +39 -15
  132. tests/test_notebooks.py +8 -0
  133. tests/test_tracking.py +232 -13
  134. tests/test_utils.py +123 -77
  135. celldetective/gui/base_components.py +0 -23
  136. celldetective/gui/layouts.py +0 -1602
  137. celldetective/gui/processes/compute_neighborhood.py +0 -594
  138. celldetective/gui/processes/measure_cells.py +0 -360
  139. celldetective/gui/processes/segment_cells.py +0 -499
  140. celldetective/gui/processes/track_cells.py +0 -303
  141. celldetective/gui/processes/train_segmentation_model.py +0 -270
  142. celldetective/gui/processes/train_signal_model.py +0 -108
  143. celldetective/gui/table_ops/merge_groups.py +0 -118
  144. celldetective/gui/viewers.py +0 -1354
  145. celldetective/io.py +0 -3663
  146. celldetective/utils.py +0 -3108
  147. celldetective-1.4.2.dist-info/RECORD +0 -123
  148. /celldetective/{gui/processes → processes}/downloader.py +0 -0
  149. {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/entry_points.txt +0 -0
  150. {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/licenses/LICENSE +0 -0
  151. {celldetective-1.4.2.dist-info → celldetective-1.5.0b0.dist-info}/top_level.txt +0 -0
celldetective/filters.py CHANGED
@@ -1,155 +1,250 @@
1
- from skimage.filters import difference_of_gaussians, threshold_multiotsu, threshold_otsu, threshold_local, \
2
- threshold_niblack, threshold_sauvola
3
- from celldetective.utils import interpolate_nan
4
- import scipy.ndimage as snd
1
+ import numpy
2
+
3
+ from celldetective.utils.image_cleaning import interpolate_nan
5
4
  import numpy as np
6
5
 
6
+
7
7
  def gauss_filter(img, sigma, interpolate=True, *kwargs):
8
+ import scipy.ndimage as snd
8
9
 
9
- if np.any(img!=img) and interpolate:
10
- img = interpolate_nan(img.astype(float))
10
+ if np.any(img != img) and interpolate:
11
+ img = interpolate_nan(img.astype(float))
12
+
13
+ return snd.gaussian_filter(img.astype(float), sigma, *kwargs)
11
14
 
12
- return snd.gaussian_filter(img.astype(float), sigma, *kwargs)
13
15
 
14
16
  def median_filter(img, size, interpolate=True, *kwargs):
15
17
 
16
- if np.any(img!=img) and interpolate:
17
- img = interpolate_nan(img.astype(float))
18
+ if np.any(img != img) and interpolate:
19
+ img = interpolate_nan(img.astype(float))
20
+
21
+ size = int(size)
22
+
23
+ import scipy.ndimage as snd
24
+
25
+ return snd.median_filter(img, size, *kwargs)
18
26
 
19
- size = int(size)
20
-
21
- return snd.median_filter(img, size, *kwargs)
22
27
 
23
28
  def maximum_filter(img, size, interpolate=True, *kwargs):
24
- if np.any(img!=img) and interpolate:
25
- img = interpolate_nan(img.astype(float))
29
+ if np.any(img != img) and interpolate:
30
+ img = interpolate_nan(img.astype(float))
31
+
32
+ import scipy.ndimage as snd
33
+
34
+ return snd.maximum_filter(img.astype(float), size, *kwargs)
26
35
 
27
- return snd.maximum_filter(img.astype(float), size, *kwargs)
28
36
 
29
37
  def minimum_filter(img, size, interpolate=True, *kwargs):
30
- if np.any(img!=img) and interpolate:
31
- img = interpolate_nan(img.astype(float))
38
+ if np.any(img != img) and interpolate:
39
+ img = interpolate_nan(img.astype(float))
40
+
41
+ import scipy.ndimage as snd
42
+
43
+ return snd.minimum_filter(img.astype(float), size, *kwargs)
32
44
 
33
- return snd.minimum_filter(img.astype(float), size, *kwargs)
34
45
 
35
46
  def percentile_filter(img, percentile, size, interpolate=True, *kwargs):
36
- if np.any(img!=img) and interpolate:
37
- img = interpolate_nan(img.astype(float))
47
+ if np.any(img != img) and interpolate:
48
+ img = interpolate_nan(img.astype(float))
49
+
50
+ import scipy.ndimage as snd
51
+
52
+ return snd.percentile_filter(img.astype(float), percentile, size, *kwargs)
38
53
 
39
- return snd.percentile_filter(img.astype(float), percentile, size, *kwargs)
40
54
 
41
55
  def subtract_filter(img, value, *kwargs):
42
- return img.astype(float) - value
56
+ return img.astype(float) - value
57
+
43
58
 
44
59
  def abs_filter(img, *kwargs):
45
- return np.abs(img)
60
+ return np.abs(img)
61
+
46
62
 
47
63
  def ln_filter(img, interpolate=True, *kwargs):
48
- if np.any(img!=img) and interpolate:
49
- img = interpolate_nan(img.astype(float))
64
+ if np.any(img != img) and interpolate:
65
+ img = interpolate_nan(img.astype(float))
50
66
 
51
- img[np.where(img>0.)] = np.log(img[np.where(img>0.)])
52
- img[np.where(img<=0.)] = 0.
67
+ img[np.where(img > 0.0)] = np.log(img[np.where(img > 0.0)])
68
+ img[np.where(img <= 0.0)] = 0.0
69
+
70
+ return img
53
71
 
54
- return img
55
72
 
56
73
  def variance_filter(img, size, interpolate=True):
57
74
 
58
- if np.any(img!=img) and interpolate:
59
- img = interpolate_nan(img.astype(float))
75
+ if np.any(img != img) and interpolate:
76
+ img = interpolate_nan(img.astype(float))
77
+
78
+ size = int(size)
79
+ img = img.astype(float)
80
+ import scipy.ndimage as snd
60
81
 
61
- size = int(size)
62
- img = img.astype(float)
63
- win_mean = snd.uniform_filter(img, (size,size), mode='wrap')
64
- win_sqr_mean = snd.uniform_filter(img**2, (size,size), mode='wrap')
65
- img = win_sqr_mean - win_mean**2
82
+ win_mean = snd.uniform_filter(img, (size, size), mode="wrap")
83
+ win_sqr_mean = snd.uniform_filter(img**2, (size, size), mode="wrap")
84
+ img = win_sqr_mean - win_mean**2
85
+
86
+ return img
66
87
 
67
- return img
68
88
 
69
89
  def std_filter(img, size, interpolate=True):
70
90
 
71
- if np.any(img!=img) and interpolate:
72
- img = interpolate_nan(img.astype(float))
73
-
74
- size = int(size)
75
- img = img.astype(float)
76
-
77
- win_mean = snd.uniform_filter(img, (size,size), mode='wrap')
78
- win_sqr_mean = snd.uniform_filter(img**2, (size, size), mode='wrap')
79
- win_sqr_mean[win_sqr_mean<=0.] = 0. # add this to prevent sqrt from breaking
80
-
81
- sub = np.subtract(win_sqr_mean,win_mean**2)
82
- sub[sub<=0.] = 0.
83
- img = np.sqrt(sub)
84
-
85
- return img
91
+ if np.any(img != img) and interpolate:
92
+ img = interpolate_nan(img.astype(float))
93
+
94
+ size = int(size)
95
+ img = img.astype(float)
96
+
97
+ import scipy.ndimage as snd
98
+
99
+ win_mean = snd.uniform_filter(img, (size, size), mode="wrap")
100
+ win_sqr_mean = snd.uniform_filter(img**2, (size, size), mode="wrap")
101
+ win_sqr_mean[win_sqr_mean <= 0.0] = 0.0 # add this to prevent sqrt from breaking
102
+
103
+ sub = np.subtract(win_sqr_mean, win_mean**2)
104
+ sub[sub <= 0.0] = 0.0
105
+ img = np.sqrt(sub)
106
+
107
+ return img
108
+
86
109
 
87
110
  def laplace_filter(img, output=float, interpolate=True, *kwargs):
88
- if np.any(img!=img) and interpolate:
89
- img = interpolate_nan(img.astype(float))
90
- return snd.laplace(img.astype(float), *kwargs)
91
-
92
- def dog_filter(img, blob_size=None, sigma_low=1, sigma_high=2, interpolate=True, *kwargs):
93
-
94
- if np.any(img!=img) and interpolate:
95
- img = interpolate_nan(img.astype(float))
96
- if blob_size is not None:
97
- sigma_low = 1.0 / (1.0 + np.sqrt(2)) * blob_size
98
- sigma_high = np.sqrt(2)*sigma_low
99
- return difference_of_gaussians(img.astype(float), sigma_low, sigma_high, *kwargs)
111
+ if np.any(img != img) and interpolate:
112
+ img = interpolate_nan(img.astype(float))
113
+ import scipy.ndimage as snd
114
+
115
+ return snd.laplace(img.astype(float), *kwargs)
116
+
117
+
118
+ def dog_filter(
119
+ img, blob_size=None, sigma_low=1, sigma_high=2, interpolate=True, *kwargs
120
+ ):
121
+
122
+ if np.any(img != img) and interpolate:
123
+ img = interpolate_nan(img.astype(float))
124
+ if blob_size is not None:
125
+ sigma_low = 1.0 / (1.0 + np.sqrt(2)) * blob_size
126
+ sigma_high = np.sqrt(2) * sigma_low
127
+ from skimage.filters import difference_of_gaussians
128
+
129
+ return difference_of_gaussians(img.astype(float), sigma_low, sigma_high, *kwargs)
130
+
100
131
 
101
132
  def otsu_filter(img, *kwargs):
102
- thresh = threshold_otsu(img.astype(float))
103
- binary = img >= thresh
104
- return binary.astype(float)
133
+ from skimage.filters import threshold_otsu
134
+
135
+ thresh = threshold_otsu(img.astype(float))
136
+ binary = img >= thresh
137
+ return binary.astype(float)
138
+
105
139
 
106
140
  def multiotsu_filter(img, classes=3, *kwargs):
107
- thresholds = threshold_multiotsu(img, classes=classes)
108
- regions = np.digitize(img, bins=thresholds)
109
- return regions.astype(float)
110
-
141
+ from skimage.filters import threshold_multiotsu
142
+
143
+ thresholds = threshold_multiotsu(img, classes=classes)
144
+ regions = np.digitize(img, bins=thresholds)
145
+ return regions.astype(float)
146
+
147
+
111
148
  def local_filter(img, *kwargs):
112
- thresh = threshold_local(img.astype(float), *kwargs)
113
- binary = img >= thresh
114
- return binary.astype(float)
149
+ from skimage.filters import threshold_local
150
+
151
+ thresh = threshold_local(img.astype(float), *kwargs)
152
+ binary = img >= thresh
153
+ return binary.astype(float)
154
+
115
155
 
116
156
  def niblack_filter(img, *kwargs):
117
157
 
118
- thresh = threshold_niblack(img, *kwargs)
119
- binary = img >= thresh
120
- return binary.astype(float)
158
+ from skimage.filters import threshold_niblack
159
+
160
+ thresh = threshold_niblack(img, *kwargs)
161
+ binary = img >= thresh
162
+ return binary.astype(float)
163
+
121
164
 
122
165
  def sauvola_filter(img, *kwargs):
123
166
 
124
- thresh = threshold_sauvola(img, *kwargs)
125
- binary = img >= thresh
126
- return binary.astype(float)
167
+ from skimage.filters import threshold_sauvola
168
+
169
+ thresh = threshold_sauvola(img, *kwargs)
170
+ binary = img >= thresh
171
+ return binary.astype(float)
172
+
127
173
 
128
174
  def log_filter(img, blob_size=None, sigma=1, interpolate=True, *kwargs):
129
175
 
130
- if np.any(img!=img) and interpolate:
131
- img = interpolate_nan(img.astype(float))
132
- if blob_size is not None:
133
- sigma_low = 1.0 / (1.0 + np.sqrt(2)) * blob_size
134
- sigma_high = np.sqrt(2)*sigma_low
176
+ if np.any(img != img) and interpolate:
177
+ img = interpolate_nan(img.astype(float))
178
+ if blob_size is not None:
179
+ sigma_low = 1.0 / (1.0 + np.sqrt(2)) * blob_size
180
+ sigma_high = np.sqrt(2) * sigma_low
181
+
182
+ import scipy.ndimage as snd
183
+
184
+ return snd.gaussian_laplace(img.astype(float), sigma, *kwargs)
135
185
 
136
- return snd.gaussian_laplace(img.astype(float), sigma, *kwargs)
137
186
 
138
187
  def tophat_filter(img, size, connectivity=4, interpolate=True, *kwargs):
139
-
140
- if np.any(img!=img) and interpolate:
141
- img = interpolate_nan(img.astype(float))
142
- structure = snd.generate_binary_structure(rank=2, connectivity=connectivity)
143
- img = snd.white_tophat(img.astype(float), structure=structure, size=size, *kwargs)
144
- return img
188
+
189
+ if np.any(img != img) and interpolate:
190
+ img = interpolate_nan(img.astype(float))
191
+ import scipy.ndimage as snd
192
+
193
+ structure = snd.generate_binary_structure(rank=2, connectivity=connectivity)
194
+ img = snd.white_tophat(img.astype(float), structure=structure, size=size, *kwargs)
195
+ return img
196
+
145
197
 
146
198
  def invert_filter(img, value=65535, *kwargs):
147
-
148
- img = img.astype(float)
149
199
 
150
- image_fill = np.zeros_like(img)
151
- image_fill[:,:] = value
200
+ img = img.astype(float)
201
+
202
+ image_fill = np.zeros_like(img)
203
+ image_fill[:, :] = value
204
+
205
+ inverted = np.subtract(image_fill, img, where=img == img)
206
+ return inverted
207
+
208
+
209
+ def filter_image(img, filters=None):
210
+ """
211
+
212
+ Apply one or more image filters to the input image.
213
+
214
+ Parameters
215
+ ----------
216
+ img : ndarray
217
+ The input image to be filtered.
218
+ filters : list or None, optional
219
+ A list of filters to be applied to the image. Each filter is represented as a tuple or list with the first element being
220
+ the filter function name (minus the '_filter' extension, as listed in software.filters) and the subsequent elements being
221
+ the arguments for that filter function. If None, the original image is returned without any filtering applied. Default is None.
222
+
223
+ Returns
224
+ -------
225
+ ndarray
226
+ The filtered image.
227
+
228
+ Notes
229
+ -----
230
+ This function applies a series of image filters to the input image. The filters are specified as a list of tuples,
231
+ where each tuple contains the name of the filter function and its corresponding arguments. The filters are applied
232
+ sequentially to the image. If no filters are provided, the original image is returned unchanged.
233
+
234
+ Examples
235
+ --------
236
+ >>> image = np.random.rand(256, 256)
237
+ >>> filtered_image = filter_image(image, filters=[('gaussian', 3), ('median', 5)])
238
+
239
+ """
240
+
241
+ if filters is None:
242
+ return img
152
243
 
153
- inverted = np.subtract(image_fill, img, where=img==img)
154
- return inverted
244
+ if img.ndim == 3:
245
+ img = np.squeeze(img)
155
246
 
247
+ for f in filters:
248
+ func = eval(f[0] + "_filter")
249
+ img = func(img, *f[1:])
250
+ return img