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
@@ -0,0 +1,351 @@
1
+ from typing import Union, List
2
+ import numpy as np
3
+
4
+
5
+ def step_function(t: Union[np.ndarray, List], t_shift: float, dt: float) -> np.ndarray:
6
+ """
7
+ Computes a step function using the logistic sigmoid function.
8
+
9
+ This function calculates the value of a sigmoid function, which is often used to model
10
+ a step change or transition. The sigmoid function is defined as:
11
+
12
+ .. math::
13
+ f(t) = \\frac{1}{1 + \\exp{\\left( -\\frac{t - t_{shift}}{dt} \\right)}}
14
+
15
+ where `t` is the input variable, `t_shift` is the point of the transition, and `dt` controls
16
+ the steepness of the transition.
17
+
18
+ Parameters
19
+ ----------
20
+ t : array_like
21
+ The input values for which the step function will be computed.
22
+ t_shift : float
23
+ The point in the `t` domain where the transition occurs.
24
+ dt : float
25
+ The parameter that controls the steepness of the transition. Smaller values make the
26
+ transition steeper, while larger values make it smoother.
27
+
28
+ Returns
29
+ -------
30
+ array_like
31
+ The computed values of the step function for each value in `t`.
32
+
33
+ Examples
34
+ --------
35
+ >>> import numpy as np
36
+ >>> t = np.array([0, 1, 2, 3, 4, 5])
37
+ >>> t_shift = 2
38
+ >>> dt = 1
39
+ >>> step_function(t, t_shift, dt)
40
+ array([0.26894142, 0.37754067, 0.5 , 0.62245933, 0.73105858, 0.81757448])
41
+ """
42
+
43
+ return 1 / (1 + np.exp(-(t - t_shift) / dt))
44
+
45
+
46
+ def derivative(x, timeline, window, mode="bi"):
47
+ """
48
+ Compute the derivative of a given array of values with respect to time using a specified numerical differentiation method.
49
+
50
+ Parameters
51
+ ----------
52
+ x : array_like
53
+ The input array of values.
54
+ timeline : array_like
55
+ The array representing the time points corresponding to the input values.
56
+ window : int
57
+ The size of the window used for numerical differentiation. Must be a positive odd integer.
58
+ mode : {'bi', 'forward', 'backward'}, optional
59
+ The numerical differentiation method to be used:
60
+ - 'bi' (default): Bidirectional differentiation using a symmetric window.
61
+ - 'forward': Forward differentiation using a one-sided window.
62
+ - 'backward': Backward differentiation using a one-sided window.
63
+
64
+ Returns
65
+ -------
66
+ dxdt : ndarray
67
+ The computed derivative values of the input array with respect to time.
68
+
69
+ Raises
70
+ ------
71
+ AssertionError
72
+ If the window size is not an odd integer and mode is 'bi'.
73
+
74
+ Notes
75
+ -----
76
+ - For 'bi' mode, the window size must be an odd number.
77
+ - For 'forward' mode, the derivative at the edge points may not be accurate due to the one-sided window.
78
+ - For 'backward' mode, the derivative at the first few points may not be accurate due to the one-sided window.
79
+
80
+ Examples
81
+ --------
82
+ >>> import numpy as np
83
+ >>> x = np.array([1, 2, 4, 7, 11])
84
+ >>> timeline = np.array([0, 1, 2, 3, 4])
85
+ >>> window = 3
86
+ >>> derivative(x, timeline, window, mode='bi')
87
+ array([3., 3., 3.])
88
+
89
+ >>> derivative(x, timeline, window, mode='forward')
90
+ array([1., 2., 3.])
91
+
92
+ >>> derivative(x, timeline, window, mode='backward')
93
+ array([3., 3., 3., 3.])
94
+ """
95
+
96
+ # modes = bi, forward, backward
97
+ dxdt = np.zeros(len(x))
98
+ dxdt[:] = np.nan
99
+
100
+ if mode == "bi":
101
+ assert window % 2 == 1, "Please set an odd window for the bidirectional mode"
102
+ lower_bound = window // 2
103
+ upper_bound = len(x) - window // 2
104
+ elif mode == "forward":
105
+ lower_bound = 0
106
+ upper_bound = len(x) - window
107
+ elif mode == "backward":
108
+ lower_bound = window
109
+ upper_bound = len(x)
110
+
111
+ for t in range(lower_bound, upper_bound):
112
+ if mode == "bi":
113
+ dxdt[t] = (x[t + window // 2] - x[t - window // 2]) / (
114
+ timeline[t + window // 2] - timeline[t - window // 2]
115
+ )
116
+ elif mode == "forward":
117
+ dxdt[t] = (x[t + window] - x[t]) / (timeline[t + window] - timeline[t])
118
+ elif mode == "backward":
119
+ dxdt[t] = (x[t] - x[t - window]) / (timeline[t] - timeline[t - window])
120
+ return dxdt
121
+
122
+
123
+ def differentiate_per_track(tracks, measurement, window_size=3, mode="bi"):
124
+
125
+ groupby_cols = ["TRACK_ID"]
126
+ if "position" in list(tracks.columns):
127
+ groupby_cols = ["position"] + groupby_cols
128
+
129
+ tracks = tracks.sort_values(by=groupby_cols + ["FRAME"], ignore_index=True)
130
+ tracks = tracks.reset_index(drop=True)
131
+ for tid, group in tracks.groupby(groupby_cols):
132
+ indices = group.index
133
+ timeline = group["FRAME"].values
134
+ signal = group[measurement].values
135
+ dsignal = derivative(signal, timeline, window_size, mode=mode)
136
+ tracks.loc[indices, "d/dt." + measurement] = dsignal
137
+ return tracks
138
+
139
+
140
+ def velocity_per_track(tracks, window_size=3, mode="bi"):
141
+
142
+ groupby_cols = ["TRACK_ID"]
143
+ if "position" in list(tracks.columns):
144
+ groupby_cols = ["position"] + groupby_cols
145
+
146
+ tracks = tracks.sort_values(by=groupby_cols + ["FRAME"], ignore_index=True)
147
+ tracks = tracks.reset_index(drop=True)
148
+ for tid, group in tracks.groupby(groupby_cols):
149
+ indices = group.index
150
+ timeline = group["FRAME"].values
151
+ x = group["POSITION_X"].values
152
+ y = group["POSITION_Y"].values
153
+ v = velocity(x, y, timeline, window=window_size, mode=mode)
154
+ v_abs = magnitude_velocity(v)
155
+ tracks.loc[indices, "velocity"] = v_abs
156
+ return tracks
157
+
158
+
159
+ def velocity(x, y, timeline, window, mode="bi"):
160
+ """
161
+ Compute the velocity vector of a given 2D trajectory represented by arrays of x and y coordinates
162
+ with respect to time using a specified numerical differentiation method.
163
+
164
+ Parameters
165
+ ----------
166
+ x : array_like
167
+ The array of x-coordinates of the trajectory.
168
+ y : array_like
169
+ The array of y-coordinates of the trajectory.
170
+ timeline : array_like
171
+ The array representing the time points corresponding to the x and y coordinates.
172
+ window : int
173
+ The size of the window used for numerical differentiation. Must be a positive odd integer.
174
+ mode : {'bi', 'forward', 'backward'}, optional
175
+ The numerical differentiation method to be used:
176
+ - 'bi' (default): Bidirectional differentiation using a symmetric window.
177
+ - 'forward': Forward differentiation using a one-sided window.
178
+ - 'backward': Backward differentiation using a one-sided window.
179
+
180
+ Returns
181
+ -------
182
+ v : ndarray
183
+ The computed velocity vector of the 2D trajectory with respect to time.
184
+ The first column represents the x-component of velocity, and the second column represents the y-component.
185
+
186
+ Raises
187
+ ------
188
+ AssertionError
189
+ If the window size is not an odd integer and mode is 'bi'.
190
+
191
+ Notes
192
+ -----
193
+ - For 'bi' mode, the window size must be an odd number.
194
+ - For 'forward' mode, the velocity at the edge points may not be accurate due to the one-sided window.
195
+ - For 'backward' mode, the velocity at the first few points may not be accurate due to the one-sided window.
196
+
197
+ Examples
198
+ --------
199
+ >>> import numpy as np
200
+ >>> x = np.array([1, 2, 4, 7, 11])
201
+ >>> y = np.array([0, 3, 5, 8, 10])
202
+ >>> timeline = np.array([0, 1, 2, 3, 4])
203
+ >>> window = 3
204
+ >>> velocity(x, y, timeline, window, mode='bi')
205
+ array([[3., 3.],
206
+ [3., 3.]])
207
+
208
+ >>> velocity(x, y, timeline, window, mode='forward')
209
+ array([[2., 2.],
210
+ [3., 3.]])
211
+
212
+ >>> velocity(x, y, timeline, window, mode='backward')
213
+ array([[3., 3.],
214
+ [3., 3.]])
215
+ """
216
+
217
+ v = np.zeros((len(x), 2))
218
+ v[:, :] = np.nan
219
+
220
+ v[:, 0] = derivative(x, timeline, window, mode=mode)
221
+ v[:, 1] = derivative(y, timeline, window, mode=mode)
222
+
223
+ return v
224
+
225
+
226
+ def magnitude_velocity(v_matrix):
227
+ """
228
+ Compute the magnitude of velocity vectors given a matrix representing 2D velocity vectors.
229
+
230
+ Parameters
231
+ ----------
232
+ v_matrix : array_like
233
+ The matrix where each row represents a 2D velocity vector with the first column
234
+ being the x-component and the second column being the y-component.
235
+
236
+ Returns
237
+ -------
238
+ magnitude : ndarray
239
+ The computed magnitudes of the input velocity vectors.
240
+
241
+ Notes
242
+ -----
243
+ - If a velocity vector has NaN components, the corresponding magnitude will be NaN.
244
+ - The function handles NaN values in the input matrix gracefully.
245
+
246
+ Examples
247
+ --------
248
+ >>> import numpy as np
249
+ >>> v_matrix = np.array([[3, 4],
250
+ ... [2, 2],
251
+ ... [3, 3]])
252
+ >>> magnitude_velocity(v_matrix)
253
+ array([5., 2.82842712, 4.24264069])
254
+
255
+ >>> v_matrix_with_nan = np.array([[3, 4],
256
+ ... [np.nan, 2],
257
+ ... [3, np.nan]])
258
+ >>> magnitude_velocity(v_matrix_with_nan)
259
+ array([5., nan, nan])
260
+ """
261
+
262
+ magnitude = np.zeros(len(v_matrix))
263
+ magnitude[:] = np.nan
264
+ for i in range(len(v_matrix)):
265
+ if v_matrix[i, 0] == v_matrix[i, 0]:
266
+ magnitude[i] = np.sqrt(v_matrix[i, 0] ** 2 + v_matrix[i, 1] ** 2)
267
+ return magnitude
268
+
269
+
270
+ def orientation(v_matrix):
271
+ """
272
+ Compute the orientation angles (in radians) of 2D velocity vectors given a matrix representing velocity vectors.
273
+
274
+ Parameters
275
+ ----------
276
+ v_matrix : array_like
277
+ The matrix where each row represents a 2D velocity vector with the first column
278
+ being the x-component and the second column being the y-component.
279
+
280
+ Returns
281
+ -------
282
+ orientation_array : ndarray
283
+ The computed orientation angles of the input velocity vectors in radians.
284
+ If a velocity vector has NaN components, the corresponding orientation angle will be NaN.
285
+
286
+ Examples
287
+ --------
288
+ >>> import numpy as np
289
+ >>> v_matrix = np.array([[3, 4],
290
+ ... [2, 2],
291
+ ... [-3, -3]])
292
+ >>> orientation(v_matrix)
293
+ array([0.92729522, 0.78539816, -2.35619449])
294
+
295
+ >>> v_matrix_with_nan = np.array([[3, 4],
296
+ ... [np.nan, 2],
297
+ ... [3, np.nan]])
298
+ >>> orientation(v_matrix_with_nan)
299
+ array([0.92729522, nan, nan])
300
+ """
301
+
302
+ orientation_array = np.zeros(len(v_matrix))
303
+ for t in range(len(orientation_array)):
304
+ if v_matrix[t, 0] == v_matrix[t, 0]:
305
+ orientation_array[t] = np.arctan2(v_matrix[t, 0], v_matrix[t, 1])
306
+ return orientation_array
307
+
308
+
309
+ def safe_log(array):
310
+ """
311
+ Safely computes the base-10 logarithm for numeric inputs, handling invalid or non-positive values.
312
+
313
+ Parameters
314
+ ----------
315
+ array : int, float, list, or numpy.ndarray
316
+ The input value or array for which to compute the logarithm.
317
+ Can be a single number (int or float), a list, or a numpy array.
318
+
319
+ Returns
320
+ -------
321
+ float or numpy.ndarray
322
+ - If the input is a single numeric value, returns the base-10 logarithm as a float, or `np.nan` if the value is non-positive.
323
+ - If the input is a list or numpy array, returns a numpy array with the base-10 logarithm of each element.
324
+ Invalid or non-positive values are replaced with `np.nan`.
325
+
326
+ Notes
327
+ -----
328
+ - Non-positive values (`<= 0`) are considered invalid and will result in `np.nan`.
329
+ - NaN values in the input array are preserved in the output.
330
+ - If the input is a list, it is converted to a numpy array for processing.
331
+
332
+ Examples
333
+ --------
334
+ >>> safe_log(10)
335
+ 1.0
336
+
337
+ >>> safe_log(-5)
338
+ nan
339
+
340
+ >>> safe_log([10, 0, -5, 100])
341
+ array([1.0, nan, nan, 2.0])
342
+
343
+ >>> import numpy as np
344
+ >>> safe_log(np.array([1, 10, 100]))
345
+ array([0.0, 1.0, 2.0])
346
+ """
347
+
348
+ array = np.asarray(array, dtype=float)
349
+ result = np.where(array > 0, np.log10(array), np.nan)
350
+
351
+ return result.item() if np.isscalar(array) else result
@@ -0,0 +1,325 @@
1
+ import os
2
+ from glob import glob
3
+ from shutil import rmtree
4
+
5
+ from natsort import natsorted
6
+
7
+ from celldetective.utils.downloaders import get_zenodo_files
8
+
9
+
10
+ def get_tracking_configs_list(return_path=False):
11
+ """
12
+
13
+ Retrieve a list of available tracking configurations.
14
+
15
+ Parameters
16
+ ----------
17
+ return_path : bool, optional
18
+ If True, also returns the path to the models. Default is False.
19
+
20
+ Returns
21
+ -------
22
+ list or tuple
23
+ If return_path is False, returns a list of available tracking configurations.
24
+ If return_path is True, returns a tuple containing the list of models and the path to the models.
25
+
26
+ Notes
27
+ -----
28
+ This function retrieves the list of available tracking configurations by searching for model directories
29
+ in the predefined model path. The model path is derived from the parent directory of the current script
30
+ location and the path to the model directory. By default, it returns only the names of the models.
31
+ If return_path is set to True, it also returns the path to the models.
32
+
33
+ Examples
34
+ --------
35
+ >>> models = get_tracking_configs_list()
36
+ # Retrieve a list of available tracking configurations.
37
+
38
+ >>> models, path = get_tracking_configs_list(return_path=True)
39
+ # Retrieve a list of available tracking configurations.
40
+
41
+ """
42
+
43
+ modelpath = os.sep.join(
44
+ [
45
+ os.path.split(os.path.dirname(os.path.realpath(__file__)))[0],
46
+ # "celldetective",
47
+ "models",
48
+ "tracking_configs",
49
+ os.sep,
50
+ ]
51
+ )
52
+ available_models = glob(modelpath + "*.json")
53
+ available_models = [m.replace("\\", "/").split("/")[-1] for m in available_models]
54
+ available_models = [m.replace("\\", "/").split(".")[0] for m in available_models]
55
+
56
+ if not return_path:
57
+ return available_models
58
+ else:
59
+ return available_models, modelpath
60
+
61
+
62
+ def get_signal_models_list(return_path=False):
63
+ """
64
+
65
+ Retrieve a list of available signal detection models.
66
+
67
+ Parameters
68
+ ----------
69
+ return_path : bool, optional
70
+ If True, also returns the path to the models. Default is False.
71
+
72
+ Returns
73
+ -------
74
+ list or tuple
75
+ If return_path is False, returns a list of available signal detection models.
76
+ If return_path is True, returns a tuple containing the list of models and the path to the models.
77
+
78
+ Notes
79
+ -----
80
+ This function retrieves the list of available signal detection models by searching for model directories
81
+ in the predefined model path. The model path is derived from the parent directory of the current script
82
+ location and the path to the model directory. By default, it returns only the names of the models.
83
+ If return_path is set to True, it also returns the path to the models.
84
+
85
+ Examples
86
+ --------
87
+ >>> models = get_signal_models_list()
88
+ # Retrieve a list of available signal detection models.
89
+
90
+ >>> models, path = get_signal_models_list(return_path=True)
91
+ # Retrieve a list of available signal detection models and the path to the models.
92
+
93
+ """
94
+
95
+ modelpath = os.sep.join(
96
+ [
97
+ os.path.split(os.path.dirname(os.path.realpath(__file__)))[0],
98
+ # "celldetective",
99
+ "models",
100
+ "signal_detection",
101
+ os.sep,
102
+ ]
103
+ )
104
+ repository_models = get_zenodo_files(
105
+ cat=os.sep.join(["models", "signal_detection"])
106
+ )
107
+
108
+ available_models = glob(modelpath + f"*{os.sep}")
109
+ available_models = [m.replace("\\", "/").split("/")[-2] for m in available_models]
110
+ available_models = [
111
+ m
112
+ for m in available_models
113
+ if os.path.exists(os.path.join(modelpath, m, "config_input.json"))
114
+ ]
115
+ for rm in repository_models:
116
+ if rm not in available_models:
117
+ available_models.append(rm)
118
+
119
+ if not return_path:
120
+ return available_models
121
+ else:
122
+ return available_models, modelpath
123
+
124
+
125
+ def get_pair_signal_models_list(return_path=False):
126
+ """
127
+
128
+ Retrieve a list of available signal detection models.
129
+
130
+ Parameters
131
+ ----------
132
+ return_path : bool, optional
133
+ If True, also returns the path to the models. Default is False.
134
+
135
+ Returns
136
+ -------
137
+ list or tuple
138
+ If return_path is False, returns a list of available signal detection models.
139
+ If return_path is True, returns a tuple containing the list of models and the path to the models.
140
+
141
+ Notes
142
+ -----
143
+ This function retrieves the list of available signal detection models by searching for model directories
144
+ in the predefined model path. The model path is derived from the parent directory of the current script
145
+ location and the path to the model directory. By default, it returns only the names of the models.
146
+ If return_path is set to True, it also returns the path to the models.
147
+
148
+ Examples
149
+ --------
150
+ >>> models = get_signal_models_list()
151
+ # Retrieve a list of available signal detection models.
152
+
153
+ >>> models, path = get_signal_models_list(return_path=True)
154
+ # Retrieve a list of available signal detection models and the path to the models.
155
+
156
+ """
157
+
158
+ modelpath = os.sep.join(
159
+ [
160
+ os.path.split(os.path.dirname(os.path.realpath(__file__)))[0],
161
+ # "celldetective",
162
+ "models",
163
+ "pair_signal_detection",
164
+ os.sep,
165
+ ]
166
+ )
167
+ # repository_models = get_zenodo_files(cat=os.sep.join(["models", "pair_signal_detection"]))
168
+
169
+ available_models = glob(modelpath + f"*{os.sep}")
170
+ available_models = [m.replace("\\", "/").split("/")[-2] for m in available_models]
171
+ # for rm in repository_models:
172
+ # if rm not in available_models:
173
+ # available_models.append(rm)
174
+
175
+ if not return_path:
176
+ return available_models
177
+ else:
178
+ return available_models, modelpath
179
+
180
+
181
+ def get_segmentation_models_list(mode="targets", return_path=False):
182
+
183
+ modelpath = os.sep.join(
184
+ [
185
+ os.path.split(os.path.dirname(os.path.realpath(__file__)))[0],
186
+ # "celldetective",
187
+ "models",
188
+ f"segmentation_{mode}",
189
+ os.sep,
190
+ ]
191
+ )
192
+ if not os.path.exists(modelpath):
193
+ os.mkdir(modelpath)
194
+ repository_models = []
195
+ else:
196
+ repository_models = get_zenodo_files(
197
+ cat=os.sep.join(["models", f"segmentation_{mode}"])
198
+ )
199
+
200
+ available_models = natsorted(glob(modelpath + "*/"))
201
+ available_models = [m.replace("\\", "/").split("/")[-2] for m in available_models]
202
+
203
+ # Auto model cleanup
204
+ to_remove = []
205
+ for model in available_models:
206
+ path = modelpath + model
207
+ files = glob(path + os.sep + "*")
208
+ if path + os.sep + "config_input.json" not in files:
209
+ rmtree(path)
210
+ to_remove.append(model)
211
+ for m in to_remove:
212
+ available_models.remove(m)
213
+
214
+ for rm in repository_models:
215
+ if rm not in available_models:
216
+ available_models.append(rm)
217
+
218
+ if not return_path:
219
+ return available_models
220
+ else:
221
+ return available_models, modelpath
222
+
223
+
224
+ def get_segmentation_datasets_list(return_path=False):
225
+ """
226
+ Retrieves a list of available segmentation datasets from both the local 'celldetective/datasets/segmentation_annotations'
227
+ directory and a Zenodo repository, optionally returning the path to the local datasets directory.
228
+
229
+ This function compiles a list of available segmentation datasets by first identifying datasets stored locally
230
+ within a specified path related to the script's directory. It then extends this list with datasets available
231
+ in a Zenodo repository, ensuring no duplicates are added. The function can return just the list of dataset
232
+ names or, if specified, also return the path to the local datasets directory.
233
+
234
+ Parameters
235
+ ----------
236
+ return_path : bool, optional
237
+ If True, the function returns a tuple containing the list of available dataset names and the path to the
238
+ local datasets directory. If False, only the list of dataset names is returned (default is False).
239
+
240
+ Returns
241
+ -------
242
+ list or (list, str)
243
+ If return_path is False, returns a list of strings, each string being the name of an available dataset.
244
+ If return_path is True, returns a tuple where the first element is this list and the second element is a
245
+ string representing the path to the local datasets directory.
246
+
247
+ """
248
+
249
+ datasets_path = os.sep.join(
250
+ [
251
+ os.path.split(os.path.dirname(os.path.realpath(__file__)))[0],
252
+ # "celldetective",
253
+ "datasets",
254
+ "segmentation_annotations",
255
+ os.sep,
256
+ ]
257
+ )
258
+ repository_datasets = get_zenodo_files(
259
+ cat=os.sep.join(["datasets", "segmentation_annotations"])
260
+ )
261
+
262
+ available_datasets = natsorted(glob(datasets_path + "*/"))
263
+ available_datasets = [
264
+ m.replace("\\", "/").split("/")[-2] for m in available_datasets
265
+ ]
266
+ for rm in repository_datasets:
267
+ if rm not in available_datasets:
268
+ available_datasets.append(rm)
269
+
270
+ if not return_path:
271
+ return available_datasets
272
+ else:
273
+ return available_datasets, datasets_path
274
+
275
+
276
+ def get_signal_datasets_list(return_path=False):
277
+ """
278
+ Retrieves a list of available signal datasets from both the local 'celldetective/datasets/signal_annotations' directory
279
+ and a Zenodo repository, optionally returning the path to the local datasets directory.
280
+
281
+ This function compiles a list of available signal datasets by first identifying datasets stored locally within a specified
282
+ path related to the script's directory. It then extends this list with datasets available in a Zenodo repository, ensuring
283
+ no duplicates are added. The function can return just the list of dataset names or, if specified, also return the path to
284
+ the local datasets directory.
285
+
286
+ Parameters
287
+ ----------
288
+ return_path : bool, optional
289
+ If True, the function returns a tuple containing the list of available dataset names and the path to the local datasets
290
+ directory. If False, only the list of dataset names is returned (default is False).
291
+
292
+ Returns
293
+ -------
294
+ list or (list, str)
295
+ If return_path is False, returns a list of strings, each string being the name of an available dataset. If return_path
296
+ is True, returns a tuple where the first element is this list and the second element is a string representing the path
297
+ to the local datasets directory.
298
+
299
+ """
300
+
301
+ datasets_path = os.sep.join(
302
+ [
303
+ os.path.split(os.path.dirname(os.path.realpath(__file__)))[0],
304
+ # "celldetective",
305
+ "datasets",
306
+ "signal_annotations",
307
+ os.sep,
308
+ ]
309
+ )
310
+ repository_datasets = get_zenodo_files(
311
+ cat=os.sep.join(["datasets", "signal_annotations"])
312
+ )
313
+
314
+ available_datasets = natsorted(glob(datasets_path + "*/"))
315
+ available_datasets = [
316
+ m.replace("\\", "/").split("/")[-2] for m in available_datasets
317
+ ]
318
+ for rm in repository_datasets:
319
+ if rm not in available_datasets:
320
+ available_datasets.append(rm)
321
+
322
+ if not return_path:
323
+ return available_datasets
324
+ else:
325
+ return available_datasets, datasets_path