celldetective 1.4.2__py3-none-any.whl → 1.5.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. celldetective/__init__.py +25 -0
  2. celldetective/__main__.py +62 -43
  3. celldetective/_version.py +1 -1
  4. celldetective/extra_properties.py +477 -399
  5. celldetective/filters.py +192 -97
  6. celldetective/gui/InitWindow.py +541 -411
  7. celldetective/gui/__init__.py +0 -15
  8. celldetective/gui/about.py +44 -39
  9. celldetective/gui/analyze_block.py +120 -84
  10. celldetective/gui/base/__init__.py +0 -0
  11. celldetective/gui/base/channel_norm_generator.py +335 -0
  12. celldetective/gui/base/components.py +249 -0
  13. celldetective/gui/base/feature_choice.py +92 -0
  14. celldetective/gui/base/figure_canvas.py +52 -0
  15. celldetective/gui/base/list_widget.py +133 -0
  16. celldetective/gui/{styles.py → base/styles.py} +92 -36
  17. celldetective/gui/base/utils.py +33 -0
  18. celldetective/gui/base_annotator.py +900 -767
  19. celldetective/gui/classifier_widget.py +6 -22
  20. celldetective/gui/configure_new_exp.py +777 -671
  21. celldetective/gui/control_panel.py +635 -524
  22. celldetective/gui/dynamic_progress.py +449 -0
  23. celldetective/gui/event_annotator.py +2023 -1662
  24. celldetective/gui/generic_signal_plot.py +1292 -944
  25. celldetective/gui/gui_utils.py +899 -1289
  26. celldetective/gui/interactions_block.py +658 -0
  27. celldetective/gui/interactive_timeseries_viewer.py +447 -0
  28. celldetective/gui/json_readers.py +48 -15
  29. celldetective/gui/layouts/__init__.py +5 -0
  30. celldetective/gui/layouts/background_model_free_layout.py +537 -0
  31. celldetective/gui/layouts/channel_offset_layout.py +134 -0
  32. celldetective/gui/layouts/local_correction_layout.py +91 -0
  33. celldetective/gui/layouts/model_fit_layout.py +372 -0
  34. celldetective/gui/layouts/operation_layout.py +68 -0
  35. celldetective/gui/layouts/protocol_designer_layout.py +96 -0
  36. celldetective/gui/pair_event_annotator.py +3130 -2435
  37. celldetective/gui/plot_measurements.py +586 -267
  38. celldetective/gui/plot_signals_ui.py +724 -506
  39. celldetective/gui/preprocessing_block.py +395 -0
  40. celldetective/gui/process_block.py +1678 -1831
  41. celldetective/gui/seg_model_loader.py +580 -473
  42. celldetective/gui/settings/__init__.py +0 -7
  43. celldetective/gui/settings/_cellpose_model_params.py +181 -0
  44. celldetective/gui/settings/_event_detection_model_params.py +95 -0
  45. celldetective/gui/settings/_segmentation_model_params.py +159 -0
  46. celldetective/gui/settings/_settings_base.py +77 -65
  47. celldetective/gui/settings/_settings_event_model_training.py +752 -526
  48. celldetective/gui/settings/_settings_measurements.py +1133 -964
  49. celldetective/gui/settings/_settings_neighborhood.py +574 -488
  50. celldetective/gui/settings/_settings_segmentation_model_training.py +779 -564
  51. celldetective/gui/settings/_settings_signal_annotator.py +329 -305
  52. celldetective/gui/settings/_settings_tracking.py +1304 -1094
  53. celldetective/gui/settings/_stardist_model_params.py +98 -0
  54. celldetective/gui/survival_ui.py +422 -312
  55. celldetective/gui/tableUI.py +1665 -1701
  56. celldetective/gui/table_ops/_maths.py +295 -0
  57. celldetective/gui/table_ops/_merge_groups.py +140 -0
  58. celldetective/gui/table_ops/_merge_one_hot.py +95 -0
  59. celldetective/gui/table_ops/_query_table.py +43 -0
  60. celldetective/gui/table_ops/_rename_col.py +44 -0
  61. celldetective/gui/thresholds_gui.py +382 -179
  62. celldetective/gui/viewers/__init__.py +0 -0
  63. celldetective/gui/viewers/base_viewer.py +700 -0
  64. celldetective/gui/viewers/channel_offset_viewer.py +331 -0
  65. celldetective/gui/viewers/contour_viewer.py +394 -0
  66. celldetective/gui/viewers/size_viewer.py +153 -0
  67. celldetective/gui/viewers/spot_detection_viewer.py +341 -0
  68. celldetective/gui/viewers/threshold_viewer.py +309 -0
  69. celldetective/gui/workers.py +403 -126
  70. celldetective/log_manager.py +92 -0
  71. celldetective/measure.py +1895 -1478
  72. celldetective/napari/__init__.py +0 -0
  73. celldetective/napari/utils.py +1025 -0
  74. celldetective/neighborhood.py +1914 -1448
  75. celldetective/preprocessing.py +1620 -1220
  76. celldetective/processes/__init__.py +0 -0
  77. celldetective/processes/background_correction.py +271 -0
  78. celldetective/processes/compute_neighborhood.py +894 -0
  79. celldetective/processes/detect_events.py +246 -0
  80. celldetective/processes/downloader.py +137 -0
  81. celldetective/processes/measure_cells.py +565 -0
  82. celldetective/processes/segment_cells.py +760 -0
  83. celldetective/processes/track_cells.py +435 -0
  84. celldetective/processes/train_segmentation_model.py +694 -0
  85. celldetective/processes/train_signal_model.py +265 -0
  86. celldetective/processes/unified_process.py +292 -0
  87. celldetective/regionprops/_regionprops.py +358 -317
  88. celldetective/relative_measurements.py +987 -710
  89. celldetective/scripts/measure_cells.py +313 -212
  90. celldetective/scripts/measure_relative.py +90 -46
  91. celldetective/scripts/segment_cells.py +165 -104
  92. celldetective/scripts/segment_cells_thresholds.py +96 -68
  93. celldetective/scripts/track_cells.py +198 -149
  94. celldetective/scripts/train_segmentation_model.py +324 -201
  95. celldetective/scripts/train_signal_model.py +87 -45
  96. celldetective/segmentation.py +844 -749
  97. celldetective/signals.py +3514 -2861
  98. celldetective/tracking.py +30 -15
  99. celldetective/utils/__init__.py +0 -0
  100. celldetective/utils/cellpose_utils/__init__.py +133 -0
  101. celldetective/utils/color_mappings.py +42 -0
  102. celldetective/utils/data_cleaning.py +630 -0
  103. celldetective/utils/data_loaders.py +450 -0
  104. celldetective/utils/dataset_helpers.py +207 -0
  105. celldetective/utils/downloaders.py +235 -0
  106. celldetective/utils/event_detection/__init__.py +8 -0
  107. celldetective/utils/experiment.py +1782 -0
  108. celldetective/utils/image_augmenters.py +308 -0
  109. celldetective/utils/image_cleaning.py +74 -0
  110. celldetective/utils/image_loaders.py +926 -0
  111. celldetective/utils/image_transforms.py +335 -0
  112. celldetective/utils/io.py +62 -0
  113. celldetective/utils/mask_cleaning.py +348 -0
  114. celldetective/utils/mask_transforms.py +5 -0
  115. celldetective/utils/masks.py +184 -0
  116. celldetective/utils/maths.py +351 -0
  117. celldetective/utils/model_getters.py +325 -0
  118. celldetective/utils/model_loaders.py +296 -0
  119. celldetective/utils/normalization.py +380 -0
  120. celldetective/utils/parsing.py +465 -0
  121. celldetective/utils/plots/__init__.py +0 -0
  122. celldetective/utils/plots/regression.py +53 -0
  123. celldetective/utils/resources.py +34 -0
  124. celldetective/utils/stardist_utils/__init__.py +104 -0
  125. celldetective/utils/stats.py +90 -0
  126. celldetective/utils/types.py +21 -0
  127. {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/METADATA +1 -1
  128. celldetective-1.5.0b1.dist-info/RECORD +187 -0
  129. {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/WHEEL +1 -1
  130. tests/gui/test_new_project.py +129 -117
  131. tests/gui/test_project.py +127 -79
  132. tests/test_filters.py +39 -15
  133. tests/test_notebooks.py +8 -0
  134. tests/test_tracking.py +232 -13
  135. tests/test_utils.py +123 -77
  136. celldetective/gui/base_components.py +0 -23
  137. celldetective/gui/layouts.py +0 -1602
  138. celldetective/gui/processes/compute_neighborhood.py +0 -594
  139. celldetective/gui/processes/downloader.py +0 -111
  140. celldetective/gui/processes/measure_cells.py +0 -360
  141. celldetective/gui/processes/segment_cells.py +0 -499
  142. celldetective/gui/processes/track_cells.py +0 -303
  143. celldetective/gui/processes/train_segmentation_model.py +0 -270
  144. celldetective/gui/processes/train_signal_model.py +0 -108
  145. celldetective/gui/table_ops/merge_groups.py +0 -118
  146. celldetective/gui/viewers.py +0 -1354
  147. celldetective/io.py +0 -3663
  148. celldetective/utils.py +0 -3108
  149. celldetective-1.4.2.dist-info/RECORD +0 -123
  150. {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/entry_points.txt +0 -0
  151. {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/licenses/LICENSE +0 -0
  152. {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/top_level.txt +0 -0
@@ -5,122 +5,154 @@ Copright © 2022 Laboratoire Adhesion et Inflammation, Authored by Remy Torro.
5
5
  import argparse
6
6
  import os
7
7
  import json
8
- from celldetective.io import auto_load_number_of_frames, load_frames, extract_position_name
8
+ from celldetective.utils.image_loaders import (
9
+ auto_load_number_of_frames,
10
+ load_frames,
11
+ _get_img_num_per_channel,
12
+ )
13
+ from celldetective.utils.experiment import (
14
+ extract_position_name,
15
+ extract_experiment_channels,
16
+ )
9
17
  from celldetective.segmentation import segment_frame_from_thresholds
10
- from celldetective.utils import _extract_channel_indices_from_config, config_section_to_dict, _extract_nbr_channels_from_config, _get_img_num_per_channel, extract_experiment_channels
18
+ from celldetective.utils.parsing import (
19
+ config_section_to_dict,
20
+ _extract_channel_indices_from_config,
21
+ _extract_nbr_channels_from_config,
22
+ )
11
23
  from pathlib import Path, PurePath
12
24
  from glob import glob
13
25
  from shutil import rmtree
14
26
  from tqdm import tqdm
15
27
  import numpy as np
16
- from csbdeep.io import save_tiff_imagej_compatible
28
+ from celldetective.utils.io import save_tiff_imagej_compatible
17
29
  import gc
18
30
  from art import tprint
19
31
  import concurrent.futures
20
32
 
21
33
  tprint("Segment")
22
34
 
23
- parser = argparse.ArgumentParser(description="Segment a movie in position with a threshold pipeline",
24
- formatter_class=argparse.ArgumentDefaultsHelpFormatter)
25
- parser.add_argument('-p',"--position", required=True, help="Path to the position")
26
- parser.add_argument('-c',"--config", required=True,help="Threshold instructions")
27
- parser.add_argument("--mode", default="target", choices=["target","effector","targets","effectors"],help="Cell population of interest")
28
- parser.add_argument("--threads", default="1",help="Number of parallel threads")
35
+ parser = argparse.ArgumentParser(
36
+ description="Segment a movie in position with a threshold pipeline",
37
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
38
+ )
39
+ parser.add_argument("-p", "--position", required=True, help="Path to the position")
40
+ parser.add_argument("-c", "--config", required=True, help="Threshold instructions")
41
+ parser.add_argument(
42
+ "--mode",
43
+ default="target",
44
+ choices=["target", "effector", "targets", "effectors"],
45
+ help="Cell population of interest",
46
+ )
47
+ parser.add_argument("--threads", default="1", help="Number of parallel threads")
29
48
 
30
49
  args = parser.parse_args()
31
50
  process_arguments = vars(args)
32
- pos = str(process_arguments['position'])
33
- mode = str(process_arguments['mode'])
34
- n_threads = int(process_arguments['threads'])
51
+ pos = str(process_arguments["position"])
52
+ mode = str(process_arguments["mode"])
53
+ n_threads = int(process_arguments["threads"])
35
54
 
36
- threshold_instructions = str(process_arguments['config'])
55
+ threshold_instructions = str(process_arguments["config"])
37
56
  equalize = False
38
57
 
39
58
  if os.path.exists(threshold_instructions):
40
- with open(threshold_instructions, 'r') as f:
41
- threshold_instructions = json.load(f)
42
- required_channels = [threshold_instructions['target_channel']]
43
- if 'equalize_reference' in threshold_instructions:
44
- equalize_info = threshold_instructions['equalize_reference']
45
- equalize = equalize_info[0]
46
- equalize_time = equalize_info[1]
59
+ with open(threshold_instructions, "r") as f:
60
+ threshold_instructions = json.load(f)
61
+ required_channels = [threshold_instructions["target_channel"]]
62
+ if "equalize_reference" in threshold_instructions:
63
+ equalize_info = threshold_instructions["equalize_reference"]
64
+ equalize = equalize_info[0]
65
+ equalize_time = equalize_info[1]
47
66
 
48
67
  else:
49
- print('The configuration path is not valid. Abort.')
50
- os.abort()
68
+ print("The configuration path is not valid. Abort.")
69
+ os.abort()
51
70
 
52
- if mode.lower()=="target" or mode.lower()=="targets":
53
- label_folder = "labels_targets"
54
- elif mode.lower()=="effector" or mode.lower()=="effectors":
55
- label_folder = "labels_effectors"
71
+ if mode.lower() == "target" or mode.lower() == "targets":
72
+ label_folder = "labels_targets"
73
+ elif mode.lower() == "effector" or mode.lower() == "effectors":
74
+ label_folder = "labels_effectors"
56
75
 
57
76
  # Locate experiment config
58
77
  parent1 = Path(pos).parent
59
78
  expfolder = parent1.parent
60
- config = PurePath(expfolder,Path("config.ini"))
61
- assert os.path.exists(config),'The configuration file for the experiment could not be located. Abort.'
79
+ config = PurePath(expfolder, Path("config.ini"))
80
+ assert os.path.exists(
81
+ config
82
+ ), "The configuration file for the experiment could not be located. Abort."
62
83
 
63
84
  print(f"Position: {extract_position_name(pos)}...")
64
- print("Configuration file: ",config)
85
+ print("Configuration file: ", config)
65
86
  print(f"Population: {mode}...")
66
87
 
67
88
  channel_indices = _extract_channel_indices_from_config(config, required_channels)
68
89
  # need to abort if channel not found
69
- print(f'Required channels: {required_channels} located at channel indices {channel_indices}...')
90
+ print(
91
+ f"Required channels: {required_channels} located at channel indices {channel_indices}..."
92
+ )
70
93
 
71
- threshold_instructions.update({'target_channel': channel_indices[0]})
94
+ threshold_instructions.update({"target_channel": channel_indices[0]})
72
95
 
73
96
  movie_prefix = config_section_to_dict(config, "MovieSettings")["movie_prefix"]
74
97
  len_movie = float(config_section_to_dict(config, "MovieSettings")["len_movie"])
75
98
  channel_names, channel_indices = extract_experiment_channels(expfolder)
76
- threshold_instructions.update({'channel_names': channel_names})
99
+ threshold_instructions.update({"channel_names": channel_names})
77
100
 
78
101
  # Try to find the file
79
102
  try:
80
- file = glob(pos+f"movie/{movie_prefix}*.tif")[0]
103
+ file = glob(pos + f"movie/{movie_prefix}*.tif")[0]
81
104
  except IndexError:
82
- print('Movie could not be found. Check the prefix.')
83
- os.abort()
105
+ print("Movie could not be found. Check the prefix.")
106
+ os.abort()
84
107
 
85
108
  len_movie_auto = auto_load_number_of_frames(file)
86
109
  if len_movie_auto is not None:
87
- len_movie = len_movie_auto
110
+ len_movie = len_movie_auto
88
111
 
89
112
  nbr_channels = _extract_nbr_channels_from_config(config)
90
- #print(f'Number of channels in the input movie: {nbr_channels}')
91
- img_num_channels = _get_img_num_per_channel(np.arange(nbr_channels), len_movie, nbr_channels)
113
+ # print(f'Number of channels in the input movie: {nbr_channels}')
114
+ img_num_channels = _get_img_num_per_channel(
115
+ np.arange(nbr_channels), len_movie, nbr_channels
116
+ )
92
117
 
93
118
  # If everything OK, prepare output, load models
94
- if os.path.exists(os.sep.join([pos,label_folder])):
95
- print('Erasing the previous labels folder...')
96
- rmtree(os.sep.join([pos,label_folder]))
97
- os.mkdir(os.sep.join([pos,label_folder]))
98
- print(f'Labels folder successfully generated...')
119
+ if os.path.exists(os.sep.join([pos, label_folder])):
120
+ print("Erasing the previous labels folder...")
121
+ rmtree(os.sep.join([pos, label_folder]))
122
+ os.mkdir(os.sep.join([pos, label_folder]))
123
+ print(f"Labels folder successfully generated...")
99
124
 
100
125
  if equalize:
101
- f_reference = load_frames(img_num_channels[:,equalize_time], file, scale=None, normalize_input=False)
102
- f_reference = f_reference[:,:,threshold_instructions['target_channel']]
126
+ f_reference = load_frames(
127
+ img_num_channels[:, equalize_time], file, scale=None, normalize_input=False
128
+ )
129
+ f_reference = f_reference[:, :, threshold_instructions["target_channel"]]
103
130
  else:
104
- f_reference = None
131
+ f_reference = None
105
132
 
106
- threshold_instructions.update({'equalize_reference': f_reference})
133
+ threshold_instructions.update({"equalize_reference": f_reference})
107
134
  print(f"Instructions: {threshold_instructions}...")
108
135
 
136
+
109
137
  # Loop over all frames and segment
110
138
  def segment_index(indices):
111
139
 
112
- for t in tqdm(indices,desc="frame"):
113
-
114
- # Load channels at time t
115
- f = load_frames(img_num_channels[:,t], file, scale=None, normalize_input=False)
116
- mask = segment_frame_from_thresholds(f, **threshold_instructions)
117
- save_tiff_imagej_compatible(os.sep.join([pos, label_folder, f"{str(t).zfill(4)}.tif"]), mask.astype(np.uint16), axes='YX')
140
+ for t in tqdm(indices, desc="frame"):
141
+
142
+ # Load channels at time t
143
+ f = load_frames(img_num_channels[:, t], file, scale=None, normalize_input=False)
144
+ mask = segment_frame_from_thresholds(f, **threshold_instructions)
145
+ save_tiff_imagej_compatible(
146
+ os.sep.join([pos, label_folder, f"{str(t).zfill(4)}.tif"]),
147
+ mask.astype(np.uint16),
148
+ axes="YX",
149
+ )
118
150
 
119
- del f;
120
- del mask;
121
- gc.collect()
151
+ del f
152
+ del mask
153
+ gc.collect()
122
154
 
123
- return
155
+ return
124
156
 
125
157
 
126
158
  print(f"Starting the segmentation with {n_threads} thread(s)...")
@@ -130,17 +162,13 @@ indices = list(range(img_num_channels.shape[1]))
130
162
  chunks = np.array_split(indices, n_threads)
131
163
 
132
164
  with concurrent.futures.ThreadPoolExecutor() as executor:
133
- results = executor.map(segment_index, chunks)
134
- try:
135
- for i,return_value in enumerate(results):
136
- print(f"Thread {i} output check: ",return_value)
137
- except Exception as e:
138
- print("Exception: ", e)
165
+ results = executor.map(segment_index, chunks)
166
+ try:
167
+ for i, return_value in enumerate(results):
168
+ print(f"Thread {i} output check: ", return_value)
169
+ except Exception as e:
170
+ print("Exception: ", e)
139
171
 
140
- print('Done.')
172
+ print("Done.")
141
173
 
142
174
  gc.collect()
143
-
144
-
145
-
146
-