microlive 1.0.11__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.
@@ -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