celldetective 1.0.2.post1__py3-none-any.whl → 1.1.1__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 +7 -21
- celldetective/events.py +2 -44
- celldetective/extra_properties.py +62 -52
- 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 +120 -81
- celldetective/gui/gui_utils.py +674 -396
- celldetective/gui/json_readers.py +7 -6
- celldetective/gui/layouts.py +756 -0
- celldetective/gui/measurement_options.py +98 -513
- celldetective/gui/neighborhood_options.py +322 -270
- celldetective/gui/plot_measurements.py +1114 -0
- celldetective/gui/plot_signals_ui.py +21 -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 +67 -39
- celldetective/gui/tableUI.py +337 -48
- celldetective/gui/thresholds_gui.py +75 -71
- celldetective/gui/viewers.py +743 -0
- celldetective/io.py +247 -27
- celldetective/measure.py +43 -263
- celldetective/models/segmentation_effectors/primNK_cfse/config_input.json +29 -0
- celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer +0 -0
- celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json +37 -0
- celldetective/neighborhood.py +498 -27
- celldetective/preprocessing.py +1023 -0
- celldetective/scripts/analyze_signals.py +7 -0
- celldetective/scripts/measure_cells.py +12 -0
- celldetective/scripts/segment_cells.py +20 -4
- celldetective/scripts/track_cells.py +11 -0
- celldetective/scripts/train_segmentation_model.py +35 -34
- celldetective/segmentation.py +14 -9
- celldetective/signals.py +234 -329
- celldetective/tracking.py +2 -2
- celldetective/utils.py +602 -49
- celldetective-1.1.1.dist-info/METADATA +305 -0
- celldetective-1.1.1.dist-info/RECORD +84 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.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_preprocessing.py +37 -0
- tests/test_segmentation.py +93 -0
- tests/test_signals.py +135 -0
- tests/test_tracking.py +164 -0
- tests/test_utils.py +118 -0
- celldetective-1.0.2.post1.dist-info/METADATA +0 -221
- celldetective-1.0.2.post1.dist-info/RECORD +0 -66
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/LICENSE +0 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/WHEEL +0 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/entry_points.txt +0 -0
celldetective/measure.py
CHANGED
|
@@ -27,6 +27,7 @@ from skimage.draw import disk as dsk
|
|
|
27
27
|
from celldetective.filters import std_filter, gauss_filter
|
|
28
28
|
from celldetective.utils import rename_intensity_column, create_patch_mask, remove_redundant_features, \
|
|
29
29
|
remove_trajectory_measurements
|
|
30
|
+
from celldetective.preprocessing import field_correction
|
|
30
31
|
import celldetective.extra_properties as extra_properties
|
|
31
32
|
from celldetective.extra_properties import *
|
|
32
33
|
import cv2
|
|
@@ -308,10 +309,11 @@ def drop_tonal_features(features):
|
|
|
308
309
|
|
|
309
310
|
"""
|
|
310
311
|
|
|
312
|
+
feat2 = features[:]
|
|
311
313
|
for f in features:
|
|
312
314
|
if 'intensity' in f:
|
|
313
|
-
|
|
314
|
-
return
|
|
315
|
+
feat2.remove(f)
|
|
316
|
+
return feat2
|
|
315
317
|
|
|
316
318
|
def measure_features(img, label, features=['area', 'intensity_mean'], channels=None,
|
|
317
319
|
border_dist=None, haralick_options=None, verbose=True, normalisation_list=None,
|
|
@@ -389,26 +391,20 @@ def measure_features(img, label, features=['area', 'intensity_mean'], channels=N
|
|
|
389
391
|
columns=['count', 'spot_mean_intensity']).reset_index()
|
|
390
392
|
# Rename columns
|
|
391
393
|
df_spots.columns = ['label', 'spot_count', 'spot_mean_intensity']
|
|
394
|
+
|
|
392
395
|
if normalisation_list:
|
|
393
396
|
for norm in normalisation_list:
|
|
394
397
|
for index, channel in enumerate(channels):
|
|
395
|
-
if channel == norm['
|
|
398
|
+
if channel == norm['target_channel']:
|
|
396
399
|
ind = index
|
|
397
|
-
if norm['
|
|
400
|
+
if norm['correction_type'] == 'local':
|
|
398
401
|
normalised_image = normalise_by_cell(img[:, :, ind].copy(), label,
|
|
399
|
-
distance=int(norm['distance']),
|
|
400
|
-
operation=norm['operation'])
|
|
402
|
+
distance=int(norm['distance']), model=norm['model'],
|
|
403
|
+
operation=norm['operation'], clip=norm['clip'])
|
|
401
404
|
img[:, :, ind] = normalised_image
|
|
402
405
|
else:
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
normalisation_operation=norm['operation'],
|
|
406
|
-
clip=False, mode=norm['type'])
|
|
407
|
-
else:
|
|
408
|
-
normalised_image, bg = field_normalisation(img[:, :, ind].copy(), threshold=norm['threshold'],
|
|
409
|
-
normalisation_operation=norm['operation'],
|
|
410
|
-
clip=norm['clip'], mode=norm['type'])
|
|
411
|
-
img[:, :, ind] = normalised_image
|
|
406
|
+
corrected_image = field_correction(img[:,:,ind].copy(), threshold_on_std=norm['threshold_on_std'], operation=norm['operation'], model=norm['model'], clip=norm['clip'])
|
|
407
|
+
img[:, :, ind] = corrected_image
|
|
412
408
|
|
|
413
409
|
extra_props = getmembers(extra_properties, isfunction)
|
|
414
410
|
extra_props = [extra_props[i][0] for i in range(len(extra_props))]
|
|
@@ -725,7 +721,7 @@ def measure_isotropic_intensity(positions, # Dataframe of cell positions @ t
|
|
|
725
721
|
|
|
726
722
|
"""
|
|
727
723
|
|
|
728
|
-
|
|
724
|
+
epsilon = -10000
|
|
729
725
|
assert ((img.ndim==2)|(img.ndim==3)),f'Invalid image shape to compute the Haralick features. Expected YXC, got {img.shape}...'
|
|
730
726
|
|
|
731
727
|
if img.ndim==2:
|
|
@@ -753,7 +749,7 @@ def measure_isotropic_intensity(positions, # Dataframe of cell positions @ t
|
|
|
753
749
|
|
|
754
750
|
pad_value_x = mask.shape[0]//2 + 1
|
|
755
751
|
pad_value_y = mask.shape[1]//2 + 1
|
|
756
|
-
frame_padded = np.pad(img, [(pad_value_x,pad_value_x),(pad_value_y,pad_value_y),(0,0)])
|
|
752
|
+
frame_padded = np.pad(img.astype(float), [(pad_value_x,pad_value_x),(pad_value_y,pad_value_y),(0,0)], constant_values=[(epsilon,epsilon),(epsilon,epsilon),(0,0)])
|
|
757
753
|
|
|
758
754
|
# Find a way to measure intensity in mask
|
|
759
755
|
for tid,group in positions.groupby(column_labels['track']):
|
|
@@ -770,11 +766,17 @@ def measure_isotropic_intensity(positions, # Dataframe of cell positions @ t
|
|
|
770
766
|
|
|
771
767
|
expanded_mask = np.expand_dims(mask, axis=-1) # shape: (X, Y, 1)
|
|
772
768
|
crop = frame_padded[ymin:ymax,xmin:xmax]
|
|
773
|
-
|
|
769
|
+
|
|
770
|
+
crop_temp = crop.copy()
|
|
771
|
+
crop_temp[crop_temp==epsilon] = 0.
|
|
772
|
+
projection = np.multiply(crop_temp, expanded_mask)
|
|
773
|
+
|
|
774
|
+
projection[crop==epsilon] = epsilon
|
|
775
|
+
projection[expanded_mask[:,:,0]==0.,:] = epsilon
|
|
774
776
|
|
|
775
777
|
for op in operations:
|
|
776
778
|
func = eval('np.'+op)
|
|
777
|
-
intensity_values = func(projection, axis=(0,1), where=projection
|
|
779
|
+
intensity_values = func(projection, axis=(0,1), where=projection>epsilon)
|
|
778
780
|
for k in range(crop.shape[-1]):
|
|
779
781
|
if isinstance(r,list):
|
|
780
782
|
positions.loc[group.index, f'{channels[k]}_ring_{min(r)}_{max(r)}_{op}'] = intensity_values[k]
|
|
@@ -806,7 +808,7 @@ def measure_isotropic_intensity(positions, # Dataframe of cell positions @ t
|
|
|
806
808
|
|
|
807
809
|
for op in operations:
|
|
808
810
|
func = eval('np.'+op)
|
|
809
|
-
intensity_values = func(projection, axis=(0,1), where=projection
|
|
811
|
+
intensity_values = func(projection, axis=(0,1), where=projection==projection)
|
|
810
812
|
for k in range(crop.shape[-1]):
|
|
811
813
|
positions.loc[group.index, f'{channels[k]}_custom_kernel_{op}'] = intensity_values[k]
|
|
812
814
|
|
|
@@ -860,7 +862,7 @@ def measure_at_position(pos, mode, return_measurements=False, threads=1):
|
|
|
860
862
|
return None
|
|
861
863
|
|
|
862
864
|
|
|
863
|
-
def local_normalisation(image, labels, background_intensity,
|
|
865
|
+
def local_normalisation(image, labels, background_intensity, measurement='intensity_median', operation='subtract', clip=False):
|
|
864
866
|
"""
|
|
865
867
|
Perform local normalization on an image based on labels.
|
|
866
868
|
|
|
@@ -900,19 +902,23 @@ def local_normalisation(image, labels, background_intensity, mode, operation):
|
|
|
900
902
|
based on the mode specified.
|
|
901
903
|
- The background intensity values should be provided in the same order as the labels.
|
|
902
904
|
"""
|
|
905
|
+
|
|
903
906
|
for index, cell in enumerate(np.unique(labels)):
|
|
904
907
|
if cell == 0:
|
|
905
908
|
continue
|
|
906
|
-
if operation == '
|
|
909
|
+
if operation == 'subtract':
|
|
907
910
|
image[np.where(labels == cell)] = image[np.where(labels == cell)].astype(float) - \
|
|
908
|
-
background_intensity[
|
|
909
|
-
elif operation == '
|
|
911
|
+
background_intensity[measurement][index-1].astype(float)
|
|
912
|
+
elif operation == 'divide':
|
|
910
913
|
image[np.where(labels == cell)] = image[np.where(labels == cell)].astype(float) / \
|
|
911
|
-
background_intensity[
|
|
914
|
+
background_intensity[measurement][index-1].astype(float)
|
|
915
|
+
if clip:
|
|
916
|
+
image[image<=0.] = 0.
|
|
917
|
+
|
|
912
918
|
return image.astype(float)
|
|
913
919
|
|
|
914
920
|
|
|
915
|
-
def normalise_by_cell(image, labels, distance,
|
|
921
|
+
def normalise_by_cell(image, labels, distance=5, model='median', operation='subtract', clip=False):
|
|
916
922
|
"""
|
|
917
923
|
Normalize an image based on cell regions.
|
|
918
924
|
|
|
@@ -950,250 +956,24 @@ def normalise_by_cell(image, labels, distance, mode, operation):
|
|
|
950
956
|
- The operation determines whether to subtract or divide the background intensity from the image.
|
|
951
957
|
"""
|
|
952
958
|
border = contour_of_instance_segmentation(label=labels, distance=distance * (-1))
|
|
953
|
-
if
|
|
959
|
+
if model == 'mean':
|
|
960
|
+
measurement = 'intensity_nanmean'
|
|
961
|
+
extra_props = [getattr(extra_properties, measurement)]
|
|
954
962
|
background_intensity = regionprops_table(intensity_image=image, label_image=border,
|
|
955
|
-
|
|
956
|
-
elif
|
|
957
|
-
|
|
958
|
-
|
|
963
|
+
extra_properties=extra_props)
|
|
964
|
+
elif model == 'median':
|
|
965
|
+
measurement = 'intensity_median'
|
|
966
|
+
extra_props = [getattr(extra_properties, measurement)]
|
|
959
967
|
background_intensity = regionprops_table(intensity_image=image, label_image=border,
|
|
960
|
-
extra_properties=
|
|
968
|
+
extra_properties=extra_props)
|
|
969
|
+
|
|
961
970
|
normalised_frame = local_normalisation(image=image.astype(float).copy(),
|
|
962
|
-
labels=labels, background_intensity=background_intensity,
|
|
963
|
-
operation=operation)
|
|
971
|
+
labels=labels, background_intensity=background_intensity, measurement=measurement,
|
|
972
|
+
operation=operation, clip=clip)
|
|
964
973
|
|
|
965
974
|
return normalised_frame
|
|
966
975
|
|
|
967
976
|
|
|
968
|
-
def paraboloid(x, y, a, b, c, d, e, g):
|
|
969
|
-
return a * x ** 2 + b * y ** 2 + c * x * y + d * x + e * y + g
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
def plane(x, y, a, b, c):
|
|
973
|
-
return a * x + b * y + c
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
def fit_plane(image, cell_masks=None):
|
|
977
|
-
"""
|
|
978
|
-
Fit a plane to the given image data.
|
|
979
|
-
|
|
980
|
-
Parameters:
|
|
981
|
-
- image (numpy.ndarray): The input image data.
|
|
982
|
-
- cell_masks (numpy.ndarray, optional): An array specifying cell masks. If provided, areas covered by
|
|
983
|
-
cell masks will be excluded from the fitting process.
|
|
984
|
-
|
|
985
|
-
Returns:
|
|
986
|
-
- numpy.ndarray: The fitted plane.
|
|
987
|
-
|
|
988
|
-
This function fits a plane to the given image data using least squares regression. It constructs a mesh
|
|
989
|
-
grid based on the dimensions of the image and fits a plane model to the data points. If cell masks are
|
|
990
|
-
provided, areas covered by cell masks will be excluded from the fitting process.
|
|
991
|
-
|
|
992
|
-
Example:
|
|
993
|
-
>>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
|
994
|
-
>>> result = fit_plane(image)
|
|
995
|
-
>>> print(result)
|
|
996
|
-
[[1. 2. 3.]
|
|
997
|
-
[4. 5. 6.]
|
|
998
|
-
[7. 8. 9.]]
|
|
999
|
-
|
|
1000
|
-
Note:
|
|
1001
|
-
- The 'cell_masks' parameter allows excluding areas covered by cell masks from the fitting process.
|
|
1002
|
-
"""
|
|
1003
|
-
data = np.empty(image.shape)
|
|
1004
|
-
x = np.arange(0, image.shape[1])
|
|
1005
|
-
y = np.arange(0, image.shape[0])
|
|
1006
|
-
xx, yy = np.meshgrid(x, y)
|
|
1007
|
-
params = Parameters()
|
|
1008
|
-
params.add('a', value=1)
|
|
1009
|
-
params.add('b', value=1)
|
|
1010
|
-
params.add('c', value=1)
|
|
1011
|
-
model = Model(plane, independent_vars=['x', 'y'])
|
|
1012
|
-
weights = np.ones_like(xx, dtype=float)
|
|
1013
|
-
weights[np.where(cell_masks > 0)] = 0.
|
|
1014
|
-
result = model.fit(image,
|
|
1015
|
-
x=xx,
|
|
1016
|
-
y=yy,
|
|
1017
|
-
weights=weights,
|
|
1018
|
-
params=params, max_nfev=100)
|
|
1019
|
-
a = result.params['a'].value
|
|
1020
|
-
b = result.params['b'].value
|
|
1021
|
-
c = result.params['c'].value
|
|
1022
|
-
fitted_plane = plane(xx, yy, a, b, c)
|
|
1023
|
-
return fitted_plane
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
def fit_paraboloid(image, cell_masks=None):
|
|
1027
|
-
"""
|
|
1028
|
-
Fit a paraboloid to the given image data.
|
|
1029
|
-
|
|
1030
|
-
Parameters:
|
|
1031
|
-
- image (numpy.ndarray): The input image data.
|
|
1032
|
-
- cell_masks (numpy.ndarray, optional): An array specifying cell masks. If provided, areas covered by
|
|
1033
|
-
cell masks will be excluded from the fitting process.
|
|
1034
|
-
|
|
1035
|
-
Returns:
|
|
1036
|
-
- numpy.ndarray: The fitted paraboloid.
|
|
1037
|
-
|
|
1038
|
-
This function fits a paraboloid to the given image data using least squares regression. It constructs
|
|
1039
|
-
a mesh grid based on the dimensions of the image and fits a paraboloid model to the data points. If cell
|
|
1040
|
-
masks are provided, areas covered by cell masks will be excluded from the fitting process.
|
|
1041
|
-
|
|
1042
|
-
Example:
|
|
1043
|
-
>>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
|
1044
|
-
>>> result = fit_paraboloid(image)
|
|
1045
|
-
>>> print(result)
|
|
1046
|
-
[[1. 2. 3.]
|
|
1047
|
-
[4. 5. 6.]
|
|
1048
|
-
[7. 8. 9.]]
|
|
1049
|
-
|
|
1050
|
-
Note:
|
|
1051
|
-
- The 'cell_masks' parameter allows excluding areas covered by cell masks from the fitting process.
|
|
1052
|
-
"""
|
|
1053
|
-
data = np.empty(image.shape)
|
|
1054
|
-
x = np.arange(0, image.shape[1])
|
|
1055
|
-
y = np.arange(0, image.shape[0])
|
|
1056
|
-
xx, yy = np.meshgrid(x, y)
|
|
1057
|
-
params = Parameters()
|
|
1058
|
-
params.add('a', value=1)
|
|
1059
|
-
params.add('b', value=1)
|
|
1060
|
-
params.add('c', value=1)
|
|
1061
|
-
params.add('d', value=1)
|
|
1062
|
-
params.add('e', value=1)
|
|
1063
|
-
params.add('g', value=1)
|
|
1064
|
-
model = Model(paraboloid, independent_vars=['x', 'y'])
|
|
1065
|
-
weights = np.ones_like(xx, dtype=float)
|
|
1066
|
-
weights[np.where(cell_masks > 0)] = 0.
|
|
1067
|
-
|
|
1068
|
-
result = model.fit(image,
|
|
1069
|
-
x=xx,
|
|
1070
|
-
y=yy,
|
|
1071
|
-
weights=weights,
|
|
1072
|
-
params=params, max_nfev=100)
|
|
1073
|
-
a = result.params['a'].value
|
|
1074
|
-
b = result.params['b'].value
|
|
1075
|
-
c = result.params['c'].value
|
|
1076
|
-
d = result.params['d'].value
|
|
1077
|
-
e = result.params['e'].value
|
|
1078
|
-
g = result.params['g'].value
|
|
1079
|
-
fitted_paraboloid = paraboloid(xx, yy, a, b, c, d, e, g)
|
|
1080
|
-
return fitted_paraboloid
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
def correct_image(img, cell_masks=None, normalisation_operation=None, clip=False, mode=None):
|
|
1084
|
-
"""
|
|
1085
|
-
Correct an image based on fitted models.
|
|
1086
|
-
|
|
1087
|
-
Parameters:
|
|
1088
|
-
- img (numpy.ndarray): The input image data.
|
|
1089
|
-
- cell_masks (numpy.ndarray, optional): An array specifying cell masks. If provided, areas covered by
|
|
1090
|
-
cell masks will be considered during correction.
|
|
1091
|
-
- normalisation_operation (str, optional): The normalisation operation ('Subtract' or 'Divide') to apply
|
|
1092
|
-
during correction.
|
|
1093
|
-
- clip (bool, optional): Whether to clip corrected values below zero to a minimum value of 0.00001.
|
|
1094
|
-
- mode (str, optional): The mode of correction ('Paraboloid' or 'Plane').
|
|
1095
|
-
|
|
1096
|
-
Returns:
|
|
1097
|
-
- tuple: A tuple containing the corrected image and the fitted model parameters.
|
|
1098
|
-
|
|
1099
|
-
This function corrects an image based on fitted models such as paraboloid or plane. It first fits a model
|
|
1100
|
-
to the image data based on the specified mode. Then, it performs correction by subtracting or dividing the
|
|
1101
|
-
image by the fitted model. Optionally, it clips corrected values below zero to a minimum value of 0.00001.
|
|
1102
|
-
|
|
1103
|
-
Example:
|
|
1104
|
-
>>> img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
|
1105
|
-
>>> correction, para = correct_image(img, mode='Paraboloid', normalisation_operation='Subtract', clip=True)
|
|
1106
|
-
>>> print(correction)
|
|
1107
|
-
[[0. 0. 0.]
|
|
1108
|
-
[0. 0. 0.]
|
|
1109
|
-
[0. 0. 0.]]
|
|
1110
|
-
>>> print(para)
|
|
1111
|
-
[[1. 2. 3.]
|
|
1112
|
-
[4. 5. 6.]
|
|
1113
|
-
[7. 8. 9.]]
|
|
1114
|
-
|
|
1115
|
-
Note:
|
|
1116
|
-
- The 'cell_masks' parameter allows considering areas covered by cell masks during correction.
|
|
1117
|
-
- The 'normalisation_operation' parameter specifies whether to subtract or divide the fitted model from
|
|
1118
|
-
the image.
|
|
1119
|
-
- If 'clip' is set to True, corrected values below zero will be clipped to a minimum value of 0.00001.
|
|
1120
|
-
"""
|
|
1121
|
-
if mode == "Paraboloid":
|
|
1122
|
-
para = fit_paraboloid(img.astype(float), cell_masks=cell_masks).astype(float)
|
|
1123
|
-
elif mode == "Plane":
|
|
1124
|
-
para = fit_plane(img.astype(float), cell_masks=cell_masks).astype(float)
|
|
1125
|
-
|
|
1126
|
-
if para is not None:
|
|
1127
|
-
para = np.array(para)
|
|
1128
|
-
if normalisation_operation == 'Subtract':
|
|
1129
|
-
correction = img.astype(float) - para.astype(float) # + 1000.
|
|
1130
|
-
else:
|
|
1131
|
-
correction = img.astype(float) / para.astype(float) # + 1000.
|
|
1132
|
-
correction = np.array(correction, dtype=float)
|
|
1133
|
-
if clip:
|
|
1134
|
-
correction[correction <= 0] = 0.00001
|
|
1135
|
-
|
|
1136
|
-
else:
|
|
1137
|
-
correction = None
|
|
1138
|
-
|
|
1139
|
-
return correction, para
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
def field_normalisation(img, threshold, normalisation_operation, clip, mode):
|
|
1143
|
-
"""
|
|
1144
|
-
Perform field normalization on an image.
|
|
1145
|
-
|
|
1146
|
-
Parameters:
|
|
1147
|
-
- img (numpy.ndarray): The input image data.
|
|
1148
|
-
- threshold (float): The threshold value for determining regions of interest.
|
|
1149
|
-
- normalisation_operation (str): The normalization operation ('Subtract' or 'Divide') to apply during correction.
|
|
1150
|
-
- clip (bool): Whether to clip corrected values below zero to a minimum value of 0.00001.
|
|
1151
|
-
- mode (str): The mode of correction ('Paraboloid' or 'Plane').
|
|
1152
|
-
|
|
1153
|
-
Returns:
|
|
1154
|
-
- tuple: A tuple containing the normalized image and the fitted background model.
|
|
1155
|
-
|
|
1156
|
-
This function performs field normalization on an image based on regions of interest determined by the
|
|
1157
|
-
specified threshold. It identifies regions with standard deviation above the threshold and considers them
|
|
1158
|
-
as areas of interest. Then, it corrects the image using the 'correct_image' function based on the specified
|
|
1159
|
-
mode and normalization operation.
|
|
1160
|
-
|
|
1161
|
-
Example:
|
|
1162
|
-
>>> img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
|
1163
|
-
>>> fluo_max, bg_fit = field_normalisation(img, threshold=0.5, normalisation_operation='Subtract', clip=True, mode='Paraboloid')
|
|
1164
|
-
>>> print(fluo_max)
|
|
1165
|
-
[[0. 0. 0.]
|
|
1166
|
-
[0. 0. 0.]
|
|
1167
|
-
[0. 0. 0.]]
|
|
1168
|
-
>>> print(bg_fit)
|
|
1169
|
-
[[1. 2. 3.]
|
|
1170
|
-
[4. 5. 6.]
|
|
1171
|
-
[7. 8. 9.]]
|
|
1172
|
-
|
|
1173
|
-
Note:
|
|
1174
|
-
- The 'threshold' parameter determines regions of interest based on standard deviation.
|
|
1175
|
-
- The 'normalisation_operation' parameter specifies whether to subtract or divide the fitted model from
|
|
1176
|
-
the image during correction.
|
|
1177
|
-
- If 'clip' is set to True, corrected values below zero will be clipped to a minimum value of 0.00001.
|
|
1178
|
-
"""
|
|
1179
|
-
std_img = std_filter(gauss_filter(img, 2), 4)
|
|
1180
|
-
mask = np.zeros_like(img)
|
|
1181
|
-
if threshold=='':
|
|
1182
|
-
pass
|
|
1183
|
-
mask[np.where(std_img > float(threshold))] = 1.0
|
|
1184
|
-
mask_int = mask.astype(int)
|
|
1185
|
-
mask_int = binary_fill_holes(mask_int).astype(float)
|
|
1186
|
-
# invert_mask = np.zeros_like(mask_int)
|
|
1187
|
-
# invert_mask[mask_int == 0] = 1
|
|
1188
|
-
# if isinstance(normalisation_operation,bool) and normalisation_operation:
|
|
1189
|
-
# normalisation_operation = 'Subtract'
|
|
1190
|
-
# else:
|
|
1191
|
-
# normalisation_operation = 'Divide'
|
|
1192
|
-
fluo_max, bg_fit = correct_image(img.astype(float), cell_masks=mask_int,
|
|
1193
|
-
normalisation_operation=normalisation_operation, clip=clip, mode=mode)
|
|
1194
|
-
return fluo_max, bg_fit
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
977
|
def blob_detection(image, label, threshold, diameter):
|
|
1198
978
|
"""
|
|
1199
979
|
Perform blob detection on an image based on labeled regions.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"channels": [
|
|
3
|
+
"effector_fluo_channel",
|
|
4
|
+
"None"
|
|
5
|
+
],
|
|
6
|
+
"diameter": 30.0,
|
|
7
|
+
"cellprob_threshold": 0.0,
|
|
8
|
+
"flow_threshold": 0.4,
|
|
9
|
+
"normalization_percentile": [
|
|
10
|
+
true,
|
|
11
|
+
true
|
|
12
|
+
],
|
|
13
|
+
"normalization_clip": [
|
|
14
|
+
true,
|
|
15
|
+
true
|
|
16
|
+
],
|
|
17
|
+
"normalization_values": [
|
|
18
|
+
[
|
|
19
|
+
0.5,
|
|
20
|
+
99.0
|
|
21
|
+
],
|
|
22
|
+
[
|
|
23
|
+
1.0,
|
|
24
|
+
99.0
|
|
25
|
+
]
|
|
26
|
+
],
|
|
27
|
+
"model_type": "cellpose",
|
|
28
|
+
"spatial_calibration": 0.21783999999999998
|
|
29
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"model_name": "cp-cfse-transfer",
|
|
3
|
+
"model_type": "cellpose",
|
|
4
|
+
"pretrained": "/home/limozin/Documents/GitHub/celldetective/celldetective/models/segmentation_generic/CP_cyto2",
|
|
5
|
+
"spatial_calibration": 0.21783999999999998,
|
|
6
|
+
"channel_option": [
|
|
7
|
+
"effector_fluo_channel",
|
|
8
|
+
"None"
|
|
9
|
+
],
|
|
10
|
+
"normalization_percentile": [
|
|
11
|
+
true,
|
|
12
|
+
true
|
|
13
|
+
],
|
|
14
|
+
"normalization_clip": [
|
|
15
|
+
true,
|
|
16
|
+
true
|
|
17
|
+
],
|
|
18
|
+
"normalization_values": [
|
|
19
|
+
[
|
|
20
|
+
0.5,
|
|
21
|
+
99.0
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
1.0,
|
|
25
|
+
99.0
|
|
26
|
+
]
|
|
27
|
+
],
|
|
28
|
+
"ds": [
|
|
29
|
+
"/home/limozin/Desktop/primNK_w_MCF7/dataset"
|
|
30
|
+
],
|
|
31
|
+
"augmentation_factor": 1.5,
|
|
32
|
+
"validation_split": 0.2,
|
|
33
|
+
"learning_rate": 0.001,
|
|
34
|
+
"batch_size": 8,
|
|
35
|
+
"epochs": 3000,
|
|
36
|
+
"target_directory": "/home/limozin/Documents/GitHub/celldetective/celldetective/models/segmentation_effectors"
|
|
37
|
+
}
|