spacr 0.2.21__tar.gz → 0.2.32__tar.gz

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 (83) hide show
  1. {spacr-0.2.21/spacr.egg-info → spacr-0.2.32}/PKG-INFO +1 -1
  2. {spacr-0.2.21 → spacr-0.2.32}/setup.py +1 -1
  3. {spacr-0.2.21 → spacr-0.2.32}/spacr/app_annotate.py +3 -4
  4. {spacr-0.2.21 → spacr-0.2.32}/spacr/core.py +58 -229
  5. {spacr-0.2.21 → spacr-0.2.32}/spacr/gui_core.py +83 -36
  6. {spacr-0.2.21 → spacr-0.2.32}/spacr/gui_elements.py +414 -63
  7. {spacr-0.2.21 → spacr-0.2.32}/spacr/gui_utils.py +58 -32
  8. {spacr-0.2.21 → spacr-0.2.32}/spacr/io.py +121 -37
  9. {spacr-0.2.21 → spacr-0.2.32}/spacr/measure.py +6 -8
  10. spacr-0.2.32/spacr/resources/icons/measure.png +0 -0
  11. spacr-0.2.32/spacr/resources/icons/ml_analyze.png +0 -0
  12. spacr-0.2.32/spacr/resources/icons/recruitment.png +0 -0
  13. spacr-0.2.32/spacr/resources/icons/spacr_logo_rotation.gif +0 -0
  14. spacr-0.2.32/spacr/resources/icons/train_cellpose.png +0 -0
  15. {spacr-0.2.21 → spacr-0.2.32}/spacr/settings.py +1 -4
  16. {spacr-0.2.21 → spacr-0.2.32}/spacr/utils.py +55 -0
  17. {spacr-0.2.21 → spacr-0.2.32/spacr.egg-info}/PKG-INFO +1 -1
  18. {spacr-0.2.21 → spacr-0.2.32}/spacr.egg-info/SOURCES.txt +2 -0
  19. spacr-0.2.21/spacr/resources/icons/measure.png +0 -0
  20. spacr-0.2.21/spacr/resources/icons/recruitment.png +0 -0
  21. spacr-0.2.21/spacr/resources/icons/train_cellpose.png +0 -0
  22. {spacr-0.2.21 → spacr-0.2.32}/LICENSE +0 -0
  23. {spacr-0.2.21 → spacr-0.2.32}/MANIFEST.in +0 -0
  24. {spacr-0.2.21 → spacr-0.2.32}/README.rst +0 -0
  25. {spacr-0.2.21 → spacr-0.2.32}/setup.cfg +0 -0
  26. {spacr-0.2.21 → spacr-0.2.32}/spacr/__init__.py +0 -0
  27. {spacr-0.2.21 → spacr-0.2.32}/spacr/__main__.py +0 -0
  28. {spacr-0.2.21 → spacr-0.2.32}/spacr/app_classify.py +0 -0
  29. {spacr-0.2.21 → spacr-0.2.32}/spacr/app_make_masks.py +0 -0
  30. {spacr-0.2.21 → spacr-0.2.32}/spacr/app_mask.py +0 -0
  31. {spacr-0.2.21 → spacr-0.2.32}/spacr/app_measure.py +0 -0
  32. {spacr-0.2.21 → spacr-0.2.32}/spacr/app_sequencing.py +0 -0
  33. {spacr-0.2.21 → spacr-0.2.32}/spacr/app_umap.py +0 -0
  34. {spacr-0.2.21 → spacr-0.2.32}/spacr/chris.py +0 -0
  35. {spacr-0.2.21 → spacr-0.2.32}/spacr/deep_spacr.py +0 -0
  36. {spacr-0.2.21 → spacr-0.2.32}/spacr/graph_learning.py +0 -0
  37. {spacr-0.2.21 → spacr-0.2.32}/spacr/gui.py +0 -0
  38. {spacr-0.2.21 → spacr-0.2.32}/spacr/logger.py +0 -0
  39. {spacr-0.2.21 → spacr-0.2.32}/spacr/plot.py +0 -0
  40. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/abort.png +0 -0
  41. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/annotate.png +0 -0
  42. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/cellpose_all.png +0 -0
  43. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/cellpose_masks.png +0 -0
  44. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/classify.png +0 -0
  45. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/default.png +0 -0
  46. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/download.png +0 -0
  47. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/logo_spacr.png +0 -0
  48. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/make_masks.png +0 -0
  49. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/map_barcodes.png +0 -0
  50. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/mask.png +0 -0
  51. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/regression.png +0 -0
  52. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/run.png +0 -0
  53. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/sequencing.png +0 -0
  54. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/settings.png +0 -0
  55. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/icons/umap.png +0 -0
  56. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model +0 -0
  57. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model_settings.csv +0 -0
  58. {spacr-0.2.21 → spacr-0.2.32}/spacr/resources/models/cp/toxo_pv_lumen.CP_model +0 -0
  59. {spacr-0.2.21 → spacr-0.2.32}/spacr/sequencing.py +0 -0
  60. {spacr-0.2.21 → spacr-0.2.32}/spacr/sim.py +0 -0
  61. {spacr-0.2.21 → spacr-0.2.32}/spacr/sim_app.py +0 -0
  62. {spacr-0.2.21 → spacr-0.2.32}/spacr/timelapse.py +0 -0
  63. {spacr-0.2.21 → spacr-0.2.32}/spacr/version.py +0 -0
  64. {spacr-0.2.21 → spacr-0.2.32}/spacr.egg-info/dependency_links.txt +0 -0
  65. {spacr-0.2.21 → spacr-0.2.32}/spacr.egg-info/entry_points.txt +0 -0
  66. {spacr-0.2.21 → spacr-0.2.32}/spacr.egg-info/requires.txt +0 -0
  67. {spacr-0.2.21 → spacr-0.2.32}/spacr.egg-info/top_level.txt +0 -0
  68. {spacr-0.2.21 → spacr-0.2.32}/tests/test_annotate_app.py +0 -0
  69. {spacr-0.2.21 → spacr-0.2.32}/tests/test_core.py +0 -0
  70. {spacr-0.2.21 → spacr-0.2.32}/tests/test_gui_classify_app.py +0 -0
  71. {spacr-0.2.21 → spacr-0.2.32}/tests/test_gui_mask_app.py +0 -0
  72. {spacr-0.2.21 → spacr-0.2.32}/tests/test_gui_measure_app.py +0 -0
  73. {spacr-0.2.21 → spacr-0.2.32}/tests/test_gui_sim_app.py +0 -0
  74. {spacr-0.2.21 → spacr-0.2.32}/tests/test_gui_utils.py +0 -0
  75. {spacr-0.2.21 → spacr-0.2.32}/tests/test_io.py +0 -0
  76. {spacr-0.2.21 → spacr-0.2.32}/tests/test_mask_app.py +0 -0
  77. {spacr-0.2.21 → spacr-0.2.32}/tests/test_measure.py +0 -0
  78. {spacr-0.2.21 → spacr-0.2.32}/tests/test_plot.py +0 -0
  79. {spacr-0.2.21 → spacr-0.2.32}/tests/test_sim.py +0 -0
  80. {spacr-0.2.21 → spacr-0.2.32}/tests/test_timelapse.py +0 -0
  81. {spacr-0.2.21 → spacr-0.2.32}/tests/test_train.py +0 -0
  82. {spacr-0.2.21 → spacr-0.2.32}/tests/test_umap.py +0 -0
  83. {spacr-0.2.21 → spacr-0.2.32}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spacr
3
- Version: 0.2.21
3
+ Version: 0.2.32
4
4
  Summary: Spatial phenotype analysis of crisp screens (SpaCr)
5
5
  Home-page: https://github.com/EinarOlafsson/spacr
6
6
  Author: Einar Birnir Olafsson
@@ -50,7 +50,7 @@ dependencies = [
50
50
 
51
51
  setup(
52
52
  name="spacr",
53
- version="0.2.21",
53
+ version="0.2.32",
54
54
  author="Einar Birnir Olafsson",
55
55
  author_email="olafsson@med.umich.com",
56
56
  description="Spatial phenotype analysis of crisp screens (SpaCr)",
@@ -1,7 +1,7 @@
1
1
  import tkinter as tk
2
2
  from tkinter import ttk
3
3
  from .gui import MainApp
4
- from .gui_elements import set_dark_style
4
+ from .gui_elements import set_dark_style, spacrButton
5
5
 
6
6
  def initiate_annotation_app(parent_frame):
7
7
  from .gui_utils import generate_annotate_fields, annotate_app
@@ -20,8 +20,6 @@ def initiate_annotation_app(parent_frame):
20
20
  settings['img_size'] = list(map(int, settings['img_size'].split(','))) # Convert string to list of integers
21
21
  settings['percentiles'] = list(map(int, settings['percentiles'].split(','))) # Convert string to list of integers
22
22
  settings['normalize'] = settings['normalize'].lower() == 'true'
23
- settings['rows'] = int(settings['rows'])
24
- settings['columns'] = int(settings['columns'])
25
23
 
26
24
  try:
27
25
  settings['measurement'] = settings['measurement'].split(',') if settings['measurement'] else None
@@ -40,9 +38,10 @@ def initiate_annotation_app(parent_frame):
40
38
  settings[key] = None
41
39
 
42
40
  settings_window.destroy()
41
+
43
42
  annotate_app(parent_frame, settings)
44
43
 
45
- start_button = tk.Button(settings_window, text="Start Annotation", command=start_annotation_app, bg=style_out['bg_color'], fg=style_out['bg_color'])
44
+ start_button = spacrButton(settings_window, text="annotate", command=start_annotation_app, show_text=False)
46
45
  start_button.pack(pady=10)
47
46
 
48
47
  def start_annotate_app():
@@ -974,7 +974,7 @@ def generate_dataset(src, file_metadata=None, experiment='TSG101_screen', sample
974
974
  def apply_model_to_tar(tar_path, model_path, file_type='cell_png', image_size=224, batch_size=64, normalize=True, preload='images', n_jobs=10, threshold=0.5, verbose=False):
975
975
 
976
976
  from .io import TarImageDataset
977
- from .utils import process_vision_results
977
+ from .utils import process_vision_results, print_progress
978
978
 
979
979
  device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
980
980
  if normalize:
@@ -1015,15 +1015,26 @@ def apply_model_to_tar(tar_path, model_path, file_type='cell_png', image_size=22
1015
1015
 
1016
1016
  prediction_pos_probs = []
1017
1017
  filenames_list = []
1018
+ time_ls = []
1018
1019
  gc.collect()
1019
1020
  with torch.no_grad():
1020
1021
  for batch_idx, (batch_images, filenames) in enumerate(data_loader, start=1):
1022
+ start = time.time()
1021
1023
  images = batch_images.to(torch.float).to(device)
1022
1024
  outputs = model(images)
1023
1025
  batch_prediction_pos_prob = torch.sigmoid(outputs).cpu().numpy()
1024
1026
  prediction_pos_probs.extend(batch_prediction_pos_prob.tolist())
1025
1027
  filenames_list.extend(filenames)
1026
- print(f'batch: {batch_idx}/{len(data_loader)}', end='\r', flush=True)
1028
+ stop = time.time()
1029
+ duration = stop - start
1030
+ time_ls.append(duration)
1031
+ files_processed = batch_idx*batch_size
1032
+ files_to_process = len(data_loader)
1033
+ print_progress(files_processed, files_to_process, n_jobs=n_jobs, time_ls=time_ls, batch_size=batch_size, operation_type="Tar dataset")
1034
+
1035
+
1036
+
1037
+
1027
1038
 
1028
1039
  data = {'path':filenames_list, 'pred':prediction_pos_probs}
1029
1040
  df = pd.DataFrame(data, index=None)
@@ -1037,6 +1048,7 @@ def apply_model_to_tar(tar_path, model_path, file_type='cell_png', image_size=22
1037
1048
  def apply_model(src, model_path, image_size=224, batch_size=64, normalize=True, n_jobs=10):
1038
1049
 
1039
1050
  from .io import NoClassDataset
1051
+ from .utils import print_progress
1040
1052
 
1041
1053
  device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
1042
1054
 
@@ -1065,14 +1077,22 @@ def apply_model(src, model_path, image_size=224, batch_size=64, normalize=True,
1065
1077
  model = model.to(device)
1066
1078
  prediction_pos_probs = []
1067
1079
  filenames_list = []
1080
+ time_ls = []
1068
1081
  with torch.no_grad():
1069
1082
  for batch_idx, (batch_images, filenames) in enumerate(data_loader, start=1):
1083
+ start = time.time()
1070
1084
  images = batch_images.to(torch.float).to(device)
1071
1085
  outputs = model(images)
1072
1086
  batch_prediction_pos_prob = torch.sigmoid(outputs).cpu().numpy()
1073
1087
  prediction_pos_probs.extend(batch_prediction_pos_prob.tolist())
1074
1088
  filenames_list.extend(filenames)
1075
- print(f'\rbatch: {batch_idx}/{len(data_loader)}', end='\r', flush=True)
1089
+ stop = time.time()
1090
+ duration = stop - start
1091
+ time_ls.append(duration)
1092
+ files_processed = batch_idx*batch_size
1093
+ files_to_process = len(data_loader)
1094
+ print_progress(files_processed, files_to_process, n_jobs=n_jobs, time_ls=time_ls, batch_size=batch_size, operation_type="Generating predictions")
1095
+
1076
1096
  data = {'path':filenames_list, 'pred':prediction_pos_probs}
1077
1097
  df = pd.DataFrame(data, index=None)
1078
1098
  df.to_csv(result_loc, index=True, header=True, mode='w')
@@ -1164,12 +1184,14 @@ def training_dataset_from_annotation(db_path, dst, annotation_column='test', ann
1164
1184
  return class_paths
1165
1185
 
1166
1186
  def generate_dataset_from_lists(dst, class_data, classes, test_split=0.1):
1187
+ from .utils import print_progress
1167
1188
  # Make sure that the length of class_data matches the length of classes
1168
1189
  if len(class_data) != len(classes):
1169
1190
  raise ValueError("class_data and classes must have the same length.")
1170
1191
 
1171
1192
  total_files = sum(len(data) for data in class_data)
1172
1193
  processed_files = 0
1194
+ time_ls = []
1173
1195
 
1174
1196
  for cls, data in zip(classes, class_data):
1175
1197
  # Create directories
@@ -1183,15 +1205,21 @@ def generate_dataset_from_lists(dst, class_data, classes, test_split=0.1):
1183
1205
 
1184
1206
  # Copy train files
1185
1207
  for path in train_data:
1208
+ start = time.time()
1186
1209
  shutil.copy(path, os.path.join(train_class_dir, os.path.basename(path)))
1187
1210
  processed_files += 1
1188
- print(f'{processed_files}/{total_files}', end='\r', flush=True)
1211
+ duration = time.time() - start
1212
+ time_ls.append(duration)
1213
+ print_progress(processed_files, total_files, n_jobs=1, time_ls=None, batch_size=None, operation_type="Copying files for Train dataset")
1189
1214
 
1190
1215
  # Copy test files
1191
1216
  for path in test_data:
1217
+ start = time.time()
1192
1218
  shutil.copy(path, os.path.join(test_class_dir, os.path.basename(path)))
1193
1219
  processed_files += 1
1194
- print(f'{processed_files}/{total_files}', end='\r', flush=True)
1220
+ duration = time.time() - start
1221
+ time_ls.append(duration)
1222
+ print_progress(processed_files, total_files, n_jobs=1, time_ls=None, batch_size=None, operation_type="Copying files for Test dataset")
1195
1223
 
1196
1224
  # Print summary
1197
1225
  for cls in classes:
@@ -1788,16 +1816,13 @@ def preprocess_generate_masks(src, settings={}):
1788
1816
  def identify_masks_finetune(settings):
1789
1817
 
1790
1818
  from .plot import print_mask_and_flows
1791
- from .utils import get_files_from_dir, resize_images_and_labels
1819
+ from .utils import get_files_from_dir, resize_images_and_labels, print_progress
1792
1820
  from .io import _load_normalized_images_and_labels, _load_images_and_labels
1793
1821
  from .settings import get_identify_masks_finetune_default_settings
1794
1822
 
1795
1823
  settings = get_identify_masks_finetune_default_settings(settings)
1796
-
1797
- #User defined settings
1798
1824
  src=settings['src']
1799
1825
  dst=settings['dst']
1800
-
1801
1826
  model_name=settings['model_name']
1802
1827
  custom_model=settings['custom_model']
1803
1828
  channels = settings['channels']
@@ -1903,8 +1928,12 @@ def identify_masks_finetune(settings):
1903
1928
  stop = time.time()
1904
1929
  duration = (stop - start)
1905
1930
  time_ls.append(duration)
1906
- average_time = np.mean(time_ls) if len(time_ls) > 0 else 0
1907
- print(f'Processing {file_index+1}/{len(images)} images : Time/image {average_time:.3f} sec', end='\r', flush=True)
1931
+ files_processed = len(images)
1932
+ files_to_process = file_index+1
1933
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls)
1934
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="")
1935
+
1936
+
1908
1937
  if verbose:
1909
1938
  if resize:
1910
1939
  stack = resizescikit(stack, dims, preserve_range=True, anti_aliasing=False).astype(stack.dtype)
@@ -1917,212 +1946,6 @@ def identify_masks_finetune(settings):
1917
1946
  gc.collect()
1918
1947
  return
1919
1948
 
1920
- def identify_masks(src, object_type, model_name, batch_size, channels, diameter, minimum_size, maximum_size, filter_intensity, flow_threshold=30, cellprob_threshold=1, figuresize=25, cmap='inferno', refine_masks=True, filter_size=True, filter_dimm=True, remove_border_objects=False, verbose=False, plot=False, merge=False, save=True, start_at=0, file_type='.npz', net_avg=True, resample=True, timelapse=False, timelapse_displacement=None, timelapse_frame_limits=None, timelapse_memory=3, timelapse_remove_transient=False, timelapse_mode='btrack', timelapse_objects='cell'):
1921
- """
1922
- Identify masks from the source images.
1923
-
1924
- Args:
1925
- src (str): Path to the source images.
1926
- object_type (str): Type of object to identify.
1927
- model_name (str): Name of the model to use for identification.
1928
- batch_size (int): Number of images to process in each batch.
1929
- channels (list): List of channel names.
1930
- diameter (float): Diameter of the objects to identify.
1931
- minimum_size (int): Minimum size of objects to keep.
1932
- maximum_size (int): Maximum size of objects to keep.
1933
- flow_threshold (int, optional): Threshold for flow detection. Defaults to 30.
1934
- cellprob_threshold (int, optional): Threshold for cell probability. Defaults to 1.
1935
- figuresize (int, optional): Size of the figure. Defaults to 25.
1936
- cmap (str, optional): Colormap for plotting. Defaults to 'inferno'.
1937
- refine_masks (bool, optional): Flag indicating whether to refine masks. Defaults to True.
1938
- filter_size (bool, optional): Flag indicating whether to filter based on size. Defaults to True.
1939
- filter_dimm (bool, optional): Flag indicating whether to filter based on intensity. Defaults to True.
1940
- remove_border_objects (bool, optional): Flag indicating whether to remove border objects. Defaults to False.
1941
- verbose (bool, optional): Flag indicating whether to display verbose output. Defaults to False.
1942
- plot (bool, optional): Flag indicating whether to plot the masks. Defaults to False.
1943
- merge (bool, optional): Flag indicating whether to merge adjacent objects. Defaults to False.
1944
- save (bool, optional): Flag indicating whether to save the masks. Defaults to True.
1945
- start_at (int, optional): Index to start processing from. Defaults to 0.
1946
- file_type (str, optional): File type for saving the masks. Defaults to '.npz'.
1947
- net_avg (bool, optional): Flag indicating whether to use network averaging. Defaults to True.
1948
- resample (bool, optional): Flag indicating whether to resample the images. Defaults to True.
1949
- timelapse (bool, optional): Flag indicating whether to generate a timelapse. Defaults to False.
1950
- timelapse_displacement (float, optional): Displacement threshold for timelapse. Defaults to None.
1951
- timelapse_frame_limits (tuple, optional): Frame limits for timelapse. Defaults to None.
1952
- timelapse_memory (int, optional): Memory for timelapse. Defaults to 3.
1953
- timelapse_remove_transient (bool, optional): Flag indicating whether to remove transient objects in timelapse. Defaults to False.
1954
- timelapse_mode (str, optional): Mode for timelapse. Defaults to 'btrack'.
1955
- timelapse_objects (str, optional): Objects to track in timelapse. Defaults to 'cell'.
1956
-
1957
- Returns:
1958
- None
1959
- """
1960
-
1961
- from .utils import _masks_to_masks_stack, _filter_cp_masks, _get_cellpose_batch_size
1962
- from .io import _create_database, _save_object_counts_to_database, _check_masks, _get_avg_object_size
1963
- from .timelapse import _npz_to_movie, _btrack_track_cells, _trackpy_track_cells
1964
- from .plot import plot_masks
1965
-
1966
- #Note add logic that handles batches of size 1 as these will break the code batches must all be > 2 images
1967
- gc.collect()
1968
-
1969
- if not torch.cuda.is_available():
1970
- print(f'Torch CUDA is not available, using CPU')
1971
-
1972
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
1973
- model = cp_models.Cellpose(gpu=True, model_type=model_name, device=device)
1974
-
1975
- if file_type == '.npz':
1976
- paths = [os.path.join(src, file) for file in os.listdir(src) if file.endswith('.npz')]
1977
- else:
1978
- paths = [os.path.join(src, file) for file in os.listdir(src) if file.endswith('.png')]
1979
- if timelapse:
1980
- print(f'timelaps is only compatible with npz files')
1981
- return
1982
-
1983
- chans = [2, 1] if model_name == 'cyto2' else [0,0] if model_name == 'nucleus' else [2,0] if model_name == 'cyto' else [2, 0]
1984
-
1985
- if verbose == True:
1986
- print(f'source: {src}')
1987
- print()
1988
- print(f'Settings: object_type: {object_type}, minimum_size: {minimum_size}, maximum_size:{maximum_size}, figuresize:{figuresize}, cmap:{cmap}, , net_avg:{net_avg}, resample:{resample}')
1989
- print()
1990
- print(f'Cellpose settings: Model: {model_name}, batch_size: {batch_size}, channels: {channels}, cellpose_chans: {chans}, diameter:{diameter}, flow_threshold:{flow_threshold}, cellprob_threshold:{cellprob_threshold}')
1991
- print()
1992
- print(f'Bool Settings: verbose:{verbose}, plot:{plot}, merge:{merge}, save:{save}, start_at:{start_at}, file_type:{file_type}, timelapse:{timelapse}')
1993
- print()
1994
-
1995
- count_loc = os.path.dirname(src)+'/measurements/measurements.db'
1996
- os.makedirs(os.path.dirname(src)+'/measurements', exist_ok=True)
1997
- _create_database(count_loc)
1998
-
1999
- average_sizes = []
2000
- time_ls = []
2001
- for file_index, path in enumerate(paths):
2002
-
2003
- name = os.path.basename(path)
2004
- name, ext = os.path.splitext(name)
2005
- if file_type == '.npz':
2006
- if start_at:
2007
- print(f'starting at file index:{start_at}')
2008
- if file_index < start_at:
2009
- continue
2010
- output_folder = os.path.join(os.path.dirname(path), object_type+'_mask_stack')
2011
- os.makedirs(output_folder, exist_ok=True)
2012
- overall_average_size = 0
2013
- with np.load(path) as data:
2014
- stack = data['data']
2015
- filenames = data['filenames']
2016
- if timelapse:
2017
- if len(stack) != batch_size:
2018
- print(f'Changed batch_size:{batch_size} to {len(stack)}, data length:{len(stack)}')
2019
- batch_size = len(stack)
2020
- if isinstance(timelapse_frame_limits, list):
2021
- if len(timelapse_frame_limits) >= 2:
2022
- stack = stack[timelapse_frame_limits[0]: timelapse_frame_limits[1], :, :, :].astype(stack.dtype)
2023
- filenames = filenames[timelapse_frame_limits[0]: timelapse_frame_limits[1]]
2024
- batch_size = len(stack)
2025
- print(f'Cut batch an indecies: {timelapse_frame_limits}, New batch_size: {batch_size} ')
2026
-
2027
- for i in range(0, stack.shape[0], batch_size):
2028
- mask_stack = []
2029
- start = time.time()
2030
-
2031
- if stack.shape[3] == 1:
2032
- batch = stack[i: i+batch_size, :, :, [0,0]].astype(stack.dtype)
2033
- else:
2034
- batch = stack[i: i+batch_size, :, :, channels].astype(stack.dtype)
2035
-
2036
- batch_filenames = filenames[i: i+batch_size].tolist()
2037
-
2038
- if not plot:
2039
- batch, batch_filenames = _check_masks(batch, batch_filenames, output_folder)
2040
- if batch.size == 0:
2041
- print(f'Processing: {file_index}/{len(paths)}: Images/N100pz {batch.shape[0]}')
2042
- #print(f'Processing {file_index}/{len(paths)}: Images/N100pz {batch.shape[0]}', end='\r', flush=True)
2043
- continue
2044
- if batch.max() > 1:
2045
- batch = batch / batch.max()
2046
-
2047
- if timelapse:
2048
- stitch_threshold=100.0
2049
- movie_path = os.path.join(os.path.dirname(src), 'movies')
2050
- os.makedirs(movie_path, exist_ok=True)
2051
- save_path = os.path.join(movie_path, f'timelapse_{object_type}_{name}.mp4')
2052
- _npz_to_movie(batch, batch_filenames, save_path, fps=2)
2053
- else:
2054
- stitch_threshold=0.0
2055
-
2056
- cellpose_batch_size = _get_cellpose_batch_size()
2057
-
2058
- masks, flows, _, _ = model.eval(x=batch,
2059
- batch_size=cellpose_batch_size,
2060
- normalize=False,
2061
- channels=chans,
2062
- channel_axis=3,
2063
- diameter=diameter,
2064
- flow_threshold=flow_threshold,
2065
- cellprob_threshold=cellprob_threshold,
2066
- rescale=None,
2067
- resample=resample,
2068
- stitch_threshold=stitch_threshold,
2069
- progress=None)
2070
-
2071
- print('Masks shape',masks.shape)
2072
- if timelapse:
2073
- _save_object_counts_to_database(masks, object_type, batch_filenames, count_loc, added_string='_timelapse')
2074
- if object_type in timelapse_objects:
2075
- if timelapse_mode == 'btrack':
2076
- if not timelapse_displacement is None:
2077
- radius = timelapse_displacement
2078
- else:
2079
- radius = 100
2080
-
2081
- n_jobs = os.cpu_count()-2
2082
- if n_jobs < 1:
2083
- n_jobs = 1
2084
-
2085
- mask_stack = _btrack_track_cells(src, name, batch_filenames, object_type, plot, save, masks_3D=masks, mode=timelapse_mode, timelapse_remove_transient=timelapse_remove_transient, radius=radius, n_jobs=n_jobs)
2086
- if timelapse_mode == 'trackpy':
2087
- mask_stack = _trackpy_track_cells(src, name, batch_filenames, object_type, masks, timelapse_displacement, timelapse_memory, timelapse_remove_transient, plot, save, timelapse_mode)
2088
-
2089
- else:
2090
- mask_stack = _masks_to_masks_stack(masks)
2091
-
2092
- else:
2093
- _save_object_counts_to_database(masks, object_type, batch_filenames, count_loc, added_string='_before_filtration')
2094
- mask_stack = _filter_cp_masks(masks, flows, filter_size, filter_intensity, minimum_size, maximum_size, remove_border_objects, merge, batch, plot, figuresize)
2095
- _save_object_counts_to_database(mask_stack, object_type, batch_filenames, count_loc, added_string='_after_filtration')
2096
-
2097
- if not np.any(mask_stack):
2098
- average_obj_size = 0
2099
- else:
2100
- average_obj_size = _get_avg_object_size(mask_stack)
2101
-
2102
- average_sizes.append(average_obj_size)
2103
- overall_average_size = np.mean(average_sizes) if len(average_sizes) > 0 else 0
2104
-
2105
- stop = time.time()
2106
- duration = (stop - start)
2107
- time_ls.append(duration)
2108
- average_time = np.mean(time_ls) if len(time_ls) > 0 else 0
2109
- time_in_min = average_time/60
2110
- time_per_mask = average_time/batch_size
2111
- print(f'Processing: {len(paths)} files with {batch_size} imgs: {(file_index+1)*(batch_size+1)}/{(len(paths))*(batch_size+1)}: Time/batch {time_in_min:.3f} min: Time/mask {time_per_mask:.3f}sec: {object_type} size: {overall_average_size:.3f} px2')
2112
- #print(f'Processing {len(paths)} files with {batch_size} imgs: {(file_index+1)*(batch_size+1)}/{(len(paths))*(batch_size+1)}: Time/batch {time_in_min:.3f} min: Time/mask {time_per_mask:.3f}sec: {object_type} size: {overall_average_size:.3f} px2', end='\r', flush=True)
2113
- if not timelapse:
2114
- if plot:
2115
- plot_masks(batch, mask_stack, flows, figuresize=figuresize, cmap=cmap, nr=batch_size, file_type='.npz')
2116
- if save:
2117
- if file_type == '.npz':
2118
- for mask_index, mask in enumerate(mask_stack):
2119
- output_filename = os.path.join(output_folder, batch_filenames[mask_index])
2120
- np.save(output_filename, mask)
2121
- mask_stack = []
2122
- batch_filenames = []
2123
- gc.collect()
2124
- return
2125
-
2126
1949
  def all_elements_match(list1, list2):
2127
1950
  # Check if all elements in list1 are in list2
2128
1951
  return all(element in list2 for element in list1)
@@ -2141,7 +1964,7 @@ def prepare_batch_for_cellpose(batch):
2141
1964
 
2142
1965
  def generate_cellpose_masks(src, settings, object_type):
2143
1966
 
2144
- from .utils import _masks_to_masks_stack, _filter_cp_masks, _get_cellpose_batch_size, _get_cellpose_channels, _choose_model, mask_object_count
1967
+ from .utils import _masks_to_masks_stack, _filter_cp_masks, _get_cellpose_batch_size, _get_cellpose_channels, _choose_model, mask_object_count, print_progress
2145
1968
  from .io import _create_database, _save_object_counts_to_database, _check_masks, _get_avg_object_size
2146
1969
  from .timelapse import _npz_to_movie, _btrack_track_cells, _trackpy_track_cells
2147
1970
  from .plot import plot_masks
@@ -2233,7 +2056,8 @@ def generate_cellpose_masks(src, settings, object_type):
2233
2056
  filenames = filenames[timelapse_frame_limits[0]: timelapse_frame_limits[1]]
2234
2057
  batch_size = len(stack)
2235
2058
  print(f'Cut batch at indecies: {timelapse_frame_limits}, New batch_size: {batch_size} ')
2236
-
2059
+
2060
+ files_processed = 0
2237
2061
  for i in range(0, stack.shape[0], batch_size):
2238
2062
  mask_stack = []
2239
2063
  start = time.time()
@@ -2379,13 +2203,15 @@ def generate_cellpose_masks(src, settings, object_type):
2379
2203
  average_sizes.append(average_obj_size)
2380
2204
  overall_average_size = np.mean(average_sizes) if len(average_sizes) > 0 else 0
2381
2205
 
2382
- stop = time.time()
2383
- duration = (stop - start)
2384
- time_ls.append(duration)
2385
- average_time = np.mean(time_ls) if len(time_ls) > 0 else 0
2386
- time_in_min = average_time/60
2387
- time_per_mask = average_time/batch_size
2388
- print(f'Processing {len(paths)} files with {batch_size} imgs: {(file_index+1)*(batch_size+1)}/{(len(paths))*(batch_size+1)}: Time/batch {time_in_min:.3f} min: Time/mask {time_per_mask:.3f}sec: {object_type} size: {overall_average_size:.3f} px2')
2206
+ stop = time.time()
2207
+ duration = (stop - start)
2208
+ time_ls.append(duration)
2209
+ files_processed += len(batch_filenames)
2210
+ #files_processed = (file_index+1)*(batch_size+1)
2211
+ files_to_process = (len(paths))*(batch_size)
2212
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type=f'{object_type}_mask_gen')
2213
+ print(f'object_size:{object_type}): {overall_average_size:.3f} px2')
2214
+
2389
2215
  if not timelapse:
2390
2216
  if settings['plot']:
2391
2217
  plot_masks(batch, mask_stack, flows, figuresize=figuresize, cmap='inferno', nr=batch_size)
@@ -2403,7 +2229,7 @@ def generate_cellpose_masks(src, settings, object_type):
2403
2229
  def generate_masks_from_imgs(src, model, model_name, batch_size, diameter, cellprob_threshold, flow_threshold, grayscale, save, normalize, channels, percentiles, circular, invert, plot, resize, target_height, target_width, remove_background, background, Signal_to_noise, verbose):
2404
2230
 
2405
2231
  from .io import _load_images_and_labels, _load_normalized_images_and_labels
2406
- from .utils import resize_images_and_labels, resizescikit
2232
+ from .utils import resize_images_and_labels, resizescikit, print_progress
2407
2233
  from .plot import print_mask_and_flows
2408
2234
 
2409
2235
  dst = os.path.join(src, model_name)
@@ -2462,8 +2288,11 @@ def generate_masks_from_imgs(src, model, model_name, batch_size, diameter, cellp
2462
2288
  stop = time.time()
2463
2289
  duration = (stop - start)
2464
2290
  time_ls.append(duration)
2465
- average_time = np.mean(time_ls) if len(time_ls) > 0 else 0
2466
- print(f'Processing {file_index+1}/{len(images)} images : Time/image {average_time:.3f} sec', end='\r', flush=True)
2291
+ files_processed = file_index+1
2292
+ files_to_process = len(images)
2293
+
2294
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Generating masks")
2295
+
2467
2296
  if plot:
2468
2297
  if resize:
2469
2298
  stack = resizescikit(stack, dims, preserve_range=True, anti_aliasing=False).astype(stack.dtype)