celldetective 1.1.0__py3-none-any.whl → 1.1.1.post1__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 (34) hide show
  1. celldetective/__main__.py +5 -19
  2. celldetective/extra_properties.py +63 -53
  3. celldetective/filters.py +39 -11
  4. celldetective/gui/classifier_widget.py +56 -7
  5. celldetective/gui/control_panel.py +5 -0
  6. celldetective/gui/layouts.py +3 -2
  7. celldetective/gui/measurement_options.py +13 -109
  8. celldetective/gui/plot_signals_ui.py +1 -0
  9. celldetective/gui/process_block.py +1 -1
  10. celldetective/gui/survival_ui.py +7 -1
  11. celldetective/gui/tableUI.py +294 -28
  12. celldetective/gui/thresholds_gui.py +51 -10
  13. celldetective/gui/viewers.py +169 -22
  14. celldetective/io.py +41 -17
  15. celldetective/measure.py +13 -238
  16. celldetective/models/segmentation_effectors/primNK_cfse/config_input.json +29 -0
  17. celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer +0 -0
  18. celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json +37 -0
  19. celldetective/neighborhood.py +4 -1
  20. celldetective/preprocessing.py +483 -143
  21. celldetective/scripts/segment_cells.py +26 -7
  22. celldetective/scripts/train_segmentation_model.py +35 -34
  23. celldetective/segmentation.py +29 -20
  24. celldetective/signals.py +13 -231
  25. celldetective/tracking.py +2 -1
  26. celldetective/utils.py +440 -26
  27. {celldetective-1.1.0.dist-info → celldetective-1.1.1.post1.dist-info}/METADATA +1 -1
  28. {celldetective-1.1.0.dist-info → celldetective-1.1.1.post1.dist-info}/RECORD +34 -30
  29. {celldetective-1.1.0.dist-info → celldetective-1.1.1.post1.dist-info}/WHEEL +1 -1
  30. tests/test_preprocessing.py +37 -0
  31. tests/test_utils.py +48 -1
  32. {celldetective-1.1.0.dist-info → celldetective-1.1.1.post1.dist-info}/LICENSE +0 -0
  33. {celldetective-1.1.0.dist-info → celldetective-1.1.1.post1.dist-info}/entry_points.txt +0 -0
  34. {celldetective-1.1.0.dist-info → celldetective-1.1.1.post1.dist-info}/top_level.txt +0 -0
celldetective/utils.py CHANGED
@@ -22,6 +22,413 @@ import zipfile
22
22
  from tqdm import tqdm
23
23
  import shutil
24
24
  import tempfile
25
+ from scipy.interpolate import griddata
26
+
27
+
28
+ def derivative(x, timeline, window, mode='bi'):
29
+
30
+ """
31
+ Compute the derivative of a given array of values with respect to time using a specified numerical differentiation method.
32
+
33
+ Parameters
34
+ ----------
35
+ x : array_like
36
+ The input array of values.
37
+ timeline : array_like
38
+ The array representing the time points corresponding to the input values.
39
+ window : int
40
+ The size of the window used for numerical differentiation. Must be a positive odd integer.
41
+ mode : {'bi', 'forward', 'backward'}, optional
42
+ The numerical differentiation method to be used:
43
+ - 'bi' (default): Bidirectional differentiation using a symmetric window.
44
+ - 'forward': Forward differentiation using a one-sided window.
45
+ - 'backward': Backward differentiation using a one-sided window.
46
+
47
+ Returns
48
+ -------
49
+ dxdt : ndarray
50
+ The computed derivative values of the input array with respect to time.
51
+
52
+ Raises
53
+ ------
54
+ AssertionError
55
+ If the window size is not an odd integer and mode is 'bi'.
56
+
57
+ Notes
58
+ -----
59
+ - For 'bi' mode, the window size must be an odd number.
60
+ - For 'forward' mode, the derivative at the edge points may not be accurate due to the one-sided window.
61
+ - For 'backward' mode, the derivative at the first few points may not be accurate due to the one-sided window.
62
+
63
+ Examples
64
+ --------
65
+ >>> import numpy as np
66
+ >>> x = np.array([1, 2, 4, 7, 11])
67
+ >>> timeline = np.array([0, 1, 2, 3, 4])
68
+ >>> window = 3
69
+ >>> derivative(x, timeline, window, mode='bi')
70
+ array([3., 3., 3.])
71
+
72
+ >>> derivative(x, timeline, window, mode='forward')
73
+ array([1., 2., 3.])
74
+
75
+ >>> derivative(x, timeline, window, mode='backward')
76
+ array([3., 3., 3., 3.])
77
+ """
78
+
79
+ # modes = bi, forward, backward
80
+ dxdt = np.zeros(len(x))
81
+ dxdt[:] = np.nan
82
+
83
+ if mode=='bi':
84
+ assert window%2==1,'Please set an odd window for the bidirectional mode'
85
+ lower_bound = window//2
86
+ upper_bound = len(x) - window//2 - 1
87
+ elif mode=='forward':
88
+ lower_bound = 0
89
+ upper_bound = len(x) - window
90
+ elif mode=='backward':
91
+ lower_bound = window
92
+ upper_bound = len(x)
93
+
94
+ for t in range(lower_bound,upper_bound):
95
+ if mode=='bi':
96
+ dxdt[t] = (x[t+window//2+1] - x[t-window//2]) / (timeline[t+window//2+1] - timeline[t-window//2])
97
+ elif mode=='forward':
98
+ dxdt[t] = (x[t+window] - x[t]) / (timeline[t+window] - timeline[t])
99
+ elif mode=='backward':
100
+ dxdt[t] = (x[t] - x[t-window]) / (timeline[t] - timeline[t-window])
101
+ return dxdt
102
+
103
+ def differentiate_per_track(tracks, measurement, window_size=3, mode='bi'):
104
+
105
+ groupby_cols = ['TRACK_ID']
106
+ if 'position' in list(tracks.columns):
107
+ groupby_cols = ['position']+groupby_cols
108
+
109
+ tracks = tracks.sort_values(by=groupby_cols+['FRAME'],ignore_index=True)
110
+ tracks = tracks.reset_index(drop=True)
111
+ for tid, group in tracks.groupby(groupby_cols):
112
+ indices = group.index
113
+ timeline = group['FRAME'].values
114
+ signal = group[measurement].values
115
+ dsignal = derivative(signal, timeline, window_size, mode=mode)
116
+ tracks.loc[indices, 'd/dt.'+measurement] = dsignal
117
+ return tracks
118
+
119
+ def velocity_per_track(tracks, window_size=3, mode='bi'):
120
+
121
+ groupby_cols = ['TRACK_ID']
122
+ if 'position' in list(tracks.columns):
123
+ groupby_cols = ['position']+groupby_cols
124
+
125
+ tracks = tracks.sort_values(by=groupby_cols+['FRAME'],ignore_index=True)
126
+ tracks = tracks.reset_index(drop=True)
127
+ for tid, group in tracks.groupby(groupby_cols):
128
+ indices = group.index
129
+ timeline = group['FRAME'].values
130
+ x = group['POSITION_X'].values
131
+ y = group['POSITION_Y'].values
132
+ v = velocity(x,y,timeline,window=window_size,mode=mode)
133
+ v_abs = magnitude_velocity(v)
134
+ tracks.loc[indices, 'velocity'] = v_abs
135
+ return tracks
136
+
137
+ def velocity(x,y,timeline,window,mode='bi'):
138
+
139
+ """
140
+ Compute the velocity vector of a given 2D trajectory represented by arrays of x and y coordinates
141
+ with respect to time using a specified numerical differentiation method.
142
+
143
+ Parameters
144
+ ----------
145
+ x : array_like
146
+ The array of x-coordinates of the trajectory.
147
+ y : array_like
148
+ The array of y-coordinates of the trajectory.
149
+ timeline : array_like
150
+ The array representing the time points corresponding to the x and y coordinates.
151
+ window : int
152
+ The size of the window used for numerical differentiation. Must be a positive odd integer.
153
+ mode : {'bi', 'forward', 'backward'}, optional
154
+ The numerical differentiation method to be used:
155
+ - 'bi' (default): Bidirectional differentiation using a symmetric window.
156
+ - 'forward': Forward differentiation using a one-sided window.
157
+ - 'backward': Backward differentiation using a one-sided window.
158
+
159
+ Returns
160
+ -------
161
+ v : ndarray
162
+ The computed velocity vector of the 2D trajectory with respect to time.
163
+ The first column represents the x-component of velocity, and the second column represents the y-component.
164
+
165
+ Raises
166
+ ------
167
+ AssertionError
168
+ If the window size is not an odd integer and mode is 'bi'.
169
+
170
+ Notes
171
+ -----
172
+ - For 'bi' mode, the window size must be an odd number.
173
+ - For 'forward' mode, the velocity at the edge points may not be accurate due to the one-sided window.
174
+ - For 'backward' mode, the velocity at the first few points may not be accurate due to the one-sided window.
175
+
176
+ Examples
177
+ --------
178
+ >>> import numpy as np
179
+ >>> x = np.array([1, 2, 4, 7, 11])
180
+ >>> y = np.array([0, 3, 5, 8, 10])
181
+ >>> timeline = np.array([0, 1, 2, 3, 4])
182
+ >>> window = 3
183
+ >>> velocity(x, y, timeline, window, mode='bi')
184
+ array([[3., 3.],
185
+ [3., 3.]])
186
+
187
+ >>> velocity(x, y, timeline, window, mode='forward')
188
+ array([[2., 2.],
189
+ [3., 3.]])
190
+
191
+ >>> velocity(x, y, timeline, window, mode='backward')
192
+ array([[3., 3.],
193
+ [3., 3.]])
194
+ """
195
+
196
+ v = np.zeros((len(x),2))
197
+ v[:,:] = np.nan
198
+
199
+ v[:,0] = derivative(x, timeline, window, mode=mode)
200
+ v[:,1] = derivative(y, timeline, window, mode=mode)
201
+
202
+ return v
203
+
204
+ def magnitude_velocity(v_matrix):
205
+
206
+ """
207
+ Compute the magnitude of velocity vectors given a matrix representing 2D velocity vectors.
208
+
209
+ Parameters
210
+ ----------
211
+ v_matrix : array_like
212
+ The matrix where each row represents a 2D velocity vector with the first column
213
+ being the x-component and the second column being the y-component.
214
+
215
+ Returns
216
+ -------
217
+ magnitude : ndarray
218
+ The computed magnitudes of the input velocity vectors.
219
+
220
+ Notes
221
+ -----
222
+ - If a velocity vector has NaN components, the corresponding magnitude will be NaN.
223
+ - The function handles NaN values in the input matrix gracefully.
224
+
225
+ Examples
226
+ --------
227
+ >>> import numpy as np
228
+ >>> v_matrix = np.array([[3, 4],
229
+ ... [2, 2],
230
+ ... [3, 3]])
231
+ >>> magnitude_velocity(v_matrix)
232
+ array([5., 2.82842712, 4.24264069])
233
+
234
+ >>> v_matrix_with_nan = np.array([[3, 4],
235
+ ... [np.nan, 2],
236
+ ... [3, np.nan]])
237
+ >>> magnitude_velocity(v_matrix_with_nan)
238
+ array([5., nan, nan])
239
+ """
240
+
241
+ magnitude = np.zeros(len(v_matrix))
242
+ magnitude[:] = np.nan
243
+ for i in range(len(v_matrix)):
244
+ if v_matrix[i,0]==v_matrix[i,0]:
245
+ magnitude[i] = np.sqrt(v_matrix[i,0]**2 + v_matrix[i,1]**2)
246
+ return magnitude
247
+
248
+ def orientation(v_matrix):
249
+
250
+ """
251
+ Compute the orientation angles (in radians) of 2D velocity vectors given a matrix representing velocity vectors.
252
+
253
+ Parameters
254
+ ----------
255
+ v_matrix : array_like
256
+ The matrix where each row represents a 2D velocity vector with the first column
257
+ being the x-component and the second column being the y-component.
258
+
259
+ Returns
260
+ -------
261
+ orientation_array : ndarray
262
+ The computed orientation angles of the input velocity vectors in radians.
263
+ If a velocity vector has NaN components, the corresponding orientation angle will be NaN.
264
+
265
+ Examples
266
+ --------
267
+ >>> import numpy as np
268
+ >>> v_matrix = np.array([[3, 4],
269
+ ... [2, 2],
270
+ ... [-3, -3]])
271
+ >>> orientation(v_matrix)
272
+ array([0.92729522, 0.78539816, -2.35619449])
273
+
274
+ >>> v_matrix_with_nan = np.array([[3, 4],
275
+ ... [np.nan, 2],
276
+ ... [3, np.nan]])
277
+ >>> orientation(v_matrix_with_nan)
278
+ array([0.92729522, nan, nan])
279
+ """
280
+
281
+ orientation_array = np.zeros(len(v_matrix))
282
+ for t in range(len(orientation_array)):
283
+ if v_matrix[t,0]==v_matrix[t,0]:
284
+ orientation_array[t] = np.arctan2(v_matrix[t,0],v_matrix[t,1])
285
+ return orientation_array
286
+
287
+
288
+ def estimate_unreliable_edge(activation_protocol=[['gauss',2],['std',4]]):
289
+
290
+ """
291
+ Safely estimate the distance to the edge of an image in which the filtered image values can be artefactual.
292
+
293
+ Parameters
294
+ ----------
295
+ activation_protocol : list of list, optional
296
+ A list of lists, where each sublist contains a string naming the filter function, followed by its arguments (usually a kernel size).
297
+ Default is [['gauss', 2], ['std', 4]].
298
+
299
+ Returns
300
+ -------
301
+ int or None
302
+ The sum of the kernel sizes in the activation protocol if the protocol
303
+ is not empty. Returns None if the activation protocol is empty.
304
+
305
+ Notes
306
+ -----
307
+ This function assumes that the second element of each sublist in the
308
+ activation protocol is a kernel size.
309
+
310
+ Examples
311
+ --------
312
+ >>> estimate_unreliable_edge([['gauss', 2], ['std', 4]])
313
+ 6
314
+ >>> estimate_unreliable_edge([])
315
+ None
316
+ """
317
+
318
+ if activation_protocol==[]:
319
+ return None
320
+ else:
321
+ edge=0
322
+ for fct in activation_protocol:
323
+ if isinstance(fct[1],(int,np.int_)):
324
+ edge+=fct[1]
325
+ return edge
326
+
327
+ def unpad(img, pad):
328
+
329
+ """
330
+ Remove padding from an image.
331
+
332
+ This function removes the specified amount of padding from the borders
333
+ of an image. The padding is assumed to be the same on all sides.
334
+
335
+ Parameters
336
+ ----------
337
+ img : ndarray
338
+ The input image from which the padding will be removed.
339
+ pad : int
340
+ The amount of padding to remove from each side of the image.
341
+
342
+ Returns
343
+ -------
344
+ ndarray
345
+ The image with the padding removed.
346
+
347
+ Raises
348
+ ------
349
+ ValueError
350
+ If `pad` is greater than or equal to half of the smallest dimension
351
+ of `img`.
352
+
353
+ See Also
354
+ --------
355
+ numpy.pad : Pads an array.
356
+
357
+ Notes
358
+ -----
359
+ This function assumes that the input image is a 2D array.
360
+
361
+ Examples
362
+ --------
363
+ >>> import numpy as np
364
+ >>> img = np.array([[0, 0, 0, 0, 0],
365
+ ... [0, 1, 1, 1, 0],
366
+ ... [0, 1, 1, 1, 0],
367
+ ... [0, 1, 1, 1, 0],
368
+ ... [0, 0, 0, 0, 0]])
369
+ >>> unpad(img, 1)
370
+ array([[1, 1, 1],
371
+ [1, 1, 1],
372
+ [1, 1, 1]])
373
+ """
374
+
375
+ return img[pad:-pad, pad:-pad]
376
+
377
+ def mask_edges(binary_mask, border_size):
378
+
379
+ """
380
+ Mask the edges of a binary mask.
381
+
382
+ This function sets the edges of a binary mask to False, effectively
383
+ masking out a border of the specified size.
384
+
385
+ Parameters
386
+ ----------
387
+ binary_mask : ndarray
388
+ A 2D binary mask array where the edges will be masked.
389
+ border_size : int
390
+ The size of the border to mask (set to False) on all sides.
391
+
392
+ Returns
393
+ -------
394
+ ndarray
395
+ The binary mask with the edges masked out.
396
+
397
+ Raises
398
+ ------
399
+ ValueError
400
+ If `border_size` is greater than or equal to half of the smallest
401
+ dimension of `binary_mask`.
402
+
403
+ Notes
404
+ -----
405
+ This function assumes that the input `binary_mask` is a 2D array. The
406
+ input mask is converted to a boolean array before masking the edges.
407
+
408
+ Examples
409
+ --------
410
+ >>> import numpy as np
411
+ >>> binary_mask = np.array([[1, 1, 1, 1, 1],
412
+ ... [1, 1, 1, 1, 1],
413
+ ... [1, 1, 1, 1, 1],
414
+ ... [1, 1, 1, 1, 1],
415
+ ... [1, 1, 1, 1, 1]])
416
+ >>> mask_edges(binary_mask, 1)
417
+ array([[False, False, False, False, False],
418
+ [False, True, True, True, False],
419
+ [False, True, True, True, False],
420
+ [False, True, True, True, False],
421
+ [False, False, False, False, False]])
422
+ """
423
+
424
+ binary_mask = binary_mask.astype(bool)
425
+ binary_mask[:border_size,:] = False
426
+ binary_mask[(binary_mask.shape[0]-border_size):,:] = False
427
+ binary_mask[:,:border_size] = False
428
+ binary_mask[:,(binary_mask.shape[1]-border_size):] = False
429
+
430
+ return binary_mask
431
+
25
432
 
26
433
  def create_patch_mask(h, w, center=None, radius=None):
27
434
 
@@ -170,8 +577,6 @@ def rename_intensity_column(df, channels):
170
577
  new_name = '_'.join(list(measure))
171
578
  new_name = new_name.replace('radial_gradient', "radial_intercept")
172
579
  to_rename.update({intensity_columns[k]: new_name.replace('-', '_')})
173
-
174
-
175
580
  else:
176
581
  to_rename = {}
177
582
  for k in range(len(intensity_columns)):
@@ -1163,7 +1568,7 @@ def remove_trajectory_measurements(trajectories, column_labels):
1163
1568
  tracks = trajectories.copy()
1164
1569
 
1165
1570
  columns_to_keep = [column_labels['track'], column_labels['time'], column_labels['x'], column_labels['y'],column_labels['x']+'_um', column_labels['y']+'_um', 'class_id',
1166
- 't', 'state', 'generation', 'root', 'parent', 'ID', 't0', 'class', 'status', 'class_color', 'status_color', 'class_firstdetection', 't_firstdetection']
1571
+ 't', 'state', 'generation', 'root', 'parent', 'ID', 't0', 'class', 'status', 'class_color', 'status_color', 'class_firstdetection', 't_firstdetection', 'velocity']
1167
1572
  cols = tracks.columns
1168
1573
  for c in columns_to_keep:
1169
1574
  if c not in cols:
@@ -1563,26 +1968,29 @@ def normalize_per_channel(X, normalization_percentile_mode=True, normalization_v
1563
1968
  assert len(normalization_clipping)==n_channels
1564
1969
  assert len(normalization_percentile_mode)==n_channels
1565
1970
 
1971
+ X_normalized = []
1566
1972
  for i in range(len(X)):
1567
- x = X[i]
1973
+ x = X[i].copy()
1568
1974
  loc_i,loc_j,loc_c = np.where(x==0.)
1569
1975
  norm_x = np.zeros_like(x, dtype=np.float32)
1570
1976
  for k in range(x.shape[-1]):
1571
- chan = x[:,:,k]
1977
+ chan = x[:,:,k].copy()
1572
1978
  if not np.all(chan.flatten()==0):
1573
1979
  if normalization_percentile_mode[k]:
1574
- min_val = np.percentile(chan[chan!=0.].flatten(), normalization_values[k][0])
1575
- max_val = np.percentile(chan[chan!=0.].flatten(), normalization_values[k][1])
1980
+ min_val = np.nanpercentile(chan[chan!=0.].flatten(), normalization_values[k][0])
1981
+ max_val = np.nanpercentile(chan[chan!=0.].flatten(), normalization_values[k][1])
1576
1982
  else:
1577
1983
  min_val = normalization_values[k][0]
1578
1984
  max_val = normalization_values[k][1]
1579
1985
 
1580
1986
  clip_option = normalization_clipping[k]
1581
- norm_x[:,:,k] = normalize_mi_ma(chan.astype(np.float32), min_val, max_val, clip=clip_option, eps=1e-20, dtype=np.float32)
1582
-
1583
- X[i] = norm_x
1987
+ norm_x[:,:,k] = normalize_mi_ma(chan.astype(np.float32).copy(), min_val, max_val, clip=clip_option, eps=1e-20, dtype=np.float32)
1988
+ else:
1989
+ norm_x[:,:,k] = 0.
1990
+ norm_x[loc_i,loc_j,loc_c] = 0.
1991
+ X_normalized.append(norm_x.copy())
1584
1992
 
1585
- return X
1993
+ return X_normalized
1586
1994
 
1587
1995
  def load_image_dataset(datasets, channels, train_spatial_calibration=None, mask_suffix='labelled'):
1588
1996
 
@@ -1688,8 +2096,7 @@ def load_image_dataset(datasets, channels, train_spatial_calibration=None, mask_
1688
2096
 
1689
2097
  if im_calib != train_spatial_calibration:
1690
2098
  factor = im_calib / train_spatial_calibration
1691
- print(f'{im_calib=}, {train_spatial_calibration=}, {factor=}')
1692
- image = zoom(image, [factor,factor,1], order=3)
2099
+ image = np.moveaxis([zoom(image[:,:,c].astype(float).copy(), [factor,factor], order=3, prefilter=False) for c in range(image.shape[-1])],0,-1) #zoom(image, [factor,factor,1], order=3)
1693
2100
  mask = zoom(mask, [factor,factor], order=0)
1694
2101
 
1695
2102
  X.append(image)
@@ -1807,17 +2214,24 @@ def download_zenodo_file(file, output_dir):
1807
2214
 
1808
2215
  os.remove(path_to_zip_file)
1809
2216
 
1810
- def interpolate_nan(array_like):
2217
+ def interpolate_nan(img, method='nearest'):
1811
2218
 
1812
- array = array_like.copy()
1813
-
1814
- isnan_array = ~np.isnan(array)
1815
-
1816
- xp = isnan_array.ravel().nonzero()[0]
1817
-
1818
- fp = array[~np.isnan(array)]
1819
- x = np.isnan(array).ravel().nonzero()[0]
1820
-
1821
- array[np.isnan(array)] = np.interp(x, xp, fp)
1822
-
1823
- return array
2219
+ """
2220
+ Interpolate NaN on single channel array 2D
2221
+ """
2222
+
2223
+ if np.all(img==0):
2224
+ return img
2225
+
2226
+ if np.any(img.flatten()!=img.flatten()):
2227
+ # then need to interpolate
2228
+ x_grid, y_grid = np.meshgrid(np.arange(img.shape[1]),np.arange(img.shape[0]))
2229
+ mask = [~np.isnan(img)][0]
2230
+ x = x_grid[mask].reshape(-1)
2231
+ y = y_grid[mask].reshape(-1)
2232
+ points = np.array([x,y]).T
2233
+ values = img[mask].reshape(-1)
2234
+ interp_grid = griddata(points, values, (x_grid, y_grid), method=method)
2235
+ return interp_grid
2236
+ else:
2237
+ return img
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: celldetective
3
- Version: 1.1.0
3
+ Version: 1.1.1.post1
4
4
  Summary: description
5
5
  Home-page: http://github.com/remyeltorro/celldetective
6
6
  Author: Rémy Torro
@@ -1,43 +1,43 @@
1
1
  celldetective/__init__.py,sha256=FEZpJKcskBH2IginYzeqPWoR1lVGuyYCXhv7Hnlkoo8,49
2
- celldetective/__main__.py,sha256=zX2ZDiUp02OlHSwsVUDJ6aCKRAAYU0SSmallsiz1HsA,14054
2
+ celldetective/__main__.py,sha256=XFAkq_2cBEkWAVXDGSNFagoQBglyl0Y-GOO3KFc8UqM,13888
3
3
  celldetective/events.py,sha256=s2pWnR3Z1fcB15sET5WsF2Pi6v6qv16hks_m3WiklNs,3658
4
- celldetective/extra_properties.py,sha256=9tQiXgkUlhmqyE7gUMgq_Kq-XTWTeeMAtFzDNwSmCgU,3961
5
- celldetective/filters.py,sha256=i-XN6psgdaG_w6gjK2Qvb1OshspQaDsV_PF1WTyo2Sw,2704
6
- celldetective/io.py,sha256=nkMj9s8fO_I3J-fVVsuRiEDrJ4nHcdWQqN-9P20DcHQ,80323
7
- celldetective/measure.py,sha256=5Jr9F9LEj3KzD32ssbPuGgS7sCghRurxYV9e2qjkuj0,56981
8
- celldetective/neighborhood.py,sha256=WZihWn6npFhe9C_LSmGhLuPevzsvjuscmH-xPLoWO6I,49406
9
- celldetective/preprocessing.py,sha256=jo5mtCBTh8OwETeGRG89RHjSb3yM_75icA2bMJe35bY,24280
10
- celldetective/segmentation.py,sha256=L_dP3n0U4V0QQhQBl-dL5NenE4d04KEYt1zFRlRUvkM,28496
11
- celldetective/signals.py,sha256=q7JSyQolsbCqrClyiigDVKhWGj1KmXkWDrk-VGgvjeY,109452
12
- celldetective/tracking.py,sha256=uTwCc8saEEHE7bcrv0ML9BNfbiwxUM6DWYK2yBoyzIU,37526
13
- celldetective/utils.py,sha256=msx-aPX4Uqyrt1jSwzwbq7GIuqkLs8LL3cDqRuTOnQo,65322
4
+ celldetective/extra_properties.py,sha256=ZdWV046RR8jrQPYxLSVVb1cXkWYxfrrLj2tXfc358cU,4179
5
+ celldetective/filters.py,sha256=b0qKwHor1fvNA_dHovP17nQz8EsW5YlyhT2TJnayn08,3615
6
+ celldetective/io.py,sha256=ptaX4GadWuf0zOQ3ZWSLCzihEID-YAalPfxW1nqvgIU,80889
7
+ celldetective/measure.py,sha256=HDQZfSRx3daOCV5Snu1paYU5JYkwu8engO2qZqhTAUo,48089
8
+ celldetective/neighborhood.py,sha256=QCuhesMHGyr3c3ys9wWcNR1HM6CHdHe51R8upoolgPw,49514
9
+ celldetective/preprocessing.py,sha256=psCs4CAI7gG3YlKvxkXKnpClFL4SjWm5TToXq2ZwL-s,37137
10
+ celldetective/segmentation.py,sha256=Hu4-lOJ4UhPw2o0Hn_NPOCHsa6Iwsw5A3PR6X3Tzbb8,29196
11
+ celldetective/signals.py,sha256=P7eiDZGGIAYCFBKjGCBi8gMBvJYywxlxZNzyGgw-26Y,102783
12
+ celldetective/tracking.py,sha256=A0mhdF4uq4m8OX1-rhtuhG69rlh_6Pb34Aebu7hIeKM,37601
13
+ celldetective/utils.py,sha256=00jBr_Ur6wX3xeFQzwgpFv9XDhnt_VCh-e2usFdrfo4,77543
14
14
  celldetective/datasets/segmentation_annotations/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  celldetective/datasets/signal_annotations/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  celldetective/gui/__init__.py,sha256=y2dvrUdJi17QMgPjl8WN3XFHYzJpu2ul4_8y7MQV1Bk,941
17
17
  celldetective/gui/about.py,sha256=i-y54Opb10pKTVNUEcJC-D6Cbiqud2EJ3ZLayXqhdqc,1715
18
18
  celldetective/gui/analyze_block.py,sha256=WD3JQQylx_dVozFCvNqrOyR6LcNHV7R1_gGh7XqOVeI,25423
19
19
  celldetective/gui/btrack_options.py,sha256=eQEf63yTUsPCN-d1LqgAMmUQpfv2FH85FqnOSaR-9Q8,35575
20
- celldetective/gui/classifier_widget.py,sha256=qvRl6svlelGsi-IRa7MrCGXrx4sRI8egl5xdGLH3r1A,15341
20
+ celldetective/gui/classifier_widget.py,sha256=52a3kOfU3uMEzUYMIOHGqiy-Q5itMEvcG-3JYrO34I8,16918
21
21
  celldetective/gui/configure_new_exp.py,sha256=ANJ-Zn4sjBphtj_aoJu6m1PFEKyv9gxeh9XqS6xOGjk,18969
22
- celldetective/gui/control_panel.py,sha256=Ndd6zeTNfo3KqfNeIa7XHX4Cj9GDKq5Qw1LtIsUQBgY,17466
22
+ celldetective/gui/control_panel.py,sha256=wcDqe4XaDJRMmPmWKJpxd0D9V4_DrdRGnEH6D7B_IK0,17557
23
23
  celldetective/gui/gui_utils.py,sha256=PidFfdc8XASeIzZO5pfKgwqe4vROG7-KpYMcBZ42jdw,22673
24
24
  celldetective/gui/json_readers.py,sha256=fTrNrlxv9NCae8ZJexBEHxI3yCLRqt6F0Yo1OeDycfA,3686
25
- celldetective/gui/layouts.py,sha256=6q3mvOEYdvceFYYGtWFKxAJTLKnaGj0FzYhjM3--x6g,26884
26
- celldetective/gui/measurement_options.py,sha256=L6NETkOM7wucRVuwY4SP7JenQ9bMNGEv-DI3C3t9JW0,52725
25
+ celldetective/gui/layouts.py,sha256=gC24lyA48hzOo2oabYF1vXTFh5r7WcQFVkqjAXXo5g0,26997
26
+ celldetective/gui/measurement_options.py,sha256=i0CdAfupHJAqhOT7RsufEK919sAzQnFBkQO4IAMYZL0,47704
27
27
  celldetective/gui/neighborhood_options.py,sha256=sdKxVRliZtuKSpcPfnFxqkW4V8rN2tzjhDxOPVmElyE,20191
28
28
  celldetective/gui/plot_measurements.py,sha256=xUoGxV6uXcen-t4yWtAmcGTUayICI-FxTVKPrWMNlfg,51799
29
- celldetective/gui/plot_signals_ui.py,sha256=AQ_Ab6bg2tmvZv5dypbaBqJBML7IE_WlDsrkxL0dXAY,43699
30
- celldetective/gui/process_block.py,sha256=pI-HDU8_s0_jNNnbRBYj7RZrz7Z6cg6xVYOfrfvdwpc,53564
29
+ celldetective/gui/plot_signals_ui.py,sha256=TwWU2u3_mkRNsM8er0kI_kwr5EoZ29YEzlr0cQzyW4A,43732
30
+ celldetective/gui/process_block.py,sha256=7n9glZ1ojEi1bObqwIj4giNhrteT69X1EPMQ1hK63aU,53565
31
31
  celldetective/gui/retrain_segmentation_model_options.py,sha256=-rkuUzI_vFFlZC3LAAYEELoJUKcz6PmkpCrxKZindhg,27218
32
32
  celldetective/gui/retrain_signal_model_options.py,sha256=uHZy3FGsGMHfZL_nYnuFiXF57XaAMVzjYxVF2OXhYnY,24184
33
33
  celldetective/gui/seg_model_loader.py,sha256=uKp8oab-4QdTGqb-tb6bOD-FLD_154GOvgWFYz97BwY,17350
34
34
  celldetective/gui/signal_annotator.py,sha256=4ymMpo_GjSBsJSRkyNKrWRLy0EFXHINbFtp9ykDqfGE,84864
35
35
  celldetective/gui/signal_annotator_options.py,sha256=-Q7f8eCwniqbgLJqMCa91Wc-V3VHAZidwt7LPd4Z5yU,10879
36
36
  celldetective/gui/styles.py,sha256=Vw4wr6MQ4iBwhOY-ZWAxFDZZ3CNohmEnuPPazwhJaho,4129
37
- celldetective/gui/survival_ui.py,sha256=Y7EbLFqINSBA_Cl3_fjGImbfp2PvpFt11pHuqkcT3OM,33537
38
- celldetective/gui/tableUI.py,sha256=DR2HVTLkR3XYZ_Rkyt7DLObOszuG7rlxyz5d6wIO1Oc,22467
39
- celldetective/gui/thresholds_gui.py,sha256=vbkiJcBejiqdk45r57Ig38LDyNMqLqqmh1FnaVltxVA,47821
40
- celldetective/gui/viewers.py,sha256=eN4JevoDGAZGI_QdmRJ3SJRh4_XGUR9BhA_ymAF4xAY,19676
37
+ celldetective/gui/survival_ui.py,sha256=2JGLC5m6D_gVLwnBAM7uEvuCKw1Cli8nM9i5s7TIpGg,33612
38
+ celldetective/gui/tableUI.py,sha256=QRYlXc7751Ka5qbUHSGbE_nXTiiezAVfEWXiRKRmuRM,32188
39
+ celldetective/gui/thresholds_gui.py,sha256=b8SkG4DlfxBRjacKTe1NSNkq7rJm8lnSLifH-mg846k,49529
40
+ celldetective/gui/viewers.py,sha256=G8uNb0U_4tJiZkcAWX9BbCSBIUbF4tjedZD-5o4WKxY,27734
41
41
  celldetective/icons/logo-large.png,sha256=FXSwV3u6zEKcfpuSn4unnqB0oUnN9cHqQ9BCKWytrpg,36631
42
42
  celldetective/icons/logo.png,sha256=wV2OS8_dU5Td5cgdPbCOU3JpMpTwNuYLnfVcnQX0tJA,2437
43
43
  celldetective/icons/signals_icon.png,sha256=vEiKoqWTtN0-uJgVqtAlwCuP-f4QeWYOlO3sdp2tg2w,3969
@@ -49,6 +49,9 @@ celldetective/icons/vignette_signals2.png,sha256=hsVOdQDpEfMGM45aaSeacEm3lvxbquR
49
49
  celldetective/icons/vignette_signals2.svg,sha256=muGNcQudV1jG-bmFd9FwV-Wb8PcrRV5osdZ7pHR7Ekk,5947
50
50
  celldetective/links/zenodo.json,sha256=7WKRuZY7MHTR-IChWBbU0i47H_479NtlxsCGaJn9-xM,22728
51
51
  celldetective/models/segmentation_effectors/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ celldetective/models/segmentation_effectors/primNK_cfse/config_input.json,sha256=gwEGP5wc6iVcwLrR5IbEb-9lTbdQuPyLLFYXh00374U,509
53
+ celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer,sha256=ps4BAzGxr2i2R0uBGJqfF9wjg5bIeSeBGQb0YcUChhY,26559970
54
+ celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json,sha256=DqEO4_oQuQmJkZiefREXz8ts60svoqxIQB-LMScuCnc,909
52
55
  celldetective/models/segmentation_generic/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
56
  celldetective/models/segmentation_targets/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
57
  celldetective/models/signal_detection/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -57,10 +60,10 @@ celldetective/models/tracking_configs/ricm.json,sha256=L-vmwCR1f89U-qnH2Ms0cBfPF
57
60
  celldetective/models/tracking_configs/ricm2.json,sha256=DDjJ6ScYcDWvlsy7ujPID8v8H28vcNcMuZmNR8XmGxo,2718
58
61
  celldetective/scripts/analyze_signals.py,sha256=23TXGNw-j5xT3ss4mXlnKdBgFLnQ50JUEQOC6_H7Q_0,2203
59
62
  celldetective/scripts/measure_cells.py,sha256=4uRG6Dg0WsO-N8ZaBJ4loWOvX6FdHaCblIFXq6Dtirc,11000
60
- celldetective/scripts/segment_cells.py,sha256=xz1wERezJFF3sI0tS3mRLD7-K0zhEIyAEH60p06DFgU,7660
63
+ celldetective/scripts/segment_cells.py,sha256=OSP52sPPHyhfXEjiXXdezkDY4MiFXLBWTb2_umRBD-M,8269
61
64
  celldetective/scripts/segment_cells_thresholds.py,sha256=GbWXa6xoO8s4PinJPZIxAuosw4vpzyJ7FiFYpSURojk,4998
62
65
  celldetective/scripts/track_cells.py,sha256=AaNiYEW4osYKKR2kbdVLOUnQEBbcZIA-D0mkhcxPWTY,7985
63
- celldetective/scripts/train_segmentation_model.py,sha256=dBXq3OOu6F0kWyYcI3K7W_hMUYvndrwKRswBS_-zQnw,8378
66
+ celldetective/scripts/train_segmentation_model.py,sha256=UY493QK7_FhS9uHYl2eeEYx7t0kw1jhvc0YMY12YZpI,8614
64
67
  celldetective/scripts/train_signal_model.py,sha256=9-dmPCLKJ9ypjsV9AwFd-Sb6B6YaHS0QGT218H5hUPo,1861
65
68
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
69
  tests/test_events.py,sha256=eLFwwEEJfQAdwhews3-fn1HSvzozcNNFN_Qn0gOvQkE,685
@@ -68,13 +71,14 @@ tests/test_filters.py,sha256=iJksl_HgquqGzPPv46qpNtlD4rkBpZ5eVtIotgZ7LDs,656
68
71
  tests/test_io.py,sha256=gk5FmoI7ANEczUtNXYRxc48KzkfYzemwS_eYaLq4_NI,2093
69
72
  tests/test_measure.py,sha256=FEUAs1rVHylvIvubCb0bJDNGZLVmkgXNgI3NaGQ1dA8,4542
70
73
  tests/test_neighborhood.py,sha256=gk5FmoI7ANEczUtNXYRxc48KzkfYzemwS_eYaLq4_NI,2093
74
+ tests/test_preprocessing.py,sha256=FI-Wk-kc4wWmOQg_NLCUIZC1oti396wr5cC-BauBai0,1436
71
75
  tests/test_segmentation.py,sha256=-3b7o_fUVMYxfVwX5VHFqRF0dDXObSTtylf5XQGcq1A,3493
72
76
  tests/test_signals.py,sha256=No4cah6KxplhDcKXnU8RrA7eDla4hWw6ccf7xGnBokU,3599
73
77
  tests/test_tracking.py,sha256=8hebWSqEIuttD1ABn-6dKCT7EXKRR7-4RwyFWi1WPFo,8800
74
- tests/test_utils.py,sha256=emElC0EgoIeCXnTweZVh-TFT2czu9XSgiRqP9sqFUX8,2175
75
- celldetective-1.1.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
76
- celldetective-1.1.0.dist-info/METADATA,sha256=ilgLPeG4uYwEibAGA2uO68p83-eWwP6k7azcQIF8gT4,12412
77
- celldetective-1.1.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
78
- celldetective-1.1.0.dist-info/entry_points.txt,sha256=2NU6_EOByvPxqBbCvjwxlVlvnQreqZ3BKRCVIKEv3dg,62
79
- celldetective-1.1.0.dist-info/top_level.txt,sha256=6rsIKKfGMKgud7HPuATcpq6EhdXwcg_yknBVWn9x4C4,20
80
- celldetective-1.1.0.dist-info/RECORD,,
78
+ tests/test_utils.py,sha256=NKRCAC1d89aBK5cWjTb7-pInYow901RrT-uBlIdz4KI,3692
79
+ celldetective-1.1.1.post1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
80
+ celldetective-1.1.1.post1.dist-info/METADATA,sha256=MItn6uMJhqWHbN0urj8068yO8xcUoc9c3kUsYTVre10,12418
81
+ celldetective-1.1.1.post1.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
82
+ celldetective-1.1.1.post1.dist-info/entry_points.txt,sha256=2NU6_EOByvPxqBbCvjwxlVlvnQreqZ3BKRCVIKEv3dg,62
83
+ celldetective-1.1.1.post1.dist-info/top_level.txt,sha256=6rsIKKfGMKgud7HPuATcpq6EhdXwcg_yknBVWn9x4C4,20
84
+ celldetective-1.1.1.post1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,37 @@
1
+ import unittest
2
+ import matplotlib.pyplot as plt
3
+ import numpy as np
4
+ import os
5
+ from celldetective.preprocessing import fit_background_model, field_correction
6
+
7
+ import matplotlib.pyplot as plt
8
+
9
+ class TestFitPlane(unittest.TestCase):
10
+
11
+ @classmethod
12
+ def setUpClass(self):
13
+ a = 5.
14
+ self.img = np.full((100,100),5.0)
15
+ self.img_with_cell = self.img.copy()
16
+ self.img_with_cell[:10,:10] = 25.0
17
+
18
+ def test_plane_is_well_fit(self):
19
+ mat = np.array(fit_background_model(self.img, cell_masks=None, model='plane', edge_exclusion=None))
20
+ self.assertTrue(np.allclose(self.img, mat))
21
+
22
+ def test_plane_is_well_fit_and_applied_with_division(self):
23
+ result = field_correction(self.img, threshold_on_std=1.0E05, operation='divide', model='plane', clip=False, return_bg=False, activation_protocol=[])
24
+ self.assertTrue(np.allclose(result, np.full((100,100), 1.0)))
25
+
26
+ def test_plane_is_well_fit_and_applied_with_subtraction(self):
27
+ result = field_correction(self.img, threshold_on_std=1.0E05, operation='subtract', model='plane', clip=False, return_bg=False, activation_protocol=[])
28
+ self.assertTrue(np.allclose(result, np.zeros((100,100))))
29
+
30
+ def test_plane_is_well_fit_with_cell(self):
31
+ cell_masks = np.zeros_like(self.img)
32
+ cell_masks[:10,:10] = 1.0
33
+ mat = np.array(fit_background_model(self.img, cell_masks=cell_masks, model='plane', edge_exclusion=None))
34
+ self.assertTrue(np.allclose(self.img, mat))
35
+
36
+ if __name__=="__main__":
37
+ unittest.main()