microlive 1.0.2__py2.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.
- microlive/__init__.py +44 -0
- microlive/data/__init__.py +0 -0
- microlive/data/icons/__init__.py +0 -0
- microlive/data/icons/icon_micro.png +0 -0
- microlive/data/models/__init__.py +0 -0
- microlive/gui/__init__.py +1 -0
- microlive/gui/app.py +16000 -0
- microlive/gui/main.py +54 -0
- microlive/gui/micro_mac.command +18 -0
- microlive/gui/micro_windows.bat +24 -0
- microlive/imports.py +209 -0
- microlive/microscopy.py +13321 -0
- microlive/ml_spot_detection.py +252 -0
- microlive/pipelines/__init__.py +17 -0
- microlive/pipelines/pipeline_FRAP.py +1225 -0
- microlive/pipelines/pipeline_folding_efficiency.py +297 -0
- microlive/pipelines/pipeline_particle_tracking.py +489 -0
- microlive/pipelines/pipeline_particle_tracking_old.py +153 -0
- microlive/pipelines/pipeline_spot_detection_no_tracking.py +368 -0
- microlive/utils/__init__.py +13 -0
- microlive/utils/device.py +99 -0
- microlive/utils/resources.py +60 -0
- microlive-1.0.2.dist-info/METADATA +267 -0
- microlive-1.0.2.dist-info/RECORD +27 -0
- microlive-1.0.2.dist-info/WHEEL +5 -0
- microlive-1.0.2.dist-info/entry_points.txt +2 -0
- microlive-1.0.2.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
"""Pipeline module for MicroLive.
|
|
2
|
+
|
|
3
|
+
This module is part of the microlive package.
|
|
4
|
+
"""
|
|
5
|
+
from microlive.imports import *
|
|
6
|
+
|
|
7
|
+
def pipeline_particle_tracking(data_folder_path, selected_image, channels_spots, max_spots_for_threshold=100000,
|
|
8
|
+
show_plot=True, channels_cytosol=None, channels_nucleus=None,memory=1,
|
|
9
|
+
min_length_trajectory=5, yx_spot_size_in_px=5, z_spot_size_in_px=2, maximum_spots_cluster=4,cluster_radius_nm =500,
|
|
10
|
+
MINIMAL_SNR=0.5, diameter_cytosol=300, diameter_nucleus=200,
|
|
11
|
+
segmentation_selection_metric='max_area',recalculate_mask=False,optimization_segmentation_method='diameter_segmentation',
|
|
12
|
+
pretrained_model_cyto_segmentation=None,use_watershed=False,list_images_to_process=None,save_3d_visualization=False,
|
|
13
|
+
max_percentage_empty_data_in_trajectory=0.1,particle_detection_threshold=None,save_croparray=False,
|
|
14
|
+
apply_photobleaching_correction=False,photobleaching_mode='inside_cell',use_maximum_projection=False,
|
|
15
|
+
max_lag_for_MSD=30,step_size_in_sec=1,separate_clusters_and_spots=False,maximum_range_search_pixels=10,results_folder_path=None,
|
|
16
|
+
calculate_MSD=True,calculate_correlations=True):
|
|
17
|
+
# Read images and metadata
|
|
18
|
+
# detect if the data is a lif file
|
|
19
|
+
list_images, list_names, pixel_xy_um, voxel_z_um, channel_names, number_color_channels, list_time_intervals, bit_depth = \
|
|
20
|
+
mi.ReadLif(data_folder_path, show_metadata=False, save_tif=False, save_png=False, format='TZYXC').read()
|
|
21
|
+
# Prepare full list of images and set up indices to process
|
|
22
|
+
list_images_complete = list_images.copy()
|
|
23
|
+
if list_images_to_process is not None:
|
|
24
|
+
selected_indices = [i for i in range(len(list_names)) if list_names[i] in list_images_to_process]
|
|
25
|
+
if use_maximum_projection:
|
|
26
|
+
# use the maximum projection in Z. but keep the image shape with only one Z slice
|
|
27
|
+
list_images = [np.max(list_images[i], axis=1, keepdims=True) for i in selected_indices]
|
|
28
|
+
else:
|
|
29
|
+
list_images = [list_images[i] for i in selected_indices]
|
|
30
|
+
else:
|
|
31
|
+
selected_indices = range(len(list_names))
|
|
32
|
+
if use_maximum_projection:
|
|
33
|
+
list_images = [np.max(img, axis=1, keepdims=True) for img in list_images]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# If selected_image is None, process all images
|
|
38
|
+
if selected_image is None:
|
|
39
|
+
list_df, list_masks, list_images_tested, list_diffusion_coefficient = [], [], [], []
|
|
40
|
+
|
|
41
|
+
#for idx in range(len(list_images)):
|
|
42
|
+
for idx in range(len(list_images_complete)):
|
|
43
|
+
if idx not in selected_indices:
|
|
44
|
+
continue
|
|
45
|
+
df, masks,image,diffusion_coefficient = process_single_image(
|
|
46
|
+
data_folder_path=data_folder_path,
|
|
47
|
+
selected_image=idx,
|
|
48
|
+
channels_spots=channels_spots,
|
|
49
|
+
max_spots_for_threshold=max_spots_for_threshold,
|
|
50
|
+
show_plot=show_plot,
|
|
51
|
+
channels_cytosol=channels_cytosol,
|
|
52
|
+
channels_nucleus=channels_nucleus,
|
|
53
|
+
min_length_trajectory=min_length_trajectory,
|
|
54
|
+
yx_spot_size_in_px=yx_spot_size_in_px,
|
|
55
|
+
z_spot_size_in_px = z_spot_size_in_px,
|
|
56
|
+
maximum_spots_cluster=maximum_spots_cluster,
|
|
57
|
+
cluster_radius_nm=cluster_radius_nm,
|
|
58
|
+
MINIMAL_SNR=MINIMAL_SNR,
|
|
59
|
+
diameter_cytosol=diameter_cytosol,
|
|
60
|
+
diameter_nucleus=diameter_nucleus,
|
|
61
|
+
segmentation_selection_metric=segmentation_selection_metric,
|
|
62
|
+
list_images=list_images_complete,
|
|
63
|
+
list_names=list_names,
|
|
64
|
+
pixel_xy_um=pixel_xy_um,
|
|
65
|
+
voxel_z_um=voxel_z_um,
|
|
66
|
+
channel_names=channel_names,
|
|
67
|
+
image_time_interval=list_time_intervals[idx],
|
|
68
|
+
recalculate_mask=recalculate_mask,
|
|
69
|
+
optimization_segmentation_method=optimization_segmentation_method,
|
|
70
|
+
pretrained_model_cyto_segmentation=pretrained_model_cyto_segmentation,
|
|
71
|
+
use_watershed=use_watershed,
|
|
72
|
+
save_3d_visualization=save_3d_visualization,
|
|
73
|
+
apply_photobleaching_correction=apply_photobleaching_correction,
|
|
74
|
+
photobleaching_mode=photobleaching_mode,
|
|
75
|
+
use_maximum_projection=use_maximum_projection,
|
|
76
|
+
max_lag_for_MSD = max_lag_for_MSD,
|
|
77
|
+
step_size_in_sec=step_size_in_sec,
|
|
78
|
+
separate_clusters_and_spots=separate_clusters_and_spots,
|
|
79
|
+
maximum_range_search_pixels=maximum_range_search_pixels,
|
|
80
|
+
max_percentage_empty_data_in_trajectory=max_percentage_empty_data_in_trajectory,
|
|
81
|
+
memory=memory,
|
|
82
|
+
particle_detection_threshold=particle_detection_threshold,
|
|
83
|
+
results_folder_path=results_folder_path,
|
|
84
|
+
calculate_MSD=calculate_MSD,
|
|
85
|
+
calculate_correlations=calculate_correlations,
|
|
86
|
+
save_croparray=save_croparray,
|
|
87
|
+
)
|
|
88
|
+
#if df is None:
|
|
89
|
+
# if the df is None or empty, continue to the next image
|
|
90
|
+
if df.empty:
|
|
91
|
+
continue
|
|
92
|
+
# rename the field image_id to idx
|
|
93
|
+
df['image_id'] = idx
|
|
94
|
+
list_df.append(df)
|
|
95
|
+
list_masks.append(masks)
|
|
96
|
+
list_images_tested.append(image)
|
|
97
|
+
list_diffusion_coefficient.append(diffusion_coefficient)
|
|
98
|
+
|
|
99
|
+
if len(list_df) >1 :
|
|
100
|
+
final_df = pd.concat(list_df, ignore_index=True)
|
|
101
|
+
else:
|
|
102
|
+
final_df = df
|
|
103
|
+
return final_df, list_df, list_masks, list_images_tested, list_diffusion_coefficient
|
|
104
|
+
else:
|
|
105
|
+
# Process single image
|
|
106
|
+
df,masks,image, diffusion_coefficient= process_single_image(
|
|
107
|
+
data_folder_path=data_folder_path,
|
|
108
|
+
selected_image=selected_image,
|
|
109
|
+
channels_spots=channels_spots,
|
|
110
|
+
max_spots_for_threshold=max_spots_for_threshold,
|
|
111
|
+
show_plot=show_plot,
|
|
112
|
+
channels_cytosol=channels_cytosol,
|
|
113
|
+
channels_nucleus=channels_nucleus,
|
|
114
|
+
min_length_trajectory=min_length_trajectory,
|
|
115
|
+
yx_spot_size_in_px=yx_spot_size_in_px,
|
|
116
|
+
z_spot_size_in_px = z_spot_size_in_px,
|
|
117
|
+
maximum_spots_cluster=maximum_spots_cluster,
|
|
118
|
+
cluster_radius_nm=cluster_radius_nm,
|
|
119
|
+
MINIMAL_SNR=MINIMAL_SNR,
|
|
120
|
+
diameter_cytosol=diameter_cytosol,
|
|
121
|
+
diameter_nucleus=diameter_nucleus,
|
|
122
|
+
segmentation_selection_metric=segmentation_selection_metric,
|
|
123
|
+
list_images=list_images,
|
|
124
|
+
list_names=list_names[idx],
|
|
125
|
+
pixel_xy_um=pixel_xy_um,
|
|
126
|
+
voxel_z_um=voxel_z_um,
|
|
127
|
+
channel_names=channel_names,
|
|
128
|
+
image_time_interval = list_time_intervals[selected_image],
|
|
129
|
+
recalculate_mask=recalculate_mask,
|
|
130
|
+
optimization_segmentation_method=optimization_segmentation_method,
|
|
131
|
+
pretrained_model_cyto_segmentation=pretrained_model_cyto_segmentation,
|
|
132
|
+
use_watershed=use_watershed,
|
|
133
|
+
save_3d_visualization=save_3d_visualization,
|
|
134
|
+
apply_photobleaching_correction=apply_photobleaching_correction,
|
|
135
|
+
photobleaching_mode=photobleaching_mode,
|
|
136
|
+
use_maximum_projection=use_maximum_projection,
|
|
137
|
+
max_lag_for_MSD = max_lag_for_MSD,
|
|
138
|
+
step_size_in_sec=step_size_in_sec,
|
|
139
|
+
separate_clusters_and_spots=separate_clusters_and_spots,
|
|
140
|
+
maximum_range_search_pixels=maximum_range_search_pixels,
|
|
141
|
+
max_percentage_empty_data_in_trajectory=max_percentage_empty_data_in_trajectory,
|
|
142
|
+
memory=memory,
|
|
143
|
+
particle_detection_threshold=particle_detection_threshold,
|
|
144
|
+
results_folder_path=results_folder_path,
|
|
145
|
+
calculate_MSD=calculate_MSD,
|
|
146
|
+
calculate_correlations=calculate_correlations,
|
|
147
|
+
save_croparray=save_croparray,
|
|
148
|
+
)
|
|
149
|
+
return df, [df], [masks], [image], [diffusion_coefficient]
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@mi.Utilities().metadata_decorator(metadata_folder_func=mi.Utilities().get_metadata_folder,exclude_args=['list_images',]) # exclude_args=['list_images', 'list_names' ]
|
|
157
|
+
def process_single_image(data_folder_path, selected_image, channels_spots, max_spots_for_threshold=100000,
|
|
158
|
+
show_plot=True, channels_cytosol=None, channels_nucleus=None,memory=1,
|
|
159
|
+
min_length_trajectory=5, yx_spot_size_in_px=5, z_spot_size_in_px=2 , maximum_spots_cluster=4,cluster_radius_nm=500,
|
|
160
|
+
MINIMAL_SNR=0.5, diameter_cytosol=300, diameter_nucleus=200, segmentation_selection_metric='area',
|
|
161
|
+
list_images=None, list_names=None, pixel_xy_um=None, voxel_z_um=None,
|
|
162
|
+
channel_names=None, optimization_segmentation_method='diameter_segmentation',
|
|
163
|
+
recalculate_mask=False,use_watershed=False, pretrained_model_cyto_segmentation=None,particle_detection_threshold=None,save_croparray=False,
|
|
164
|
+
image_time_interval=None,save_3d_visualization=False,apply_photobleaching_correction=False,photobleaching_mode='inside_cell',max_percentage_empty_data_in_trajectory=0.1,
|
|
165
|
+
use_maximum_projection=False,max_lag_for_MSD=30,step_size_in_sec=1,separate_clusters_and_spots=False,maximum_range_search_pixels=10,results_folder_path=None,
|
|
166
|
+
calculate_MSD=True,calculate_correlations=True):
|
|
167
|
+
# Ensure lists are properly formatted
|
|
168
|
+
channels_spots = [channels_spots] if not isinstance(channels_spots, list) else channels_spots
|
|
169
|
+
channels_cytosol = [channels_cytosol] if not isinstance(channels_cytosol, list) else channels_cytosol
|
|
170
|
+
channels_nucleus = [channels_nucleus] if not isinstance(channels_nucleus, list) else channels_nucleus
|
|
171
|
+
|
|
172
|
+
# Convert pixel and voxel sizes to nm
|
|
173
|
+
pixel_xy_nm = int(pixel_xy_um * 1000)
|
|
174
|
+
voxel_z_nm = int(voxel_z_um * 1000)
|
|
175
|
+
list_voxels = [voxel_z_nm, pixel_xy_nm]
|
|
176
|
+
list_spot_size_px = [z_spot_size_in_px, yx_spot_size_in_px]
|
|
177
|
+
# print a line
|
|
178
|
+
print('--------------------------------------------------')
|
|
179
|
+
print(f'Processing image: {list_names[selected_image]}')
|
|
180
|
+
tested_image = list_images[selected_image] # TZYXC
|
|
181
|
+
original_tested_image = tested_image.copy()
|
|
182
|
+
# Creating the results folder
|
|
183
|
+
results_name = 'results_' + data_folder_path.stem + '_cell_id_' + str(selected_image)
|
|
184
|
+
current_dir = pathlib.Path().absolute()
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
if results_folder_path is not None:
|
|
188
|
+
# ensure that results_folder_path is a Path object
|
|
189
|
+
if not isinstance(results_folder_path, pathlib.Path):
|
|
190
|
+
results_folder_path = pathlib.Path(results_folder_path)
|
|
191
|
+
results_folder = results_folder_path.joinpath(results_name)
|
|
192
|
+
else:
|
|
193
|
+
results_folder = current_dir.joinpath('results_live_cell', results_name)
|
|
194
|
+
results_folder.mkdir(parents=True, exist_ok=True)
|
|
195
|
+
mi.Utilities().clear_folder_except_substring(results_folder, 'mask')
|
|
196
|
+
# Plot the original image
|
|
197
|
+
plot_name_original = results_folder.joinpath('original_image.png')
|
|
198
|
+
suptitle=f'Image: {data_folder_path.stem[:16]} - {list_names[selected_image]} - Cell_ID: {selected_image}'
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
mi.Plots().plot_images(
|
|
202
|
+
image_ZYXC=tested_image[0],
|
|
203
|
+
figsize=(12, 5),
|
|
204
|
+
show_plot=show_plot,
|
|
205
|
+
use_maximum_projection=True,
|
|
206
|
+
use_gaussian_filter=True,
|
|
207
|
+
cmap='binary',
|
|
208
|
+
min_max_percentile=[0.5, 99.9],
|
|
209
|
+
show_gird=False,
|
|
210
|
+
save_plots=True,
|
|
211
|
+
plot_name=plot_name_original,
|
|
212
|
+
suptitle=suptitle
|
|
213
|
+
)
|
|
214
|
+
# Read or create masks
|
|
215
|
+
mask_file_name = 'mask_' + data_folder_path.stem + '_image_' + str(selected_image) + '.tif'
|
|
216
|
+
mask_file_path = results_folder.joinpath(mask_file_name)
|
|
217
|
+
path_mask_exist = os.path.exists(str(mask_file_path))
|
|
218
|
+
if path_mask_exist and recalculate_mask is False:
|
|
219
|
+
masks = imread(str(mask_file_path)).astype(bool)
|
|
220
|
+
else:
|
|
221
|
+
# Use Cellpose to create masks
|
|
222
|
+
if use_watershed:
|
|
223
|
+
masks_complete_cells = mi.CellSegmentationWatershed(np.max(tested_image[:,:,:,:,channels_cytosol[0]],
|
|
224
|
+
axis=(0,1)), footprint_size=2, ).apply_watershed()
|
|
225
|
+
else:
|
|
226
|
+
masks_complete_cells, _, _ = mi.CellSegmentation(
|
|
227
|
+
tested_image[0],
|
|
228
|
+
channels_cytosol=channels_cytosol,
|
|
229
|
+
channels_nucleus=channels_nucleus,
|
|
230
|
+
diameter_cytosol=diameter_cytosol,
|
|
231
|
+
diameter_nucleus=diameter_nucleus,
|
|
232
|
+
optimization_segmentation_method=optimization_segmentation_method,
|
|
233
|
+
remove_fragmented_cells=False,
|
|
234
|
+
show_plot=show_plot,
|
|
235
|
+
image_name=None,
|
|
236
|
+
NUMBER_OF_CORES=1,
|
|
237
|
+
selection_metric=segmentation_selection_metric,
|
|
238
|
+
pretrained_model_cyto_segmentation = pretrained_model_cyto_segmentation
|
|
239
|
+
).calculate_masks()
|
|
240
|
+
# Selecting the mask that is in the center of the image
|
|
241
|
+
center_y = masks_complete_cells.shape[0] // 2
|
|
242
|
+
center_x = masks_complete_cells.shape[1] // 2
|
|
243
|
+
selected_mask_id = masks_complete_cells[center_y, center_x]
|
|
244
|
+
if selected_mask_id > 0:
|
|
245
|
+
masks = masks_complete_cells == selected_mask_id
|
|
246
|
+
else:
|
|
247
|
+
# Select the largest mask that is not the background mask (0)
|
|
248
|
+
mask_labels = np.unique(masks_complete_cells)
|
|
249
|
+
mask_sizes = [(label, np.sum(masks_complete_cells == label)) for label in mask_labels if label != 0]
|
|
250
|
+
if mask_sizes:
|
|
251
|
+
selected_mask_id = max(mask_sizes, key=lambda x: x[1])[0]
|
|
252
|
+
masks = masks_complete_cells == selected_mask_id
|
|
253
|
+
else:
|
|
254
|
+
masks = np.zeros_like(masks_complete_cells, dtype=bool)
|
|
255
|
+
# Save the mask
|
|
256
|
+
masks = masks.astype(np.uint8)
|
|
257
|
+
tifffile.imwrite(str(mask_file_path), masks, dtype='uint8')
|
|
258
|
+
|
|
259
|
+
if apply_photobleaching_correction:
|
|
260
|
+
file_path_photobleacing = results_folder.joinpath('photobleaching.png')
|
|
261
|
+
corrected_image = mi.Photobleaching(image_TZYXC=tested_image,mask_YX=masks, show_plot=False, mode= photobleaching_mode,plot_name=file_path_photobleacing).apply_photobleaching_correction() #mi.PhotobleachingCorrection(tested_image).apply_correction()
|
|
262
|
+
|
|
263
|
+
else:
|
|
264
|
+
corrected_image = tested_image
|
|
265
|
+
# Calculate the threshold for spot detection
|
|
266
|
+
plot_name_threshold = results_folder.joinpath('threshold_spot_detection.png')
|
|
267
|
+
|
|
268
|
+
if particle_detection_threshold is None:
|
|
269
|
+
starting_threshold = mi.Utilities().calculate_threshold_for_spot_detection(
|
|
270
|
+
corrected_image, list_spot_size_px, list_voxels, channels_spots,
|
|
271
|
+
max_spots_for_threshold=max_spots_for_threshold,
|
|
272
|
+
show_plot=True,plot_name=plot_name_threshold
|
|
273
|
+
)
|
|
274
|
+
else:
|
|
275
|
+
starting_threshold = [particle_detection_threshold]*len(channels_spots)
|
|
276
|
+
|
|
277
|
+
# Run the particle tracking
|
|
278
|
+
try:
|
|
279
|
+
list_dataframes_trajectories, _ = mi.ParticleTracking(
|
|
280
|
+
image=corrected_image,
|
|
281
|
+
channels_spots=channels_spots,
|
|
282
|
+
masks=masks,
|
|
283
|
+
list_voxels=list_voxels,
|
|
284
|
+
memory=memory,
|
|
285
|
+
channels_cytosol=channels_cytosol,
|
|
286
|
+
channels_nucleus=channels_nucleus,
|
|
287
|
+
min_length_trajectory=min_length_trajectory,
|
|
288
|
+
threshold_for_spot_detection=starting_threshold,
|
|
289
|
+
yx_spot_size_in_px=yx_spot_size_in_px,
|
|
290
|
+
z_spot_size_in_px=z_spot_size_in_px,
|
|
291
|
+
maximum_spots_cluster=maximum_spots_cluster,
|
|
292
|
+
cluster_radius_nm = cluster_radius_nm,
|
|
293
|
+
separate_clusters_and_spots=separate_clusters_and_spots,
|
|
294
|
+
maximum_range_search_pixels=maximum_range_search_pixels,
|
|
295
|
+
).run()
|
|
296
|
+
except Exception as e:
|
|
297
|
+
print(f'Error: {e}')
|
|
298
|
+
return pd.DataFrame(), masks, original_tested_image, None
|
|
299
|
+
#df_tracking = list_dataframes_trajectories[0]
|
|
300
|
+
df_tracking = list_dataframes_trajectories[0]
|
|
301
|
+
|
|
302
|
+
if len(df_tracking)==0:
|
|
303
|
+
return pd.DataFrame(), masks, original_tested_image, None
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
if len(list_dataframes_trajectories) > 1:
|
|
307
|
+
for i in range(1, len(list_dataframes_trajectories)):
|
|
308
|
+
df_tracking = pd.concat([df_tracking, list_dataframes_trajectories[i]], ignore_index=True)
|
|
309
|
+
df_tracking = df_tracking.reset_index(drop=True)
|
|
310
|
+
#print(df_tracking)
|
|
311
|
+
# Plot histograms for the SNR
|
|
312
|
+
selected_field = 'snr' # options are: psf_sigma, snr, 'spot_int'
|
|
313
|
+
plot_name_snr = results_folder.joinpath('spots_' + selected_field + '.png')
|
|
314
|
+
mean_snr = mi.Plots().plot_histograms_from_df(
|
|
315
|
+
df_tracking,
|
|
316
|
+
selected_field=selected_field,
|
|
317
|
+
figsize=(8, 2),
|
|
318
|
+
plot_name=plot_name_snr,
|
|
319
|
+
bin_count=60,
|
|
320
|
+
save_plot=True,
|
|
321
|
+
list_colors=channel_names,
|
|
322
|
+
remove_outliers=True
|
|
323
|
+
)
|
|
324
|
+
# Plot histograms for the spot intensity
|
|
325
|
+
selected_field = 'spot_int'
|
|
326
|
+
plot_name_int = results_folder.joinpath('spots_' + selected_field + '.png')
|
|
327
|
+
mean_int = mi.Plots().plot_histograms_from_df(
|
|
328
|
+
df_tracking,
|
|
329
|
+
selected_field=selected_field,
|
|
330
|
+
figsize=(8, 2),
|
|
331
|
+
plot_name=plot_name_int,
|
|
332
|
+
bin_count=60,
|
|
333
|
+
save_plot=True,
|
|
334
|
+
list_colors=channel_names,
|
|
335
|
+
remove_outliers=True
|
|
336
|
+
)
|
|
337
|
+
# Remove tracks with low SNR in the tracking channel
|
|
338
|
+
if MINIMAL_SNR is not None:
|
|
339
|
+
array_selected_field = mi.Utilities().df_trajectories_to_array(
|
|
340
|
+
dataframe=df_tracking,
|
|
341
|
+
selected_field=selected_field + '_ch_' + str(channels_spots[0]),
|
|
342
|
+
fill_value='nans'
|
|
343
|
+
)
|
|
344
|
+
mean_snr = np.nanmean(array_selected_field, axis=1)
|
|
345
|
+
indices_low_quality_tracks = np.where(mean_snr < MINIMAL_SNR)[0]
|
|
346
|
+
df_tracking = df_tracking[~df_tracking['particle'].isin(indices_low_quality_tracks)]
|
|
347
|
+
df_tracking = df_tracking.reset_index(drop=True)
|
|
348
|
+
df_tracking['particle'] = df_tracking.groupby('particle').ngroup()
|
|
349
|
+
# Plot image intensity histogram
|
|
350
|
+
|
|
351
|
+
masked_data = corrected_image * masks[np.newaxis, np.newaxis, :, :, np.newaxis].astype(float)
|
|
352
|
+
for i in range(len(channels_spots)):
|
|
353
|
+
#plot_name_histogram = results_folder.joinpath('pixel_histogram_in_cell.png')
|
|
354
|
+
plot_name_histogram = results_folder.joinpath('pixel_histogram_in_cell_'+str(channels_spots[i])+'.png')
|
|
355
|
+
mi.Plots().plot_image_pixel_intensity_distribution(
|
|
356
|
+
image=np.mean(masked_data, axis=(0, 1)),
|
|
357
|
+
figsize=(8, 2),
|
|
358
|
+
bins=100,
|
|
359
|
+
remove_outliers=True,
|
|
360
|
+
remove_zeros=True,
|
|
361
|
+
save_plots=True,
|
|
362
|
+
plot_name=plot_name_histogram,
|
|
363
|
+
single_color=None,
|
|
364
|
+
list_colors=channel_names,
|
|
365
|
+
tracking_channel=channels_spots[0],
|
|
366
|
+
threshold_tracking=starting_threshold[i]
|
|
367
|
+
)
|
|
368
|
+
# Plot original image and tracks
|
|
369
|
+
suptitle = f'Image: {data_folder_path.stem[:16]} - {list_names[selected_image]} - Cell_ID: {selected_image}'
|
|
370
|
+
plot_name_original_image_and_tracks = results_folder.joinpath('original_image_tracking.png')
|
|
371
|
+
mi.Plots().plot_images(
|
|
372
|
+
image_ZYXC=corrected_image[0],
|
|
373
|
+
df=df_tracking,
|
|
374
|
+
masks=masks,
|
|
375
|
+
show_trajectories=True,
|
|
376
|
+
suptitle=suptitle,
|
|
377
|
+
figsize=(12, 3),
|
|
378
|
+
show_plot=True,
|
|
379
|
+
selected_time=0,
|
|
380
|
+
use_maximum_projection=True,
|
|
381
|
+
use_gaussian_filter=True,
|
|
382
|
+
cmap='binary',
|
|
383
|
+
min_max_percentile=[0.05, 99.95],
|
|
384
|
+
show_gird=False,
|
|
385
|
+
save_plots=True,
|
|
386
|
+
plot_name=plot_name_original_image_and_tracks
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
# Combine the original image and the image with tracks
|
|
390
|
+
plot_name_complete_image = results_folder.joinpath('complete_image_tracking.png')
|
|
391
|
+
mi.Utilities().combine_images_vertically([plot_name_original, plot_name_original_image_and_tracks], plot_name_complete_image, delete_originals=True)
|
|
392
|
+
|
|
393
|
+
# Save the DataFrame
|
|
394
|
+
df_tracking.to_csv(results_folder.joinpath('tracking_results.csv'), index=False)
|
|
395
|
+
PLOT_FILTERED_IMAGES = True
|
|
396
|
+
normalize_each_particle = True
|
|
397
|
+
crop_size = yx_spot_size_in_px + 5 # 3 pixels for the border
|
|
398
|
+
# add 5 pixels to crop_size, check if the crop_size is odd, if not, add 1
|
|
399
|
+
if crop_size % 2 == 0:
|
|
400
|
+
crop_size += 1
|
|
401
|
+
selected_time_point = None
|
|
402
|
+
#if PLOT_FILTERED_IMAGES:
|
|
403
|
+
filtered_image = mi.Utilities().gaussian_laplace_filter_image(corrected_image, list_spot_size_px, list_voxels)
|
|
404
|
+
croparray_filtered, mean_crop_filtered, first_appearance, crop_size = mi.CropArray(image=filtered_image, df_crops=df_tracking, crop_size=crop_size, remove_outliers=False, max_percentile=99.95,selected_time_point=selected_time_point,normalize_each_particle=normalize_each_particle).run()
|
|
405
|
+
#else:
|
|
406
|
+
# croparray_filtered, mean_crop_filtered, first_appearance, crop_size = mi.CropArray(image=tested_image, df_crops=df_tracking, crop_size=crop_size, remove_outliers=False, max_percentile=99.9,selected_time_point=selected_time_point,normalize_each_particle=normalize_each_particle).run()
|
|
407
|
+
# Plot all crops
|
|
408
|
+
if save_croparray:
|
|
409
|
+
path_crop_array = results_folder.joinpath('crop_array.png')
|
|
410
|
+
mi.Plots().plot_croparray(croparray_filtered, crop_size, save_plots=True,plot_name= path_crop_array,suptitle=None,show_particle_labels=True, cmap='binary_r',max_percentile = 99) # flag_vector=flag_vector
|
|
411
|
+
# plot pair of crops
|
|
412
|
+
plot_name_crops_filter = results_folder.joinpath('crops.png')
|
|
413
|
+
mi.Plots().plot_matrix_pair_crops (mean_crop_filtered, crop_size,save_plots=True,plot_name=plot_name_crops_filter) # flag_vector=flag_vector
|
|
414
|
+
# Calculate the Mean Squared Displacement
|
|
415
|
+
plot_name_MSD = results_folder.joinpath('MSD_plot.png')
|
|
416
|
+
|
|
417
|
+
#max_lag_for_MSD = 30
|
|
418
|
+
if image_time_interval is None:
|
|
419
|
+
image_time_interval = step_size_in_sec
|
|
420
|
+
print(f'Warning: The image_time_interval was not provided. Using the step_size_in_sec as the image_time_interval: {step_size_in_sec} seconds.')
|
|
421
|
+
else:
|
|
422
|
+
image_time_interval = float(image_time_interval)
|
|
423
|
+
# print a warning message indicating that we are using the step_size_in_sec as the image_time_interval
|
|
424
|
+
|
|
425
|
+
if calculate_MSD:
|
|
426
|
+
diffusion_coefficient, em, time_range, model_fit, trackpy_df = mi.ParticleMotion(df_tracking,
|
|
427
|
+
microns_per_pixel=pixel_xy_um,
|
|
428
|
+
step_size_in_sec=image_time_interval,
|
|
429
|
+
max_lagtime=max_lag_for_MSD,
|
|
430
|
+
show_plot=True,
|
|
431
|
+
remove_drift=False,
|
|
432
|
+
plot_name=plot_name_MSD).calculate_msd()
|
|
433
|
+
else:
|
|
434
|
+
diffusion_coefficient = None
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
if calculate_correlations:
|
|
438
|
+
# calculate and plot the autocorrelation
|
|
439
|
+
array_ch0= mi.Utilities().df_trajectories_to_array(dataframe=df_tracking, selected_field='spot_int_ch_0', fill_value='nans')
|
|
440
|
+
|
|
441
|
+
if 'spot_int_ch_1' in df_tracking.columns:
|
|
442
|
+
array_ch1= mi.Utilities().df_trajectories_to_array(dataframe=df_tracking, selected_field='spot_int_ch_1', fill_value='nans')
|
|
443
|
+
intensity_array_ch0_short, intensity_array_ch1_short = mi.Utilities().shift_trajectories(array_ch0, array_ch1,max_percentage_empty_data_in_trajectory=max_percentage_empty_data_in_trajectory)
|
|
444
|
+
else:
|
|
445
|
+
array_ch1 = None
|
|
446
|
+
intensity_array_ch0_short = mi.Utilities().shift_trajectories(array_ch0,max_percentage_empty_data_in_trajectory=max_percentage_empty_data_in_trajectory)
|
|
447
|
+
intensity_array_ch1_short = None
|
|
448
|
+
|
|
449
|
+
plot_name_intensity_matrix = results_folder.joinpath('intensity_matrix.png')
|
|
450
|
+
mi.Plots().plot_matrix_sample_time(intensity_array_ch0_short, intensity_array_ch1_short,plot_name=plot_name_intensity_matrix)
|
|
451
|
+
|
|
452
|
+
plot_name_AC_ch0 = results_folder.joinpath('AC_plot_ch0.png')
|
|
453
|
+
mean_correlation_ch0, std_correlation_ch0, lags_ch0, correlations_array_ch0,dwell_time_ch0 = mi.Correlation(primary_data=intensity_array_ch0_short, max_lag=None,
|
|
454
|
+
nan_handling='ignore',shift_data=True,return_full=False,
|
|
455
|
+
time_interval_between_frames_in_seconds=image_time_interval,
|
|
456
|
+
show_plot=True,start_lag=1,fit_type='exponential',
|
|
457
|
+
use_linear_projection_for_lag_0=True,save_plots=True,plot_name=plot_name_AC_ch0).run()
|
|
458
|
+
if array_ch1 is not None:
|
|
459
|
+
plot_name_AC_ch1 = results_folder.joinpath('AC_plot_ch1.png')
|
|
460
|
+
mean_correlation_ch1, std_correlation_ch1, lags_ch1, correlations_array_ch1,dwell_time_ch1 = mi.Correlation(primary_data=intensity_array_ch1_short, max_lag=None,
|
|
461
|
+
nan_handling='ignore',shift_data=True,return_full=False,
|
|
462
|
+
time_interval_between_frames_in_seconds=image_time_interval,
|
|
463
|
+
show_plot=True,start_lag=1,fit_type='exponential',
|
|
464
|
+
use_linear_projection_for_lag_0=True,save_plots=True,plot_name=plot_name_AC_ch1).run()
|
|
465
|
+
|
|
466
|
+
# Plot cross-correlation
|
|
467
|
+
plot_name_cross_correlation = results_folder.joinpath('cross_correlation.png')
|
|
468
|
+
mean_cross_correlation, std_cross_correlation, lags_cross_correlation, cross_correlations_array, max_lag = mi.Correlation(primary_data=intensity_array_ch0_short, secondary_data=intensity_array_ch1_short,
|
|
469
|
+
max_lag=None, nan_handling='ignore', shift_data=False, return_full=True,
|
|
470
|
+
time_interval_between_frames_in_seconds=image_time_interval,show_plot=True,
|
|
471
|
+
save_plots=True,plot_name=plot_name_cross_correlation).run()
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
# plot napari visualizer
|
|
475
|
+
if save_3d_visualization:
|
|
476
|
+
mask_expanded = masks[np.newaxis, np.newaxis, :, :, np.newaxis]
|
|
477
|
+
masked_image_TZYXC = filtered_image * mask_expanded
|
|
478
|
+
# Apply Gaussian filter to reduce background noise
|
|
479
|
+
#from scipy.ndimage import gaussian_filter
|
|
480
|
+
masked_image_TZYXC = gaussian_filter(masked_image_TZYXC, sigma=1)
|
|
481
|
+
# Remove extreme values from the image
|
|
482
|
+
masked_image_TZYXC = mi.RemoveExtrema(masked_image_TZYXC, min_percentile=0.001, max_percentile=99.995).remove_outliers()
|
|
483
|
+
plot_name_3d_visualizer = str(results_folder.joinpath('image_3d.gif'))
|
|
484
|
+
mi.Plots().Napari_Visualizer(masked_image_TZYXC, df_tracking, z_correction=7, channels_spots=0, plot_name=plot_name_3d_visualizer)
|
|
485
|
+
|
|
486
|
+
# print the process has finished for the selected image
|
|
487
|
+
print(f'Image {list_names[selected_image]} has been processed.')
|
|
488
|
+
|
|
489
|
+
return df_tracking, masks, original_tested_image, diffusion_coefficient
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Pipeline module for MicroLive.
|
|
2
|
+
|
|
3
|
+
This module is part of the microlive package.
|
|
4
|
+
"""
|
|
5
|
+
from microlive.imports import *
|
|
6
|
+
|
|
7
|
+
def metadata_decorator(metadata_folder_func=None, metadata_filename=None):
|
|
8
|
+
def decorator(func):
|
|
9
|
+
@wraps(func)
|
|
10
|
+
def wrapper(*args, **kwargs):
|
|
11
|
+
# Capture function arguments
|
|
12
|
+
sig = inspect.signature(func)
|
|
13
|
+
bound_args = sig.bind(*args, **kwargs)
|
|
14
|
+
bound_args.apply_defaults()
|
|
15
|
+
# Build metadata dictionary
|
|
16
|
+
metadata = {}
|
|
17
|
+
# Add Date and Time
|
|
18
|
+
metadata["Date and Time"] = pd.Timestamp.now().round('min')
|
|
19
|
+
# Add computer user name
|
|
20
|
+
metadata["computer_user_name"] = getpass.getuser()
|
|
21
|
+
# Add function arguments
|
|
22
|
+
for name, value in bound_args.arguments.items():
|
|
23
|
+
metadata[name] = value
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
# Call the original function
|
|
27
|
+
result = func(*args, **kwargs)
|
|
28
|
+
#metadata["Function Result"] = str(result)
|
|
29
|
+
except Exception as e:
|
|
30
|
+
# Capture exception details
|
|
31
|
+
metadata["Exception"] = str(e)
|
|
32
|
+
metadata["Traceback"] = traceback.format_exc()
|
|
33
|
+
raise # Re-raise the exception after logging
|
|
34
|
+
finally:
|
|
35
|
+
# Determine metadata folder path
|
|
36
|
+
if metadata_folder_func is not None:
|
|
37
|
+
metadata_folder = metadata_folder_func(*args, **kwargs)
|
|
38
|
+
else:
|
|
39
|
+
metadata_folder = 'temp_metadata_folder' # default folder
|
|
40
|
+
|
|
41
|
+
# Create metadata folder if it doesn't exist
|
|
42
|
+
metadata_folder_path = Path(metadata_folder)
|
|
43
|
+
metadata_folder_path.mkdir(parents=True, exist_ok=True)
|
|
44
|
+
|
|
45
|
+
# Customize metadata file name
|
|
46
|
+
if metadata_filename:
|
|
47
|
+
metadata_file = f"{metadata_filename}.txt"
|
|
48
|
+
else:
|
|
49
|
+
metadata_file = f"{func.__name__}_metadata.txt"
|
|
50
|
+
metadata_file_path = metadata_folder_path / metadata_file
|
|
51
|
+
|
|
52
|
+
# Write metadata to text file
|
|
53
|
+
with open(metadata_file_path, 'w') as f:
|
|
54
|
+
for key, value in metadata.items():
|
|
55
|
+
f.write(f"{key}: {value}\n")
|
|
56
|
+
|
|
57
|
+
return result
|
|
58
|
+
return wrapper
|
|
59
|
+
return decorator
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_metadata_folder(*args, **kwargs):
|
|
63
|
+
# Extract data_folder_path and selected_image from args or kwargs
|
|
64
|
+
sig = inspect.signature(pipeline_particle_tracking)
|
|
65
|
+
bound_args = sig.bind(*args, **kwargs)
|
|
66
|
+
bound_args.apply_defaults()
|
|
67
|
+
data_folder_path = Path(bound_args.arguments['data_folder_path'])
|
|
68
|
+
selected_image = bound_args.arguments['selected_image']
|
|
69
|
+
results_name = 'results_' + data_folder_path.stem + '_cell_id_' + str(selected_image)
|
|
70
|
+
current_dir = Path().absolute()
|
|
71
|
+
results_folder = current_dir.joinpath('results_live_cell', results_name)
|
|
72
|
+
return results_folder
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
#@metadata_decorator(metadata_folder)
|
|
76
|
+
@metadata_decorator(metadata_folder_func=get_metadata_folder)
|
|
77
|
+
def pipeline_particle_tracking(data_folder_path, selected_image, channels_spots, max_spots_for_threshold = 100000, show_plot = True, channels_cytosol = None, channels_nucleus = None, min_length_trajectory = 5, yx_spot_size_in_px = 3, maximum_spots_cluster = 4, MINIMAL_SNR = 0.5,diameter_cytosol = 300, diameter_nucleus = 200,segmentation_selection_metric = 'area'):
|
|
78
|
+
# if channels_spots is not a list make it a list.
|
|
79
|
+
channels_spots = [channels_spots] if not isinstance(channels_spots, list) else channels_spots
|
|
80
|
+
# if channels_cytosol is not a list make it a list.
|
|
81
|
+
channels_cytosol = [channels_cytosol] if not isinstance(channels_cytosol, list) else channels_cytosol
|
|
82
|
+
# if channels_nucleus is not a list make it a list.
|
|
83
|
+
channels_nucleus = [channels_nucleus] if not isinstance(channels_nucleus, list) else channels_nucleus
|
|
84
|
+
list_images, list_names, pixel_xy_um, voxel_z_um, channel_names, number_color_channels,list_time_intervals, bit_depth = mi.ReadLif(data_folder_path,show_metadata=False,save_tif=False,save_png=False,format='TZYXC').read()
|
|
85
|
+
# Converting the pixel and voxel sizes to nm
|
|
86
|
+
pixel_xy_nm = int(pixel_xy_um*1000)
|
|
87
|
+
voxel_z_nm = int(voxel_z_um*1000)
|
|
88
|
+
list_voxels = [voxel_z_nm , pixel_xy_nm] # , [voxel_z_nm , pixel_xy_nm] ]
|
|
89
|
+
list_psfs = [voxel_z_nm ,pixel_xy_nm] #, [voxel_z_nm , pixel_xy_nm] ]
|
|
90
|
+
|
|
91
|
+
# Selecting the image to be analyzed
|
|
92
|
+
tested_image =list_images[selected_image] # TZYXC
|
|
93
|
+
# Creating the results folder
|
|
94
|
+
results_name = 'results_'+data_folder_path.stem + '_cell_id_'+str(selected_image)
|
|
95
|
+
current_dir = pathlib.Path().absolute()
|
|
96
|
+
results_folder = current_dir.joinpath('results_live_cell',results_name)
|
|
97
|
+
results_folder.mkdir(parents=True, exist_ok=True)
|
|
98
|
+
mi.Utilities().clear_folder_except_substring(results_folder, 'mask')
|
|
99
|
+
# Plot the original image
|
|
100
|
+
plot_name = results_folder.joinpath('original_image.png')
|
|
101
|
+
mi.Plots().plot_images(image_ZYXC=tested_image[0],figsize=(12, 5), show_plot=show_plot, use_maximum_projection=True, use_gaussian_filter=True,cmap='binary',min_max_percentile=[0.5,99.9],show_gird=False,save_plots=True,plot_name=plot_name)
|
|
102
|
+
|
|
103
|
+
# Read the tif files containing the masks as numpy arrays
|
|
104
|
+
mask_file_name = 'mask_'+data_folder_path.stem+'_image_'+str(selected_image)+'.tif'
|
|
105
|
+
if os.path.exists(str(results_folder.joinpath(mask_file_name))):
|
|
106
|
+
masks = imread(str(results_folder.joinpath(mask_file_name))).astype(bool)
|
|
107
|
+
else: # use cellpose to create the masks
|
|
108
|
+
masks_complete_cells, masks_nuclei, masks_cytosol_no_nuclei = mi.CellSegmentation(tested_image[0], channels_cytosol = channels_cytosol, channels_nucleus= channels_nucleus, diameter_cytosol = diameter_cytosol, diameter_nucleus = diameter_nucleus, optimization_segmentation_method='diameter_segmentation', remove_fragmented_cells=False, show_plot= show_plot, image_name = None,NUMBER_OF_CORES=1,selection_metric=segmentation_selection_metric).calculate_masks()
|
|
109
|
+
# Selecting the mask that is in the center of the image
|
|
110
|
+
selected_mask_id = masks_complete_cells[masks_complete_cells.shape[0] // 2, masks_complete_cells.shape[1] // 2]
|
|
111
|
+
if selected_mask_id > 0:
|
|
112
|
+
masks = masks_complete_cells == selected_mask_id
|
|
113
|
+
else:
|
|
114
|
+
# select the largest mask that is not the background mask (0).
|
|
115
|
+
mask_sizes = [np.sum(mask) for mask in masks_complete_cells]
|
|
116
|
+
selected_mask_id = np.argmax(mask_sizes[1:]) + 1
|
|
117
|
+
masks = masks_complete_cells == selected_mask_id
|
|
118
|
+
# Save the mask
|
|
119
|
+
masks = masks.astype(np.uint8)
|
|
120
|
+
tifffile.imwrite(str(results_folder.joinpath(mask_file_name)), masks,dtype='uint8',)
|
|
121
|
+
|
|
122
|
+
# Calculate the threshold for spot detection
|
|
123
|
+
starting_threshold = mi.Utilities().calculate_threshold_for_spot_detection(tested_image,list_psfs,list_voxels,channels_spots, max_spots_for_threshold = max_spots_for_threshold, show_plot=show_plot)
|
|
124
|
+
# Run the particle tracking
|
|
125
|
+
list_dataframes_trajectories, _ = mi.ParticleTracking (image=tested_image,channels_spots=channels_spots, masks=masks, list_voxels=list_voxels,list_psfs=list_psfs, channels_cytosol=channels_cytosol,channels_nucleus=channels_nucleus,min_length_trajectory=min_length_trajectory,threshold_for_spot_detection=starting_threshold,yx_spot_size_in_px=yx_spot_size_in_px,maximum_spots_cluster=maximum_spots_cluster).run()
|
|
126
|
+
df_tracking= list_dataframes_trajectories[0]
|
|
127
|
+
threshold_tracking = starting_threshold
|
|
128
|
+
filtered_image = mi.Utilities().gaussian_laplace_filter_image(tested_image,list_psfs,list_voxels)
|
|
129
|
+
# Plot histigrams for the SNR
|
|
130
|
+
selected_field = 'snr' # options are: psf_sigma, snr, 'spot_int'
|
|
131
|
+
plot_name_snr = results_folder.joinpath('spots_'+selected_field+'.png')
|
|
132
|
+
mean_snr = mi.Plots().plot_histograms_from_df(df_tracking, selected_field=selected_field,figsize=(8,2), plot_name=plot_name_snr, bin_count=60, save_plot=True, list_colors= channel_names,remove_outliers=True)
|
|
133
|
+
# Plotting histograms for the spot intensity
|
|
134
|
+
selected_field = 'spot_int' # options are: psf_sigma, snr, 'spot_int'
|
|
135
|
+
plot_name_int = results_folder.joinpath('spots_'+selected_field+'.png')
|
|
136
|
+
mean_snr = mi.Plots().plot_histograms_from_df(df_tracking, selected_field=plot_name_int,figsize=(8,2), plot_name=plot_name_snr, bin_count=60, save_plot=True, list_colors= channel_names,remove_outliers=True)
|
|
137
|
+
# Remove tracks with low SNR in the tracking channel
|
|
138
|
+
if MINIMAL_SNR is not None:
|
|
139
|
+
# filtering the tracks based on the SNR on a selected channel [channels_spots]
|
|
140
|
+
array_selected_field= mi.Utilities().df_trajectories_to_array(dataframe=df_tracking, selected_field=selected_field+'_ch_'+str(channels_spots[0]), fill_value='nans')
|
|
141
|
+
mean_snr = np.nanmean(array_selected_field, axis=1)
|
|
142
|
+
indices_low_quality_tracks = np.where(mean_snr < MINIMAL_SNR)[0]
|
|
143
|
+
df_tracking = df_tracking[~df_tracking['particle'].isin(indices_low_quality_tracks)]
|
|
144
|
+
df_tracking = df_tracking.reset_index(drop=True)
|
|
145
|
+
df_tracking['particle'] = df_tracking.groupby('particle').ngroup()
|
|
146
|
+
# plot image intensity histogram
|
|
147
|
+
plot_name_histogram = results_folder.joinpath('pixel_histogram_in_cell.png')
|
|
148
|
+
masked_data = tested_image * masks[np.newaxis, np.newaxis, :, :, np.newaxis].astype(float)
|
|
149
|
+
list_median_intensity = mi.Plots().plot_image_pixel_intensity_distribution(image=np.mean(masked_data[:,:,:,:,:],axis=0),figsize=(8, 2),bins=100,remove_outliers=True,remove_zeros=True,save_plots=True, plot_name=plot_name_histogram ,single_color =None,list_colors=channel_names,tracking_channel = channels_spots[0],threshold_tracking=threshold_tracking)
|
|
150
|
+
suptitle = 'Image: ' + data_folder_path.stem[:16]+'- '+list_names[selected_image] +' - Cell_ID: '+ str(selected_image)
|
|
151
|
+
plot_name_original_image_and_tracks = results_folder.joinpath('original_image_tracking.png')
|
|
152
|
+
mi.Plots().plot_images(image_ZYXC=tested_image[0], df=df_tracking, masks=masks, show_trajectories=True, suptitle=suptitle,figsize=(12, 3), show_plot=True,selected_time=0, use_maximum_projection=True, use_gaussian_filter=True,cmap='binary',min_max_percentile=[0.05,99.95],show_gird=False,save_plots=True,plot_name=plot_name_original_image_and_tracks)
|
|
153
|
+
return df_tracking
|