celldetective 1.0.2__py3-none-any.whl → 1.1.0__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.
- celldetective/__main__.py +2 -2
- celldetective/events.py +2 -44
- celldetective/filters.py +4 -5
- celldetective/gui/__init__.py +1 -1
- celldetective/gui/analyze_block.py +37 -10
- celldetective/gui/btrack_options.py +24 -23
- celldetective/gui/classifier_widget.py +62 -19
- celldetective/gui/configure_new_exp.py +32 -35
- celldetective/gui/control_panel.py +115 -81
- celldetective/gui/gui_utils.py +674 -396
- celldetective/gui/json_readers.py +7 -6
- celldetective/gui/layouts.py +755 -0
- celldetective/gui/measurement_options.py +168 -487
- celldetective/gui/neighborhood_options.py +322 -270
- celldetective/gui/plot_measurements.py +1114 -0
- celldetective/gui/plot_signals_ui.py +20 -20
- celldetective/gui/process_block.py +449 -169
- celldetective/gui/retrain_segmentation_model_options.py +27 -26
- celldetective/gui/retrain_signal_model_options.py +25 -24
- celldetective/gui/seg_model_loader.py +31 -27
- celldetective/gui/signal_annotator.py +2326 -2295
- celldetective/gui/signal_annotator_options.py +18 -16
- celldetective/gui/styles.py +16 -1
- celldetective/gui/survival_ui.py +61 -39
- celldetective/gui/tableUI.py +60 -23
- celldetective/gui/thresholds_gui.py +68 -66
- celldetective/gui/viewers.py +596 -0
- celldetective/io.py +234 -23
- celldetective/measure.py +37 -32
- celldetective/neighborhood.py +495 -27
- celldetective/preprocessing.py +683 -0
- celldetective/scripts/analyze_signals.py +7 -0
- celldetective/scripts/measure_cells.py +12 -0
- celldetective/scripts/segment_cells.py +5 -0
- celldetective/scripts/track_cells.py +11 -0
- celldetective/signals.py +221 -98
- celldetective/tracking.py +0 -1
- celldetective/utils.py +178 -36
- celldetective-1.1.0.dist-info/METADATA +305 -0
- celldetective-1.1.0.dist-info/RECORD +80 -0
- {celldetective-1.0.2.dist-info → celldetective-1.1.0.dist-info}/top_level.txt +1 -0
- tests/__init__.py +0 -0
- tests/test_events.py +28 -0
- tests/test_filters.py +24 -0
- tests/test_io.py +70 -0
- tests/test_measure.py +141 -0
- tests/test_neighborhood.py +70 -0
- tests/test_segmentation.py +93 -0
- tests/test_signals.py +135 -0
- tests/test_tracking.py +164 -0
- tests/test_utils.py +71 -0
- celldetective-1.0.2.dist-info/METADATA +0 -192
- celldetective-1.0.2.dist-info/RECORD +0 -66
- {celldetective-1.0.2.dist-info → celldetective-1.1.0.dist-info}/LICENSE +0 -0
- {celldetective-1.0.2.dist-info → celldetective-1.1.0.dist-info}/WHEEL +0 -0
- {celldetective-1.0.2.dist-info → celldetective-1.1.0.dist-info}/entry_points.txt +0 -0
celldetective/tracking.py
CHANGED
|
@@ -606,7 +606,6 @@ def interpolate_time_gaps(trajectories, column_labels={'track': "TRACK_ID", 'tim
|
|
|
606
606
|
trajectories.reset_index(drop=True, inplace=True)
|
|
607
607
|
trajectories[column_labels['time']] = trajectories[column_labels['time']].astype('int64').astype(float) / 10**9
|
|
608
608
|
#trajectories[column_labels['time']] = trajectories[column_labels['time']].astype('int64')
|
|
609
|
-
print(trajectories[column_labels['time']])
|
|
610
609
|
trajectories.sort_values(by=[column_labels['track'],column_labels['time']],inplace=True)
|
|
611
610
|
|
|
612
611
|
return trajectories
|
celldetective/utils.py
CHANGED
|
@@ -367,7 +367,7 @@ def compute_weights(y):
|
|
|
367
367
|
|
|
368
368
|
return class_weights
|
|
369
369
|
|
|
370
|
-
def train_test_split(data_x, data_y1,
|
|
370
|
+
def train_test_split(data_x, data_y1, data_class=None, validation_size=0.25, test_size=0, n_iterations=10):
|
|
371
371
|
|
|
372
372
|
"""
|
|
373
373
|
|
|
@@ -407,37 +407,56 @@ def train_test_split(data_x, data_y1, data_y2=None, validation_size=0.25, test_s
|
|
|
407
407
|
|
|
408
408
|
"""
|
|
409
409
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
np.random.shuffle(randomize)
|
|
410
|
+
if data_class is not None:
|
|
411
|
+
print(f"Unique classes: {np.sort(np.argmax(np.unique(data_class,axis=0),axis=1))}")
|
|
413
412
|
|
|
414
|
-
|
|
415
|
-
chunks = split_by_ratio(randomize, train_percentage, validation_size, test_size)
|
|
413
|
+
for i in range(n_iterations):
|
|
416
414
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
y2_train = data_y2[chunks[0]]
|
|
415
|
+
n_values = len(data_x)
|
|
416
|
+
randomize = np.arange(n_values)
|
|
417
|
+
np.random.shuffle(randomize)
|
|
421
418
|
|
|
419
|
+
train_percentage = 1 - validation_size - test_size
|
|
422
420
|
|
|
423
|
-
|
|
424
|
-
y1_val = data_y1[chunks[1]]
|
|
425
|
-
if data_y2 is not None:
|
|
426
|
-
y2_val = data_y2[chunks[1]]
|
|
421
|
+
chunks = split_by_ratio(randomize, train_percentage, validation_size, test_size)
|
|
427
422
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
423
|
+
x_train = data_x[chunks[0]]
|
|
424
|
+
y1_train = data_y1[chunks[0]]
|
|
425
|
+
if data_class is not None:
|
|
426
|
+
y2_train = data_class[chunks[0]]
|
|
427
|
+
|
|
428
|
+
x_val = data_x[chunks[1]]
|
|
429
|
+
y1_val = data_y1[chunks[1]]
|
|
430
|
+
if data_class is not None:
|
|
431
|
+
y2_val = data_class[chunks[1]]
|
|
432
|
+
|
|
433
|
+
if data_class is not None:
|
|
434
|
+
print(f"classes in train set: {np.sort(np.argmax(np.unique(y2_train,axis=0),axis=1))}; classes in validation set: {np.sort(np.argmax(np.unique(y2_val,axis=0),axis=1))}")
|
|
435
|
+
same_class_test = np.array_equal(np.sort(np.argmax(np.unique(y2_train,axis=0),axis=1)), np.sort(np.argmax(np.unique(y2_val,axis=0),axis=1)))
|
|
436
|
+
print(f"Check that classes are found in all sets: {same_class_test}...")
|
|
437
|
+
else:
|
|
438
|
+
same_class_test = True
|
|
439
|
+
|
|
440
|
+
if same_class_test:
|
|
441
|
+
|
|
442
|
+
ds = {"x_train": x_train, "x_val": x_val,
|
|
443
|
+
"y1_train": y1_train, "y1_val": y1_val}
|
|
444
|
+
if data_class is not None:
|
|
445
|
+
ds.update({"y2_train": y2_train, "y2_val": y2_val})
|
|
446
|
+
|
|
447
|
+
if test_size>0:
|
|
448
|
+
x_test = data_x[chunks[2]]
|
|
449
|
+
y1_test = data_y1[chunks[2]]
|
|
450
|
+
ds.update({"x_test": x_test, "y1_test": y1_test})
|
|
451
|
+
if data_class is not None:
|
|
452
|
+
y2_test = data_class[chunks[2]]
|
|
453
|
+
ds.update({"y2_test": y2_test})
|
|
454
|
+
return ds
|
|
455
|
+
else:
|
|
456
|
+
continue
|
|
457
|
+
|
|
458
|
+
raise Exception("Some classes are missing from the train or validation set... Abort.")
|
|
432
459
|
|
|
433
|
-
if test_size>0:
|
|
434
|
-
x_test = data_x[chunks[2]]
|
|
435
|
-
y1_test = data_y1[chunks[2]]
|
|
436
|
-
ds.update({"x_test": x_test, "y1_test": y1_test})
|
|
437
|
-
if data_y2 is not None:
|
|
438
|
-
y2_test = data_y2[chunks[2]]
|
|
439
|
-
ds.update({"y2_test": y2_test})
|
|
440
|
-
return ds
|
|
441
460
|
|
|
442
461
|
def remove_redundant_features(features, reference_features, channel_names=None):
|
|
443
462
|
|
|
@@ -482,7 +501,7 @@ def remove_redundant_features(features, reference_features, channel_names=None):
|
|
|
482
501
|
|
|
483
502
|
"""
|
|
484
503
|
|
|
485
|
-
new_features = features
|
|
504
|
+
new_features = features[:]
|
|
486
505
|
|
|
487
506
|
for f in features:
|
|
488
507
|
|
|
@@ -1201,11 +1220,32 @@ def color_from_class(cclass, recently_modified=False):
|
|
|
1201
1220
|
def random_fliprot(img, mask):
|
|
1202
1221
|
|
|
1203
1222
|
"""
|
|
1223
|
+
Randomly flips and rotates an image and its corresponding mask.
|
|
1224
|
+
|
|
1225
|
+
This function applies a series of random flips and permutations (rotations) to both the input image and its
|
|
1226
|
+
associated mask, ensuring that any transformations applied to the image are also exactly applied to the mask.
|
|
1227
|
+
The function is designed to handle multi-dimensional images (e.g., multi-channel images in YXC format where
|
|
1228
|
+
channels are last).
|
|
1229
|
+
|
|
1230
|
+
Parameters
|
|
1231
|
+
----------
|
|
1232
|
+
img : ndarray
|
|
1233
|
+
The input image to be transformed. This array is expected to have dimensions where the channel axis is last.
|
|
1234
|
+
mask : ndarray
|
|
1235
|
+
The mask corresponding to `img`, to be transformed in the same way as the image.
|
|
1236
|
+
|
|
1237
|
+
Returns
|
|
1238
|
+
-------
|
|
1239
|
+
tuple of ndarray
|
|
1240
|
+
A tuple containing the transformed image and mask.
|
|
1204
1241
|
|
|
1205
|
-
|
|
1206
|
-
|
|
1242
|
+
Raises
|
|
1243
|
+
------
|
|
1244
|
+
AssertionError
|
|
1245
|
+
If the number of dimensions of the mask exceeds that of the image, indicating incompatible shapes.
|
|
1207
1246
|
|
|
1208
1247
|
"""
|
|
1248
|
+
|
|
1209
1249
|
assert img.ndim >= mask.ndim
|
|
1210
1250
|
axes = tuple(range(mask.ndim))
|
|
1211
1251
|
perm = tuple(np.random.permutation(axes))
|
|
@@ -1225,12 +1265,37 @@ def random_fliprot(img, mask):
|
|
|
1225
1265
|
def random_shift(image,mask, max_shift_amplitude=0.1):
|
|
1226
1266
|
|
|
1227
1267
|
"""
|
|
1268
|
+
Randomly shifts an image and its corresponding mask along the X and Y axes.
|
|
1228
1269
|
|
|
1229
|
-
|
|
1230
|
-
|
|
1270
|
+
This function shifts both the image and the mask by a randomly chosen distance up to a maximum
|
|
1271
|
+
percentage of the image's dimensions, specified by `max_shift_amplitude`. The shifts are applied
|
|
1272
|
+
independently in both the X and Y directions. This type of augmentation can help improve the robustness
|
|
1273
|
+
of models to positional variations in images.
|
|
1274
|
+
|
|
1275
|
+
Parameters
|
|
1276
|
+
----------
|
|
1277
|
+
image : ndarray
|
|
1278
|
+
The input image to be shifted. Must be in YXC format (height, width, channels).
|
|
1279
|
+
mask : ndarray
|
|
1280
|
+
The mask corresponding to `image`, to be shifted in the same way as the image.
|
|
1281
|
+
max_shift_amplitude : float, optional
|
|
1282
|
+
The maximum shift as a fraction of the image's dimension. Default is 0.1 (10% of the image's size).
|
|
1283
|
+
|
|
1284
|
+
Returns
|
|
1285
|
+
-------
|
|
1286
|
+
tuple of ndarray
|
|
1287
|
+
A tuple containing the shifted image and mask.
|
|
1288
|
+
|
|
1289
|
+
Notes
|
|
1290
|
+
-----
|
|
1291
|
+
- The shift values are chosen randomly within the range defined by the maximum amplitude.
|
|
1292
|
+
- Shifting is performed using the 'constant' mode where missing values are filled with zeros (cval=0.0),
|
|
1293
|
+
which may introduce areas of zero-padding along the edges of the shifted images and masks.
|
|
1294
|
+
- This function is designed to support data augmentation for machine learning and image processing tasks,
|
|
1295
|
+
particularly in contexts where spatial invariance is beneficial.
|
|
1296
|
+
|
|
1297
|
+
"""
|
|
1231
1298
|
|
|
1232
|
-
"""
|
|
1233
|
-
|
|
1234
1299
|
input_shape = image.shape[0]
|
|
1235
1300
|
max_shift = input_shape*max_shift_amplitude
|
|
1236
1301
|
|
|
@@ -1249,9 +1314,35 @@ def random_shift(image,mask, max_shift_amplitude=0.1):
|
|
|
1249
1314
|
|
|
1250
1315
|
|
|
1251
1316
|
def blur(x,max_sigma=4.0):
|
|
1317
|
+
|
|
1252
1318
|
"""
|
|
1253
|
-
|
|
1319
|
+
Applies a random Gaussian blur to an image.
|
|
1320
|
+
|
|
1321
|
+
This function blurs an image by applying a Gaussian filter with a randomly chosen sigma value. The sigma
|
|
1322
|
+
represents the standard deviation for the Gaussian kernel and is selected randomly up to a specified maximum.
|
|
1323
|
+
The blurring is applied while preserving the range of the image's intensity values and maintaining any
|
|
1324
|
+
zero-valued pixels as they are.
|
|
1325
|
+
|
|
1326
|
+
Parameters
|
|
1327
|
+
----------
|
|
1328
|
+
x : ndarray
|
|
1329
|
+
The input image to be blurred. The image can have any number of channels, but must be in a format
|
|
1330
|
+
where the channels are the last dimension (YXC format).
|
|
1331
|
+
max_sigma : float, optional
|
|
1332
|
+
The maximum value for the standard deviation of the Gaussian blur. Default is 4.0.
|
|
1333
|
+
|
|
1334
|
+
Returns
|
|
1335
|
+
-------
|
|
1336
|
+
ndarray
|
|
1337
|
+
The blurred image. The output will have the same shape and type as the input image.
|
|
1338
|
+
|
|
1339
|
+
Notes
|
|
1340
|
+
-----
|
|
1341
|
+
- The function ensures that zero-valued pixels in the input image remain unchanged after the blurring,
|
|
1342
|
+
which can be important for maintaining masks or other specific regions within the image.
|
|
1343
|
+
- Gaussian blurring is commonly used in image processing to reduce image noise and detail by smoothing.
|
|
1254
1344
|
"""
|
|
1345
|
+
|
|
1255
1346
|
sigma = np.random.random()*max_sigma
|
|
1256
1347
|
loc_i,loc_j,loc_c = np.where(x==0.)
|
|
1257
1348
|
x = gaussian(x, sigma, channel_axis=-1, preserve_range=True)
|
|
@@ -1262,8 +1353,44 @@ def blur(x,max_sigma=4.0):
|
|
|
1262
1353
|
def noise(x, apply_probability=0.5, clip_option=False):
|
|
1263
1354
|
|
|
1264
1355
|
"""
|
|
1265
|
-
|
|
1356
|
+
Applies random noise to each channel of a multichannel image based on a specified probability.
|
|
1357
|
+
|
|
1358
|
+
This function introduces various types of random noise to an image. Each channel of the image can be
|
|
1359
|
+
modified independently with different noise models chosen randomly from a predefined list. The application
|
|
1360
|
+
of noise to any given channel is determined by a specified probability, allowing for selective noise
|
|
1361
|
+
addition.
|
|
1362
|
+
|
|
1363
|
+
Parameters
|
|
1364
|
+
----------
|
|
1365
|
+
x : ndarray
|
|
1366
|
+
The input multichannel image to which noise will be added. The image should be in format with channels
|
|
1367
|
+
as the last dimension (e.g., height x width x channels).
|
|
1368
|
+
apply_probability : float, optional
|
|
1369
|
+
The probability with which noise is applied to each channel of the image. Default is 0.5.
|
|
1370
|
+
clip_option : bool, optional
|
|
1371
|
+
Specifies whether to clip the corrupted data to stay within the valid range after noise addition.
|
|
1372
|
+
If True, the output array will be clipped to the range [0, 1] or [0, 255] depending on the input
|
|
1373
|
+
data type. Default is False.
|
|
1374
|
+
|
|
1375
|
+
Returns
|
|
1376
|
+
-------
|
|
1377
|
+
ndarray
|
|
1378
|
+
The noised image. This output has the same shape as the input but potentially altered intensity values
|
|
1379
|
+
due to noise addition.
|
|
1380
|
+
|
|
1381
|
+
Notes
|
|
1382
|
+
-----
|
|
1383
|
+
- The types of noise that can be applied include 'gaussian', 'localvar', 'poisson', and 'speckle'.
|
|
1384
|
+
- The choice of noise type for each channel is randomized and the noise is only applied if a randomly
|
|
1385
|
+
generated number is less than or equal to `apply_probability`.
|
|
1386
|
+
- Zero-valued pixels in the input image remain zero in the output to preserve background or masked areas.
|
|
1266
1387
|
|
|
1388
|
+
Examples
|
|
1389
|
+
--------
|
|
1390
|
+
>>> import numpy as np
|
|
1391
|
+
>>> x = np.random.rand(256, 256, 3) # Example 3-channel image
|
|
1392
|
+
>>> noised_image = noise(x)
|
|
1393
|
+
# The image 'x' may have different types of noise applied to each of its channels with a 50% probability.
|
|
1267
1394
|
"""
|
|
1268
1395
|
|
|
1269
1396
|
x_noise = x.astype(float).copy()
|
|
@@ -1678,4 +1805,19 @@ def download_zenodo_file(file, output_dir):
|
|
|
1678
1805
|
if file=='db-si-NucCondensation':
|
|
1679
1806
|
os.rename(os.sep.join([output_dir,'db1-NucCondensation']), os.sep.join([output_dir,file]))
|
|
1680
1807
|
|
|
1681
|
-
os.remove(path_to_zip_file)
|
|
1808
|
+
os.remove(path_to_zip_file)
|
|
1809
|
+
|
|
1810
|
+
def interpolate_nan(array_like):
|
|
1811
|
+
|
|
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
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: celldetective
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: description
|
|
5
|
+
Home-page: http://github.com/remyeltorro/celldetective
|
|
6
|
+
Author: Rémy Torro
|
|
7
|
+
Author-email: remy.torro@inserm.fr
|
|
8
|
+
License: GPL-3.0
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: wheel
|
|
12
|
+
Requires-Dist: nbsphinx
|
|
13
|
+
Requires-Dist: nbsphinx-link
|
|
14
|
+
Requires-Dist: sphinx-rtd-theme
|
|
15
|
+
Requires-Dist: sphinx ==5.0.2
|
|
16
|
+
Requires-Dist: jinja2 <3.1
|
|
17
|
+
Requires-Dist: ipykernel
|
|
18
|
+
Requires-Dist: stardist
|
|
19
|
+
Requires-Dist: cellpose <3
|
|
20
|
+
Requires-Dist: scikit-learn
|
|
21
|
+
Requires-Dist: btrack
|
|
22
|
+
Requires-Dist: tensorflow <=2.12.1
|
|
23
|
+
Requires-Dist: napari
|
|
24
|
+
Requires-Dist: tqdm
|
|
25
|
+
Requires-Dist: mahotas
|
|
26
|
+
Requires-Dist: fonticon-materialdesignicons6
|
|
27
|
+
Requires-Dist: art
|
|
28
|
+
Requires-Dist: lifelines
|
|
29
|
+
Requires-Dist: setuptools
|
|
30
|
+
Requires-Dist: scipy
|
|
31
|
+
Requires-Dist: seaborn
|
|
32
|
+
Requires-Dist: opencv-python-headless ==4.7.0.72
|
|
33
|
+
Requires-Dist: liblapack
|
|
34
|
+
Requires-Dist: gputools
|
|
35
|
+
Requires-Dist: lmfit ~=1.2.2
|
|
36
|
+
Requires-Dist: superqt[cmap] >=0.6.1
|
|
37
|
+
Requires-Dist: matplotlib-scalebar
|
|
38
|
+
|
|
39
|
+
# Celldetective
|
|
40
|
+
|
|
41
|
+
<embed>
|
|
42
|
+
<p align="center">
|
|
43
|
+
<img src="https://github.com/remyeltorro/celldetective/blob/main/celldetective/icons/logo-large.png" width="33%" />
|
|
44
|
+
</p>
|
|
45
|
+
</embed>
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+

|
|
49
|
+

|
|
50
|
+

|
|
51
|
+

|
|
52
|
+

|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
Celldetective is a python package and software to perform single-cell
|
|
56
|
+
analysis on multimodal time lapse microscopy images.
|
|
57
|
+
|
|
58
|
+
- **Documentation:** <https://celldetective.readthedocs.io>
|
|
59
|
+
- **Source code:** <https://github.com/remyeltorro/celldetective>
|
|
60
|
+
- **Bug reports:**
|
|
61
|
+
<https://github.com/remyeltorro/celldetective/issues/new/choose>
|
|
62
|
+
- **Datasets, models and demos:**
|
|
63
|
+
<https://zenodo.org/records/10650279>
|
|
64
|
+
|
|
65
|
+
## Overview
|
|
66
|
+
|
|
67
|
+
<embed>
|
|
68
|
+
<p align="center">
|
|
69
|
+
<img src="https://github.com/remyeltorro/celldetective/blob/main/docs/source/_static/celldetective-blocks.png" width="90%" />
|
|
70
|
+
</p>
|
|
71
|
+
</embed>
|
|
72
|
+
|
|
73
|
+
Despite notable efforts in the development of user-friendly softwares
|
|
74
|
+
that integrate state-of-the-art solutions to perform single cell
|
|
75
|
+
analysis, very few are designed for time-lapse data and even less for
|
|
76
|
+
multimodal problems where cells populations are mixed and can only be
|
|
77
|
+
separated through the use of multimodal information. Few software
|
|
78
|
+
solutions provide, to our knowledge, the extraction of response
|
|
79
|
+
functions from single cell events such as the dynamic survival of a
|
|
80
|
+
population directly in the GUI, as coding skills are usually required to
|
|
81
|
+
do so. We want to study complex data which is often multimodal time
|
|
82
|
+
lapse microscopy images of interacting cell populations, without loss of
|
|
83
|
+
generality. With a high need for an easy-to-use,
|
|
84
|
+
no-coding-skill-required software adapted to images and intended for
|
|
85
|
+
biologists, we introduce **Celldetective**, an open-source python-based
|
|
86
|
+
software with the following highlight features:
|
|
87
|
+
|
|
88
|
+
- **Comprehensive single-cell image analysis** : Celldetective ships
|
|
89
|
+
segmentation, tracking, and measurement modules, as well as event
|
|
90
|
+
detection from single-cell signals, for up to two populations of
|
|
91
|
+
interest.
|
|
92
|
+
- **Integration of state-of-the-art solutions** : Celldetective
|
|
93
|
+
harnesses state-of-the-art segmentation techniques (StarDist[^1],
|
|
94
|
+
Cellpose[^2] ,[^3]) and tracking algorithm (bTrack[^4]), as well as
|
|
95
|
+
the napari viewer[^5] where applicable. These algorithms are
|
|
96
|
+
interfaced to be well integrated and accessible for the target
|
|
97
|
+
audience, in the context of complex biological applications.
|
|
98
|
+
- **A framework for event description and annotations** : we propose a
|
|
99
|
+
broad and intuitive framework to annotate and automate the detection
|
|
100
|
+
of events from single-cell signals through Deep Learning signal
|
|
101
|
+
classification and regression. The event formulation is directly
|
|
102
|
+
exploited to define population survival responses.
|
|
103
|
+
- **A neighborhood scheme to study cell-cell interactions** : we
|
|
104
|
+
introduce a neighborhood scheme to relate the spatio-temporal
|
|
105
|
+
distribution and measurements of two cell populations, allowing the
|
|
106
|
+
study of how cell-cell interactions affect single-cell and
|
|
107
|
+
population responses.
|
|
108
|
+
- **Deep Learning customization in GUI** : Celldetective facilitates
|
|
109
|
+
the specialization of Deep Learning models or the creation of new
|
|
110
|
+
ones adapted to user data, by facilitating the creation of training
|
|
111
|
+
sets and the training of such models, without having to write a
|
|
112
|
+
single line of code.
|
|
113
|
+
- **In-software analysis** : Celldetective ships visualization tools
|
|
114
|
+
to collapse single-cell signals with respect to an event, build
|
|
115
|
+
survival curves, compare measurement distributions across biological
|
|
116
|
+
conditions.
|
|
117
|
+
- **A library of segmentation and signal models**: we created specific
|
|
118
|
+
models to investigate a co-culture of MCF-7 cells and primary NK
|
|
119
|
+
cells, that are available directly is the software with a large
|
|
120
|
+
collection of generalist models developed by the StarDist and
|
|
121
|
+
Cellpose teams, which are a perfect starting point to segment single
|
|
122
|
+
cells in a new biological system.
|
|
123
|
+
- **Accessible and open source** : Celldetective does not require any
|
|
124
|
+
coding skills. The software, its models and datasets are made fully
|
|
125
|
+
open source to encourage transparency and reproducibility.
|
|
126
|
+
|
|
127
|
+
<embed>
|
|
128
|
+
<p align="center">
|
|
129
|
+
<img src="https://github.com/remyeltorro/celldetective/blob/main/docs/source/_static/signal-annotator.gif" width="90%" />
|
|
130
|
+
</p>
|
|
131
|
+
</embed>
|
|
132
|
+
|
|
133
|
+
# System requirements
|
|
134
|
+
|
|
135
|
+
## Hardware requirements
|
|
136
|
+
|
|
137
|
+
The software was tested on several machines, including:
|
|
138
|
+
|
|
139
|
+
- An Intel(R) Core(TM) i9-10850K CPU @ 3.60GHz, with a single NVIDIA
|
|
140
|
+
GeForce RTX 3070 (8 Gb of memory) and 16 Gb of memory
|
|
141
|
+
- An Intel(R) Core(TM) i7-9750H CPU @ 2.60 GHz, with 16 Gb of memory
|
|
142
|
+
|
|
143
|
+
In GPU mode, succesive segmentation and DL signal analysis could be
|
|
144
|
+
performed without saturating the GPU memory thanks to the subprocess
|
|
145
|
+
formulation for the different modules. The GPU can be disabled in the
|
|
146
|
+
startup window. The software does not require a GPU (but model inference
|
|
147
|
+
will be longer). A typical analysis of a single movie with a GPU takes
|
|
148
|
+
between 5 to 15 minutes. Depending on the number of cells and frames on
|
|
149
|
+
the images, this computation time can increase to the order of half an
|
|
150
|
+
hour on a CPU.
|
|
151
|
+
|
|
152
|
+
The memory must be sufficient to load a movie stack at once in order to
|
|
153
|
+
visualize it in napari. Otherwise, processing is performed frame by
|
|
154
|
+
frame, therefore the memory required is extremely low.
|
|
155
|
+
|
|
156
|
+
## Software requirements
|
|
157
|
+
|
|
158
|
+
The software was developed simulateously on Ubuntu 20.04 and Windows 11.
|
|
159
|
+
It was tested on MacOS, but Tensorflow installation can rquire extra
|
|
160
|
+
steps.
|
|
161
|
+
|
|
162
|
+
- Linux: Ubuntu 20.04.6 LTS (Focal Fossa) (not tested on ulterior
|
|
163
|
+
versions)
|
|
164
|
+
- Windows: Windows 11 Home 23H2
|
|
165
|
+
|
|
166
|
+
To use the software, you must install python, *e.g.* through
|
|
167
|
+
[Anaconda](https://www.anaconda.com/download). We developed and tested
|
|
168
|
+
the software in Python 3.9.18.
|
|
169
|
+
|
|
170
|
+
# Installation
|
|
171
|
+
|
|
172
|
+
## Stable release
|
|
173
|
+
|
|
174
|
+
Celldetective can be installed with `pip`:
|
|
175
|
+
|
|
176
|
+
``` bash
|
|
177
|
+
pip install celldetective
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
We recommend that you create an environment to use Celldetective, *e.g.*
|
|
181
|
+
with `conda`:
|
|
182
|
+
|
|
183
|
+
``` bash
|
|
184
|
+
conda create -n celldetective python=3.9.18 pyqt
|
|
185
|
+
conda activate celldetective
|
|
186
|
+
pip install celldetective
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Need an update? Simply type the following in the terminal (in your
|
|
190
|
+
environment):
|
|
191
|
+
|
|
192
|
+
``` bash
|
|
193
|
+
pip install --upgrade celldetective
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Development version
|
|
197
|
+
|
|
198
|
+
### From GitHub
|
|
199
|
+
|
|
200
|
+
If you want to run the latest development version, you can clone the
|
|
201
|
+
repository to your local machine and install Celldetective in
|
|
202
|
+
"development" mode. This means that any changes to the cloned repository
|
|
203
|
+
will be immediately available in the python environment:
|
|
204
|
+
|
|
205
|
+
``` bash
|
|
206
|
+
# creates "celldetective" folder
|
|
207
|
+
git clone git://github.com/remyeltorro/celldetective.git
|
|
208
|
+
cd celldetective
|
|
209
|
+
|
|
210
|
+
# install the celldetective package in editable/development mode
|
|
211
|
+
pip install -r requirements.txt
|
|
212
|
+
pip install -e .
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
To run the latest development version without cloning the repository,
|
|
216
|
+
you can also use this line:
|
|
217
|
+
|
|
218
|
+
``` bash
|
|
219
|
+
pip install git+https//github.com/remyeltorro/celldetective.git
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### From a zip file
|
|
223
|
+
|
|
224
|
+
You can also download the repository as a compressed file. Unzip the
|
|
225
|
+
file and open a terminal at the root of the folder (same level as the
|
|
226
|
+
file requirements.txt). We recommend that you create a python
|
|
227
|
+
environment as Celldetective relies on many packages that may interfere
|
|
228
|
+
with package requirements for other projects. Run the following lines to
|
|
229
|
+
create an environment named \"celldetective\":
|
|
230
|
+
|
|
231
|
+
``` bash
|
|
232
|
+
conda create -n celldetective python=3.9.18 pyqt
|
|
233
|
+
conda activate celldetective
|
|
234
|
+
pip install -r requirements.txt
|
|
235
|
+
pip install .
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
The installation of the dependencies will take a few minutes (up to half
|
|
239
|
+
an hour if the network is bad). The Celldetective package itself is
|
|
240
|
+
light and installs in a few seconds.
|
|
241
|
+
|
|
242
|
+
Before launching the software, move to a different directory as running
|
|
243
|
+
the package locally can create some bugs when locating the models.
|
|
244
|
+
|
|
245
|
+
# Quick start
|
|
246
|
+
|
|
247
|
+
You can launch the GUI by 1) opening a terminal and 2) typing the
|
|
248
|
+
following:
|
|
249
|
+
|
|
250
|
+
``` bash
|
|
251
|
+
python -m celldetective
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
# Documentation
|
|
255
|
+
|
|
256
|
+
Read the tutorial here:
|
|
257
|
+
|
|
258
|
+
<https://celldetective.readthedocs.io/>
|
|
259
|
+
|
|
260
|
+
# How to cite?
|
|
261
|
+
|
|
262
|
+
If you use this software in your research, please cite the
|
|
263
|
+
[Celldetective](https://www.biorxiv.org/content/10.1101/2024.03.15.585250v1)
|
|
264
|
+
paper (currently preprint):
|
|
265
|
+
|
|
266
|
+
``` raw
|
|
267
|
+
@article {Torro2024.03.15.585250,
|
|
268
|
+
author = {R{\'e}my Torro and Beatriz D{\`\i}az-Bello and Dalia El Arawi and Lorna Ammer and Patrick Chames and Kheya Sengupta and Laurent Limozin},
|
|
269
|
+
title = {Celldetective: an AI-enhanced image analysis tool for unraveling dynamic cell interactions},
|
|
270
|
+
elocation-id = {2024.03.15.585250},
|
|
271
|
+
year = {2024},
|
|
272
|
+
doi = {10.1101/2024.03.15.585250},
|
|
273
|
+
publisher = {Cold Spring Harbor Laboratory},
|
|
274
|
+
abstract = {A current key challenge in bioimaging is the analysis of multimodal and multidimensional data reporting dynamic interactions between diverse cell populations. We developed Celldetective, a software that integrates AI-based segmentation and tracking algorithms and automated signal analysis into a user-friendly graphical interface. It offers complete interactive visualization, annotation, and training capabilities. We demonstrate it by analyzing original experimental data of spreading immune effector cells as well as antibody-dependent cell cytotoxicity events using multimodal fluorescence microscopy.Competing Interest StatementThe authors have declared no competing interest.},
|
|
275
|
+
URL = {https://www.biorxiv.org/content/early/2024/03/17/2024.03.15.585250},
|
|
276
|
+
eprint = {https://www.biorxiv.org/content/early/2024/03/17/2024.03.15.585250.full.pdf},
|
|
277
|
+
journal = {bioRxiv}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Make sure you to cite the papers of any segmentation model (StarDist,
|
|
282
|
+
Cellpose) or tracker (bTrack) you used through Celldetective.
|
|
283
|
+
|
|
284
|
+
# Bibliography
|
|
285
|
+
|
|
286
|
+
[^1]: Schmidt, U., Weigert, M., Broaddus, C. & Myers, G. Cell Detection
|
|
287
|
+
with Star-Convex Polygons. in Medical Image Computing and Computer
|
|
288
|
+
Assisted Intervention -- MICCAI 2018 (eds. Frangi, A. F., Schnabel,
|
|
289
|
+
J. A., Davatzikos, C., Alberola-López, C. & Fichtinger, G.) 265--273
|
|
290
|
+
(Springer International Publishing, Cham, 2018).
|
|
291
|
+
<doi:10.1007/978-3-030-00934-2_30>.
|
|
292
|
+
|
|
293
|
+
[^2]: Stringer, C., Wang, T., Michaelos, M. & Pachitariu, M. Cellpose: a
|
|
294
|
+
generalist algorithm for cellular segmentation. Nat Methods 18,
|
|
295
|
+
100--106 (2021).
|
|
296
|
+
|
|
297
|
+
[^3]: Pachitariu, M. & Stringer, C. Cellpose 2.0: how to train your own
|
|
298
|
+
model. Nat Methods 19, 1634--1641 (2022).
|
|
299
|
+
|
|
300
|
+
[^4]: Ulicna, K., Vallardi, G., Charras, G. & Lowe, A. R. Automated Deep
|
|
301
|
+
Lineage Tree Analysis Using a Bayesian Single Cell Tracking
|
|
302
|
+
Approach. Frontiers in Computer Science 3, (2021).
|
|
303
|
+
|
|
304
|
+
[^5]: Ahlers, J. et al. napari: a multi-dimensional image viewer for
|
|
305
|
+
Python. Zenodo <https://doi.org/10.5281/zenodo.8115575> (2023).
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
celldetective/__init__.py,sha256=FEZpJKcskBH2IginYzeqPWoR1lVGuyYCXhv7Hnlkoo8,49
|
|
2
|
+
celldetective/__main__.py,sha256=zX2ZDiUp02OlHSwsVUDJ6aCKRAAYU0SSmallsiz1HsA,14054
|
|
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
|
|
14
|
+
celldetective/datasets/segmentation_annotations/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
celldetective/datasets/signal_annotations/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
+
celldetective/gui/__init__.py,sha256=y2dvrUdJi17QMgPjl8WN3XFHYzJpu2ul4_8y7MQV1Bk,941
|
|
17
|
+
celldetective/gui/about.py,sha256=i-y54Opb10pKTVNUEcJC-D6Cbiqud2EJ3ZLayXqhdqc,1715
|
|
18
|
+
celldetective/gui/analyze_block.py,sha256=WD3JQQylx_dVozFCvNqrOyR6LcNHV7R1_gGh7XqOVeI,25423
|
|
19
|
+
celldetective/gui/btrack_options.py,sha256=eQEf63yTUsPCN-d1LqgAMmUQpfv2FH85FqnOSaR-9Q8,35575
|
|
20
|
+
celldetective/gui/classifier_widget.py,sha256=qvRl6svlelGsi-IRa7MrCGXrx4sRI8egl5xdGLH3r1A,15341
|
|
21
|
+
celldetective/gui/configure_new_exp.py,sha256=ANJ-Zn4sjBphtj_aoJu6m1PFEKyv9gxeh9XqS6xOGjk,18969
|
|
22
|
+
celldetective/gui/control_panel.py,sha256=Ndd6zeTNfo3KqfNeIa7XHX4Cj9GDKq5Qw1LtIsUQBgY,17466
|
|
23
|
+
celldetective/gui/gui_utils.py,sha256=PidFfdc8XASeIzZO5pfKgwqe4vROG7-KpYMcBZ42jdw,22673
|
|
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
|
|
27
|
+
celldetective/gui/neighborhood_options.py,sha256=sdKxVRliZtuKSpcPfnFxqkW4V8rN2tzjhDxOPVmElyE,20191
|
|
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
|
|
31
|
+
celldetective/gui/retrain_segmentation_model_options.py,sha256=-rkuUzI_vFFlZC3LAAYEELoJUKcz6PmkpCrxKZindhg,27218
|
|
32
|
+
celldetective/gui/retrain_signal_model_options.py,sha256=uHZy3FGsGMHfZL_nYnuFiXF57XaAMVzjYxVF2OXhYnY,24184
|
|
33
|
+
celldetective/gui/seg_model_loader.py,sha256=uKp8oab-4QdTGqb-tb6bOD-FLD_154GOvgWFYz97BwY,17350
|
|
34
|
+
celldetective/gui/signal_annotator.py,sha256=4ymMpo_GjSBsJSRkyNKrWRLy0EFXHINbFtp9ykDqfGE,84864
|
|
35
|
+
celldetective/gui/signal_annotator_options.py,sha256=-Q7f8eCwniqbgLJqMCa91Wc-V3VHAZidwt7LPd4Z5yU,10879
|
|
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
|
|
41
|
+
celldetective/icons/logo-large.png,sha256=FXSwV3u6zEKcfpuSn4unnqB0oUnN9cHqQ9BCKWytrpg,36631
|
|
42
|
+
celldetective/icons/logo.png,sha256=wV2OS8_dU5Td5cgdPbCOU3JpMpTwNuYLnfVcnQX0tJA,2437
|
|
43
|
+
celldetective/icons/signals_icon.png,sha256=vEiKoqWTtN0-uJgVqtAlwCuP-f4QeWYOlO3sdp2tg2w,3969
|
|
44
|
+
celldetective/icons/splash-test.png,sha256=W9smcuuwJUF9DU-rz4aACx7_rCmGRsxYUGPBDlDnrJk,17523
|
|
45
|
+
celldetective/icons/splash.png,sha256=J_1jPJylxwHGzGF1xCGocc-BmylHtHTII9VJSLKnezY,17895
|
|
46
|
+
celldetective/icons/splash0.png,sha256=qVXsrYUinm5g6-vbHcqwyjh8SIqs9lEqPWnPa1WijaQ,14233
|
|
47
|
+
celldetective/icons/survival2.png,sha256=8zsualD7d9VPAecoFA4Om9TFARErqpJzMg6U7XANXf4,4479
|
|
48
|
+
celldetective/icons/vignette_signals2.png,sha256=hsVOdQDpEfMGM45aaSeacEm3lvxbquRKKYutiS9qoS0,20743
|
|
49
|
+
celldetective/icons/vignette_signals2.svg,sha256=muGNcQudV1jG-bmFd9FwV-Wb8PcrRV5osdZ7pHR7Ekk,5947
|
|
50
|
+
celldetective/links/zenodo.json,sha256=7WKRuZY7MHTR-IChWBbU0i47H_479NtlxsCGaJn9-xM,22728
|
|
51
|
+
celldetective/models/segmentation_effectors/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
|
+
celldetective/models/segmentation_generic/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
|
+
celldetective/models/segmentation_targets/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
|
+
celldetective/models/signal_detection/blank,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
|
+
celldetective/models/tracking_configs/mcf7.json,sha256=iDjb8i6yxs0GleW39dvY3Ld5bZJatlXJrwI8PG3vCT0,1780
|
|
56
|
+
celldetective/models/tracking_configs/ricm.json,sha256=L-vmwCR1f89U-qnH2Ms0cBfPFR_dxIWoe2ccH8V-QBA,2727
|
|
57
|
+
celldetective/models/tracking_configs/ricm2.json,sha256=DDjJ6ScYcDWvlsy7ujPID8v8H28vcNcMuZmNR8XmGxo,2718
|
|
58
|
+
celldetective/scripts/analyze_signals.py,sha256=23TXGNw-j5xT3ss4mXlnKdBgFLnQ50JUEQOC6_H7Q_0,2203
|
|
59
|
+
celldetective/scripts/measure_cells.py,sha256=4uRG6Dg0WsO-N8ZaBJ4loWOvX6FdHaCblIFXq6Dtirc,11000
|
|
60
|
+
celldetective/scripts/segment_cells.py,sha256=xz1wERezJFF3sI0tS3mRLD7-K0zhEIyAEH60p06DFgU,7660
|
|
61
|
+
celldetective/scripts/segment_cells_thresholds.py,sha256=GbWXa6xoO8s4PinJPZIxAuosw4vpzyJ7FiFYpSURojk,4998
|
|
62
|
+
celldetective/scripts/track_cells.py,sha256=AaNiYEW4osYKKR2kbdVLOUnQEBbcZIA-D0mkhcxPWTY,7985
|
|
63
|
+
celldetective/scripts/train_segmentation_model.py,sha256=dBXq3OOu6F0kWyYcI3K7W_hMUYvndrwKRswBS_-zQnw,8378
|
|
64
|
+
celldetective/scripts/train_signal_model.py,sha256=9-dmPCLKJ9ypjsV9AwFd-Sb6B6YaHS0QGT218H5hUPo,1861
|
|
65
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
66
|
+
tests/test_events.py,sha256=eLFwwEEJfQAdwhews3-fn1HSvzozcNNFN_Qn0gOvQkE,685
|
|
67
|
+
tests/test_filters.py,sha256=iJksl_HgquqGzPPv46qpNtlD4rkBpZ5eVtIotgZ7LDs,656
|
|
68
|
+
tests/test_io.py,sha256=gk5FmoI7ANEczUtNXYRxc48KzkfYzemwS_eYaLq4_NI,2093
|
|
69
|
+
tests/test_measure.py,sha256=FEUAs1rVHylvIvubCb0bJDNGZLVmkgXNgI3NaGQ1dA8,4542
|
|
70
|
+
tests/test_neighborhood.py,sha256=gk5FmoI7ANEczUtNXYRxc48KzkfYzemwS_eYaLq4_NI,2093
|
|
71
|
+
tests/test_segmentation.py,sha256=-3b7o_fUVMYxfVwX5VHFqRF0dDXObSTtylf5XQGcq1A,3493
|
|
72
|
+
tests/test_signals.py,sha256=No4cah6KxplhDcKXnU8RrA7eDla4hWw6ccf7xGnBokU,3599
|
|
73
|
+
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,,
|
tests/__init__.py
ADDED
|
File without changes
|