spacr 0.2.45__tar.gz → 0.2.46__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 (82) hide show
  1. {spacr-0.2.45/spacr.egg-info → spacr-0.2.46}/PKG-INFO +1 -1
  2. {spacr-0.2.45 → spacr-0.2.46}/setup.py +1 -1
  3. {spacr-0.2.45 → spacr-0.2.46}/spacr/core.py +12 -19
  4. {spacr-0.2.45 → spacr-0.2.46}/spacr/gui_core.py +72 -101
  5. {spacr-0.2.45 → spacr-0.2.46}/spacr/gui_utils.py +26 -12
  6. {spacr-0.2.45 → spacr-0.2.46}/spacr/io.py +24 -18
  7. {spacr-0.2.45 → spacr-0.2.46/spacr.egg-info}/PKG-INFO +1 -1
  8. {spacr-0.2.45 → spacr-0.2.46}/LICENSE +0 -0
  9. {spacr-0.2.45 → spacr-0.2.46}/MANIFEST.in +0 -0
  10. {spacr-0.2.45 → spacr-0.2.46}/README.rst +0 -0
  11. {spacr-0.2.45 → spacr-0.2.46}/setup.cfg +0 -0
  12. {spacr-0.2.45 → spacr-0.2.46}/spacr/__init__.py +0 -0
  13. {spacr-0.2.45 → spacr-0.2.46}/spacr/__main__.py +0 -0
  14. {spacr-0.2.45 → spacr-0.2.46}/spacr/app_annotate.py +0 -0
  15. {spacr-0.2.45 → spacr-0.2.46}/spacr/app_classify.py +0 -0
  16. {spacr-0.2.45 → spacr-0.2.46}/spacr/app_make_masks.py +0 -0
  17. {spacr-0.2.45 → spacr-0.2.46}/spacr/app_mask.py +0 -0
  18. {spacr-0.2.45 → spacr-0.2.46}/spacr/app_measure.py +0 -0
  19. {spacr-0.2.45 → spacr-0.2.46}/spacr/app_sequencing.py +0 -0
  20. {spacr-0.2.45 → spacr-0.2.46}/spacr/app_umap.py +0 -0
  21. {spacr-0.2.45 → spacr-0.2.46}/spacr/chris.py +0 -0
  22. {spacr-0.2.45 → spacr-0.2.46}/spacr/deep_spacr.py +0 -0
  23. {spacr-0.2.45 → spacr-0.2.46}/spacr/graph_learning.py +0 -0
  24. {spacr-0.2.45 → spacr-0.2.46}/spacr/gui.py +0 -0
  25. {spacr-0.2.45 → spacr-0.2.46}/spacr/gui_elements.py +0 -0
  26. {spacr-0.2.45 → spacr-0.2.46}/spacr/logger.py +0 -0
  27. {spacr-0.2.45 → spacr-0.2.46}/spacr/measure.py +0 -0
  28. {spacr-0.2.45 → spacr-0.2.46}/spacr/plot.py +0 -0
  29. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/abort.png +0 -0
  30. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/annotate.png +0 -0
  31. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/cellpose_all.png +0 -0
  32. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/cellpose_masks.png +0 -0
  33. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/classify.png +0 -0
  34. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/default.png +0 -0
  35. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/download.png +0 -0
  36. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/logo.pdf +0 -0
  37. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/logo_spacr.png +0 -0
  38. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/logo_spacr_1.png +0 -0
  39. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/make_masks.png +0 -0
  40. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/map_barcodes.png +0 -0
  41. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/mask.png +0 -0
  42. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/measure.png +0 -0
  43. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/ml_analyze.png +0 -0
  44. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/recruitment.png +0 -0
  45. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/regression.png +0 -0
  46. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/run.png +0 -0
  47. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/sequencing.png +0 -0
  48. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/settings.png +0 -0
  49. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/spacr_logo_rotation.gif +0 -0
  50. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/train_cellpose.png +0 -0
  51. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/icons/umap.png +0 -0
  52. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model +0 -0
  53. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model_settings.csv +0 -0
  54. {spacr-0.2.45 → spacr-0.2.46}/spacr/resources/models/cp/toxo_pv_lumen.CP_model +0 -0
  55. {spacr-0.2.45 → spacr-0.2.46}/spacr/sequencing.py +0 -0
  56. {spacr-0.2.45 → spacr-0.2.46}/spacr/settings.py +0 -0
  57. {spacr-0.2.45 → spacr-0.2.46}/spacr/sim.py +0 -0
  58. {spacr-0.2.45 → spacr-0.2.46}/spacr/sim_app.py +0 -0
  59. {spacr-0.2.45 → spacr-0.2.46}/spacr/timelapse.py +0 -0
  60. {spacr-0.2.45 → spacr-0.2.46}/spacr/utils.py +0 -0
  61. {spacr-0.2.45 → spacr-0.2.46}/spacr/version.py +0 -0
  62. {spacr-0.2.45 → spacr-0.2.46}/spacr.egg-info/SOURCES.txt +0 -0
  63. {spacr-0.2.45 → spacr-0.2.46}/spacr.egg-info/dependency_links.txt +0 -0
  64. {spacr-0.2.45 → spacr-0.2.46}/spacr.egg-info/entry_points.txt +0 -0
  65. {spacr-0.2.45 → spacr-0.2.46}/spacr.egg-info/requires.txt +0 -0
  66. {spacr-0.2.45 → spacr-0.2.46}/spacr.egg-info/top_level.txt +0 -0
  67. {spacr-0.2.45 → spacr-0.2.46}/tests/test_annotate_app.py +0 -0
  68. {spacr-0.2.45 → spacr-0.2.46}/tests/test_core.py +0 -0
  69. {spacr-0.2.45 → spacr-0.2.46}/tests/test_gui_classify_app.py +0 -0
  70. {spacr-0.2.45 → spacr-0.2.46}/tests/test_gui_mask_app.py +0 -0
  71. {spacr-0.2.45 → spacr-0.2.46}/tests/test_gui_measure_app.py +0 -0
  72. {spacr-0.2.45 → spacr-0.2.46}/tests/test_gui_sim_app.py +0 -0
  73. {spacr-0.2.45 → spacr-0.2.46}/tests/test_gui_utils.py +0 -0
  74. {spacr-0.2.45 → spacr-0.2.46}/tests/test_io.py +0 -0
  75. {spacr-0.2.45 → spacr-0.2.46}/tests/test_mask_app.py +0 -0
  76. {spacr-0.2.45 → spacr-0.2.46}/tests/test_measure.py +0 -0
  77. {spacr-0.2.45 → spacr-0.2.46}/tests/test_plot.py +0 -0
  78. {spacr-0.2.45 → spacr-0.2.46}/tests/test_sim.py +0 -0
  79. {spacr-0.2.45 → spacr-0.2.46}/tests/test_timelapse.py +0 -0
  80. {spacr-0.2.45 → spacr-0.2.46}/tests/test_train.py +0 -0
  81. {spacr-0.2.45 → spacr-0.2.46}/tests/test_umap.py +0 -0
  82. {spacr-0.2.45 → spacr-0.2.46}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spacr
3
- Version: 0.2.45
3
+ Version: 0.2.46
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
@@ -53,7 +53,7 @@ dependencies = [
53
53
 
54
54
  setup(
55
55
  name="spacr",
56
- version="0.2.45",
56
+ version="0.2.46",
57
57
  author="Einar Birnir Olafsson",
58
58
  author_email="olafsson@med.umich.com",
59
59
  description="Spatial phenotype analysis of crisp screens (SpaCr)",
@@ -1782,7 +1782,7 @@ def preprocess_generate_masks(src, settings={}):
1782
1782
 
1783
1783
  for i, file in enumerate(files):
1784
1784
  start = time.time()
1785
- if i <= settings['examples_to_plot']:
1785
+ if i+1 <= settings['examples_to_plot']:
1786
1786
  file_path = os.path.join(merged_src, file)
1787
1787
  plot_image_mask_overlay(file_path, settings['channels'], settings['cell_channel'], settings['nucleus_channel'], settings['pathogen_channel'], figuresize=10, normalize=True, thickness=3, save_pdf=True)
1788
1788
  stop = time.time()
@@ -2014,7 +2014,6 @@ def generate_cellpose_masks(src, settings, object_type):
2014
2014
 
2015
2015
  files_to_process = len(paths)
2016
2016
  for file_index, path in enumerate(paths):
2017
- start = time.time()
2018
2017
  name = os.path.basename(path)
2019
2018
  name, ext = os.path.splitext(name)
2020
2019
  output_folder = os.path.join(os.path.dirname(path), object_type+'_mask_stack')
@@ -2051,6 +2050,7 @@ def generate_cellpose_masks(src, settings, object_type):
2051
2050
  print(f'Cut batch at indecies: {timelapse_frame_limits}, New batch_size: {batch_size} ')
2052
2051
 
2053
2052
  for i in range(0, stack.shape[0], batch_size):
2053
+ start = time.time()
2054
2054
  mask_stack = []
2055
2055
  if stack.shape[3] == 1:
2056
2056
  batch = stack[i: i+batch_size, :, :, [0,0]].astype(stack.dtype)
@@ -2062,7 +2062,6 @@ def generate_cellpose_masks(src, settings, object_type):
2062
2062
  if not settings['plot']:
2063
2063
  batch, batch_filenames = _check_masks(batch, batch_filenames, output_folder)
2064
2064
  if batch.size == 0:
2065
- #print(f'Processing {file_index}/{len(paths)}: Images/npz {batch.shape[0]}')
2066
2065
  continue
2067
2066
 
2068
2067
  batch = prepare_batch_for_cellpose(batch)
@@ -2073,16 +2072,14 @@ def generate_cellpose_masks(src, settings, object_type):
2073
2072
  save_path = os.path.join(movie_path, f'timelapse_{object_type}_{name}.mp4')
2074
2073
  _npz_to_movie(batch, batch_filenames, save_path, fps=2)
2075
2074
 
2076
- #if settings['verbose']:
2077
- #print(f'Processing {file_index}/{len(paths)}: Images/npz {batch.shape[0]}')
2078
-
2079
- #cellpose_normalize_dict = {'lowhigh':[0.0,1.0], #pass in normalization values for 0.0 and 1.0 as list [low, high] if None all other keys ignored
2080
- # 'sharpen':object_settings['diameter']/4, #recommended to be 1/4-1/8 diameter of cells in pixels
2081
- # 'normalize':True, #(if False, all following parameters ignored)
2082
- # 'percentile':[2,98], #[perc_low, perc_high]
2083
- # 'tile_norm':224, #normalize by tile set to e.g. 100 for normailize window to be 100 px
2084
- # 'norm3D':True} #compute normalization across entire z-stack rather than plane-by-plane in stitching mode.
2085
-
2075
+ stop = time.time()
2076
+ duration = (stop - start)
2077
+ time_ls.append(duration)
2078
+ files_processed = (file_index+1)*len(batch_filenames)
2079
+ files_processed = len(paths)*batch.shape[0]
2080
+ print('file_index', file_index, 'len(paths)', len(paths), 'batch.shape[0]', batch.shape[0])
2081
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch.shape[0], operation_type=f'{object_type}_mask_gen')
2082
+
2086
2083
  output = model.eval(x=batch,
2087
2084
  batch_size=cellpose_batch_size,
2088
2085
  normalize=False,
@@ -2204,12 +2201,8 @@ def generate_cellpose_masks(src, settings, object_type):
2204
2201
  np.save(output_filename, mask)
2205
2202
  mask_stack = []
2206
2203
  batch_filenames = []
2207
- stop = time.time()
2208
- duration = (stop - start)
2209
- time_ls.append(duration)
2210
- files_processed = file_index+1
2211
- 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')
2212
- #gc.collect()
2204
+
2205
+ gc.collect()
2213
2206
  torch.cuda.empty_cache()
2214
2207
  return
2215
2208
 
@@ -10,6 +10,7 @@ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
10
10
  import numpy as np
11
11
  import psutil
12
12
  import GPUtil
13
+ import tkinter.font as tkFont
13
14
 
14
15
  try:
15
16
  ctypes.windll.shcore.SetProcessDpiAwareness(True)
@@ -253,51 +254,45 @@ def setup_plot_section(vertical_container):
253
254
 
254
255
  def setup_console(vertical_container):
255
256
  global console_output
257
+ from .gui_elements import set_dark_style
256
258
 
257
- # Create a frame to hold the console and button sections
258
- console_button_frame = tk.Frame(vertical_container)
259
- vertical_container.add(console_button_frame, stretch="always")
259
+ # Apply dark style and get style output
260
+ style = ttk.Style()
261
+ style_out = set_dark_style(style)
262
+
263
+ # Create a PanedWindow to hold the main content and console sections
264
+ main_paned_window = tk.PanedWindow(vertical_container, orient=tk.VERTICAL, bg=style_out['bg_color'])
265
+ vertical_container.add(main_paned_window, stretch="always")
260
266
 
261
- # Create a PanedWindow for resizing height
262
- console_paned_window = tk.PanedWindow(console_button_frame, orient=tk.VERTICAL, bg='black')
263
- console_paned_window.pack(fill=tk.BOTH, expand=True)
267
+ # Create the main content frame
268
+ main_content_frame = tk.Frame(main_paned_window, bg=style_out['bg_color'])
269
+ main_paned_window.add(main_content_frame, stretch="always")
264
270
 
265
- # Create the main console frame using spacrFrame with textbox=True
266
- console_frame = spacrFrame(console_paned_window, textbox=True)
267
- console_paned_window.add(console_frame, stretch="always")
271
+ # Create a frame to hold the console and button sections
272
+ console_button_frame = tk.Frame(main_paned_window, bg=style_out['bg_color'])
273
+ main_paned_window.add(console_button_frame, stretch="always")
268
274
 
269
- # Assign the scrollable frame (which is a Text widget) to console_output
270
- console_output = console_frame.scrollable_frame
275
+ # Create the main console frame
276
+ console_frame = tk.Frame(console_button_frame, bg=style_out['bg_color'])
277
+ console_frame.pack(fill=tk.BOTH, expand=True)
271
278
 
272
- # Ensure the Text widget spans the entire console frame
273
- console_output.grid(row=0, column=0, sticky="nsew")
279
+ # Create the scrollable frame (which is a Text widget) with white text
280
+ family = style_out['font_family']
281
+ size = style_out['font_size'] -2
282
+ font = tkFont.Font(family=family, size=size)
283
+ console_output = tk.Text(console_frame, bg=style_out['bg_color'], fg=style_out['fg_color'], font=font)
284
+ console_output.pack(fill=tk.BOTH, expand=True)
274
285
 
275
286
  # Configure the grid to allow expansion
276
287
  console_frame.grid_rowconfigure(0, weight=1)
277
288
  console_frame.grid_columnconfigure(0, weight=1)
278
289
 
279
290
  # Create a lower frame to act as the anchor point
280
- lower_frame = tk.Frame(console_paned_window)
281
- console_paned_window.add(lower_frame, minsize=10) # Adjust minsize to ensure usability
282
-
283
- # Dynamically adjust the height and width of the console_frame
284
- def adjust_frame_size(event):
285
- console_frame.update_idletasks()
286
- new_width = console_paned_window.winfo_width()
287
- new_height = console_paned_window.winfo_height()
288
- console_frame.config(width=new_width, height=new_height)
289
- console_output.config(width=new_width, height=new_height)
290
-
291
- # Bind the configure event to dynamically adjust size
292
- console_paned_window.bind("<Configure>", adjust_frame_size)
293
-
294
- # Apply dark style to the PanedWindow and lower frame
295
- style = ttk.Style()
296
- set_dark_style(style, containers=[console_paned_window, lower_frame])
291
+ lower_frame = tk.Frame(console_button_frame, bg=style_out['bg_color'])
292
+ lower_frame.pack(fill=tk.X, expand=False)
297
293
 
298
294
  return console_output, console_frame
299
295
 
300
-
301
296
  def setup_progress_frame(vertical_container):
302
297
  global progress_output
303
298
  progress_frame = tk.Frame(vertical_container)
@@ -321,13 +316,12 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
321
316
  from .gui_utils import set_element_size, download_hug_dataset
322
317
  from .settings import categories
323
318
 
324
-
325
319
  size_dict = set_element_size(horizontal_container)
326
320
  button_section_height = size_dict['panel_height']
327
321
  button_frame = tk.Frame(horizontal_container, height=button_section_height)
328
322
 
329
323
  # Prevent the frame from resizing based on the child widget
330
- button_frame.pack_propagate(False)
324
+ #button_frame.pack_propagate(False)
331
325
 
332
326
  horizontal_container.add(button_frame, stretch="always", sticky="nsew")
333
327
  button_scrollable_frame = spacrFrame(button_frame, scrollbar=False)
@@ -338,7 +332,6 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
338
332
  btn_row = 0
339
333
 
340
334
  if run:
341
- print(f'settings_type: {settings_type}')
342
335
  run_button = spacrButton(button_scrollable_frame.scrollable_frame, text="run", command=lambda: start_process(q, fig_queue, settings_type), show_text=False, size=size_dict['btn_size'], animation=False)
343
336
  run_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
344
337
  widgets.append(run_button)
@@ -364,7 +357,7 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
364
357
 
365
358
  # Add the progress bar under the settings category menu
366
359
  progress_bar = spacrProgressBar(button_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate')
367
- progress_bar.grid(row=btn_row, column=0, columnspan=5, pady=5, padx=5, sticky='ew')
360
+ progress_bar.grid(row=btn_row, column=0, columnspan=6, pady=5, padx=5, sticky='ew')
368
361
  progress_bar.set_label_position() # Set the label position after grid placement
369
362
  widgets.append(progress_bar)
370
363
 
@@ -374,11 +367,14 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
374
367
  style = ttk.Style(horizontal_container)
375
368
  _ = set_dark_style(style, containers=[button_frame], widgets=widgets)
376
369
 
377
- return button_scrollable_frame
370
+ return button_scrollable_frame, btn_col
378
371
 
379
- def setup_usage_panel(horizontal_container):
372
+ def setup_usage_panel(horizontal_container, btn_col):
380
373
  global usage_bars
381
374
  from .gui_utils import set_element_size
375
+ from .gui_elements import set_dark_style
376
+
377
+ usg_col = 1
382
378
 
383
379
  def update_usage(ram_bar, vram_bar, gpu_bar, usage_bars, parent_frame):
384
380
  # Update RAM usage
@@ -405,7 +401,7 @@ def setup_usage_panel(horizontal_container):
405
401
  size_dict = set_element_size(horizontal_container)
406
402
  usage_panel_height = size_dict['panel_height']
407
403
  usage_frame = tk.Frame(horizontal_container, height=usage_panel_height)
408
- horizontal_container.add(usage_frame, stretch="always", sticky="nsew")
404
+ horizontal_container.add(usage_frame)
409
405
 
410
406
  usage_frame.grid_rowconfigure(0, weight=0)
411
407
  usage_frame.grid_rowconfigure(1, weight=1)
@@ -415,6 +411,7 @@ def setup_usage_panel(horizontal_container):
415
411
  usage_scrollable_frame = spacrFrame(usage_frame, scrollbar=False)
416
412
  usage_scrollable_frame.grid(row=1, column=0, sticky="nsew", columnspan=2)
417
413
  widgets = [usage_scrollable_frame.scrollable_frame]
414
+
418
415
  usage_bars = []
419
416
  max_elements_per_column = 6
420
417
  row = 0
@@ -422,12 +419,19 @@ def setup_usage_panel(horizontal_container):
422
419
 
423
420
  # Initialize RAM, VRAM, and GPU bars as None
424
421
  ram_bar, vram_bar, gpu_bar = None, None, None
422
+
423
+ # Configure the style for the label
424
+ style = ttk.Style()
425
+ style_out = set_dark_style(style)
426
+ size = style_out['font_size'] - 2
427
+ usage_font = tkFont.Font(family=style_out['font_family'], size=size)
428
+ style.configure("usage.TLabel", font=usage_font, foreground=style_out['fg_color'])
425
429
 
426
430
  # Try adding RAM bar
427
431
  try:
428
432
  ram_info = psutil.virtual_memory()
429
433
  ram_label_text = f"RAM"
430
- label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=ram_label_text, anchor='w')
434
+ label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=ram_label_text, anchor='w', style="usage.TLabel")
431
435
  label.grid(row=row, column=2 * col, pady=5, padx=5, sticky='w')
432
436
  ram_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
433
437
  ram_bar.grid(row=row, column=2 * col + 1, pady=5, padx=5, sticky='ew')
@@ -444,7 +448,7 @@ def setup_usage_panel(horizontal_container):
444
448
  if gpus:
445
449
  gpu = gpus[0]
446
450
  vram_label_text = f"VRAM"
447
- label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=vram_label_text, anchor='w')
451
+ label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=vram_label_text, anchor='w', style="usage.TLabel")
448
452
  label.grid(row=row, column=2 * col, pady=5, padx=5, sticky='w')
449
453
  vram_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
450
454
  vram_bar.grid(row=row, column=2 * col + 1, pady=5, padx=5, sticky='ew')
@@ -454,7 +458,7 @@ def setup_usage_panel(horizontal_container):
454
458
  row += 1
455
459
 
456
460
  gpu_label_text = f"GPU"
457
- label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=gpu_label_text, anchor='w')
461
+ label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=gpu_label_text, anchor='w', style="usage.TLabel")
458
462
  label.grid(row=row, column=2 * col, pady=5, padx=5, sticky='w')
459
463
  gpu_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
460
464
  gpu_bar.grid(row=row, column=2 * col + 1, pady=5, padx=5, sticky='ew')
@@ -474,7 +478,7 @@ def setup_usage_panel(horizontal_container):
474
478
  if row > 0 and row % max_elements_per_column == 0:
475
479
  col += 1
476
480
  row = 0
477
- label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=f"Core {core+1}", anchor='w')
481
+ label = ttk.Label(usage_scrollable_frame.scrollable_frame, text=f"Core {core+1}", anchor='w', style="usage.TLabel")
478
482
  label.grid(row=row, column=2 * col, pady=2, padx=5, sticky='w')
479
483
  bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
480
484
  bar.grid(row=row, column=2 * col + 1, pady=2, padx=5, sticky='ew')
@@ -494,58 +498,9 @@ def setup_usage_panel(horizontal_container):
494
498
  vram_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
495
499
  if gpu_bar is None:
496
500
  gpu_bar = spacrProgressBar(usage_scrollable_frame.scrollable_frame, orient='horizontal', mode='determinate', length=size_dict['bar_size'], label=False)
497
-
498
- update_usage(ram_bar, vram_bar, gpu_bar, usage_bars, usage_frame)
499
- return usage_scrollable_frame, usage_bars
500
-
501
- def setup_help_section(horizontal_container, settings_type='mask'):
502
- from .settings import descriptions
503
- from .gui_utils import set_element_size
504
-
505
- size_dict = set_element_size(horizontal_container)
506
- help_section_height = size_dict['panel_height']
507
-
508
- # Create the frame for the help section
509
- description_frame = tk.Frame(horizontal_container, height=help_section_height)
510
- description_frame.pack_propagate(False)
511
-
512
- # Add the description frame to the horizontal container
513
- horizontal_container.add(description_frame, stretch="always", sticky="nsew")
514
- description_frame.grid_columnconfigure(0, weight=1)
515
- description_frame.grid_rowconfigure(0, weight=1) # Ensure the text widget row is expandable
516
-
517
- style_out = set_dark_style(ttk.Style())
518
- bg_color = style_out['bg_color']
519
- fg_color = style_out['fg_color']
520
-
521
- # Insert the description text
522
- description_text = descriptions.get(settings_type, "No description available for this module.")
523
- first_line, *rest_of_description = description_text.split('\n', 1)
524
-
525
- # Create the first line label
526
- first_line_label = ttk.Label(description_frame, text=first_line, anchor='w', background=bg_color, foreground=fg_color)
527
- first_line_label.grid(row=0, column=0, sticky='ew')
528
-
529
- # Create the text widget with the appropriate background and foreground colors
530
- description_text_widget = tk.Text(description_frame, wrap="word", bg=bg_color, fg=fg_color, bd=0, highlightthickness=0)
531
- description_text_widget.grid(row=1, column=0, sticky="nsew")
532
-
533
- # Insert the rest of the description text
534
- if rest_of_description:
535
- description_text_widget.insert("1.0", rest_of_description[0].lstrip())
536
- description_text_widget.config(state="disabled") # Make the text widget read-only
537
-
538
- def update_wraplength(event):
539
- new_width = event.width - 20 # Adjust as needed
540
- description_text_widget.config(width=new_width)
541
-
542
- description_text_widget.bind('<Configure>', update_wraplength)
543
-
544
- # Apply dark style
545
- style = ttk.Style(horizontal_container)
546
- _ = set_dark_style(style, containers=[description_frame], widgets=[description_text_widget, first_line_label])
547
-
548
- return description_frame
501
+
502
+ update_usage(ram_bar, vram_bar, gpu_bar, usage_bars, usage_frame)
503
+ return usage_scrollable_frame, usage_bars, usg_col
549
504
 
550
505
  def initiate_abort():
551
506
  global thread_control, q, parent_frame
@@ -602,9 +557,11 @@ def process_console_queue():
602
557
  # Initialize function attribute if it doesn't exist
603
558
  if not hasattr(process_console_queue, "completed_tasks"):
604
559
  process_console_queue.completed_tasks = []
560
+ if not hasattr(process_console_queue, "current_maximum"):
561
+ process_console_queue.current_maximum = None
605
562
 
606
563
  ansi_escape_pattern = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
607
-
564
+
608
565
  while not q.empty():
609
566
  message = q.get_nowait()
610
567
  clean_message = ansi_escape_pattern.sub('', message)
@@ -616,12 +573,18 @@ def process_console_queue():
616
573
  try:
617
574
  # Extract the progress information
618
575
  match = re.search(r'Progress: (\d+)/(\d+), operation_type: ([\w\s]*)(.*)', clean_message)
576
+ print('match', match)
619
577
  if match:
620
578
  current_progress = int(match.group(1))
621
579
  total_progress = int(match.group(2))
622
580
  operation_type = match.group(3).strip()
623
581
  time_info = match.group(4).strip()
624
582
 
583
+ # Check if the maximum value has changed
584
+ if process_console_queue.current_maximum != total_progress:
585
+ process_console_queue.current_maximum = total_progress
586
+ process_console_queue.completed_tasks = []
587
+
625
588
  # Add the task to the completed set
626
589
  process_console_queue.completed_tasks.append(current_progress)
627
590
 
@@ -656,16 +619,19 @@ def process_console_queue():
656
619
  # Clear completed tasks when progress is complete
657
620
  if unique_progress_count >= total_progress:
658
621
  process_console_queue.completed_tasks.clear()
622
+
659
623
  except Exception as e:
660
624
  print(f"Error parsing progress message: {e}")
661
625
 
662
- after_id = console_output.after(100, process_console_queue)
626
+ after_id = console_output.after(10, process_console_queue)
663
627
  parent_frame.after_tasks.append(after_id)
664
628
 
665
629
  def initiate_root(parent, settings_type='mask'):
666
630
  global q, fig_queue, thread_control, parent_frame, scrollable_frame, button_frame, vars_dict, canvas, canvas_widget, button_scrollable_frame, progress_bar
667
631
  from .gui_utils import main_thread_update_function, setup_frame, set_element_size
668
632
  from .gui import gui_app
633
+ from .settings import descriptions
634
+
669
635
  set_start_method('spawn', force=True)
670
636
  print("Initializing root with settings_type:", settings_type)
671
637
 
@@ -693,14 +659,19 @@ def initiate_root(parent, settings_type='mask'):
693
659
  initiate_make_mask_app(horizontal_container)
694
660
  else:
695
661
  scrollable_frame, vars_dict = setup_settings_panel(settings_container, settings_type)
662
+ print('setup_settings_panel')
696
663
  canvas, canvas_widget = setup_plot_section(vertical_container)
697
- console_output, console_frame = setup_console(vertical_container)
698
- button_scrollable_frame = setup_button_section(horizontal_container, settings_type)
699
- _, usage_bars = setup_usage_panel(horizontal_container)
700
- _ = setup_help_section(horizontal_container, settings_type)
701
-
664
+ console_output, _ = setup_console(vertical_container)
665
+ button_scrollable_frame, btn_col = setup_button_section(horizontal_container, settings_type)
666
+ _, usage_bars, btn_col = setup_usage_panel(horizontal_container, btn_col)
667
+
702
668
  set_globals(thread_control, q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame, fig_queue, progress_bar, usage_bars)
669
+ description_text = descriptions.get(settings_type, "No description available for this module.")
670
+
703
671
  q.put(f"Console")
672
+ q.put(f" ")
673
+ q.put(description_text)
674
+
704
675
  process_console_queue()
705
676
  process_fig_queue()
706
677
  after_id = parent_window.after(100, lambda: main_thread_update_function(parent_window, q, fig_queue, canvas_widget))
@@ -314,7 +314,7 @@ def set_element_size(widget):
314
314
  screen_height = widget.winfo_screenheight()
315
315
  btn_size = screen_width // 40
316
316
  bar_size = screen_width // 50
317
- settings_width = screen_width // 6
317
+ settings_width = screen_width // 5
318
318
  panel_height = screen_height // 12
319
319
  panel_width = settings_width
320
320
  size_dict = {
@@ -507,24 +507,38 @@ def hide_all_settings(vars_dict, categories):
507
507
 
508
508
  def setup_frame(parent_frame):
509
509
  from .gui_elements import set_dark_style, set_default_font
510
+
510
511
  style = ttk.Style(parent_frame)
511
512
  size_dict = set_element_size(parent_frame)
512
-
513
- settings_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL, width=size_dict['settings_width'])
514
- vertical_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL)
515
- horizontal_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL, height=size_dict['panel_height'])
513
+ style_out = set_dark_style(style)
514
+
515
+ settings_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL, width=size_dict['settings_width'], bg=style_out['bg_color'])
516
+ vertical_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL, bg=style_out['bg_color'])
517
+ horizontal_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL, height=size_dict['panel_height'], bg=style_out['bg_color'])
516
518
 
517
519
  parent_frame.grid_rowconfigure(0, weight=1)
518
520
  parent_frame.grid_rowconfigure(1, weight=0)
519
- parent_frame.grid_columnconfigure(0, weight=0) # Change this line
520
- parent_frame.grid_columnconfigure(1, weight=1) # Change this line
521
+ parent_frame.grid_columnconfigure(0, weight=0)
522
+ parent_frame.grid_columnconfigure(1, weight=1)
523
+
524
+ settings_container.grid(row=0, column=0, rowspan=2, sticky="nsew")
525
+ vertical_container.grid(row=0, column=1, sticky="nsew")
526
+ horizontal_container.grid(row=1, column=1, sticky="nsew")
521
527
 
522
- settings_container.grid(row=0, column=0, rowspan=2, sticky="nsew") # Change this line
523
- vertical_container.grid(row=0, column=1, sticky="nsew") # Change this line
524
- horizontal_container.grid(row=1, column=1, sticky="ew") # Change this line
528
+ # Lock the width of the horizontal_container
529
+ horizontal_container.update_idletasks() # Ensure geometry manager calculates size
530
+ fixed_width = horizontal_container.winfo_width()
531
+ parent_frame.grid_columnconfigure(1, weight=0)
532
+ horizontal_container.config(width=fixed_width)
533
+
534
+ tk.Label(settings_container, text="Settings Container", bg=style_out['bg_color']).pack(fill=tk.BOTH, expand=True)
535
+ tk.Label(vertical_container, text="Vertical Container", bg=style_out['bg_color']).pack(fill=tk.BOTH, expand=True)
525
536
 
526
537
  set_dark_style(style, parent_frame, [settings_container, vertical_container, horizontal_container])
527
- set_default_font(parent_frame, font_name="Helvetica", size=8)
538
+
539
+ size = style_out['font_size'] - 2
540
+
541
+ set_default_font(parent_frame, font_name=style_out['font_family'], size=size)
528
542
 
529
543
  return parent_frame, vertical_container, horizontal_container, settings_container
530
544
 
@@ -532,7 +546,7 @@ def download_hug_dataset(q, vars_dict):
532
546
  dataset_repo_id = "einarolafsson/toxo_mito"
533
547
  settings_repo_id = "einarolafsson/spacr_settings"
534
548
  dataset_subfolder = "plate1"
535
- local_dir = os.path.join(os.path.expanduser("~"), "datasets") # Set to the home directory
549
+ local_dir = os.path.join(os.path.expanduser("~"), "datasets")
536
550
 
537
551
  # Download the dataset
538
552
  try:
@@ -594,9 +594,9 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
594
594
  print(f'All_files: {len(all_filenames)} in {src}')
595
595
  time_ls = []
596
596
 
597
- for i in range(0, len(all_filenames), batch_size):
597
+ for idx in range(0, len(all_filenames), batch_size):
598
598
  start = time.time()
599
- batch_filenames = all_filenames[i:i+batch_size]
599
+ batch_filenames = all_filenames[idx:idx+batch_size]
600
600
  files_processed = 0
601
601
  for filename in batch_filenames:
602
602
  images_by_key = _extract_filename_metadata(batch_filenames, src, images_by_key, regular_expression, metadata_type, pick_slice, skip_mode)
@@ -610,6 +610,12 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
610
610
  os.makedirs(output_dir, exist_ok=True)
611
611
  output_filename = f'{plate}_{well}_{field}.tif'
612
612
  output_path = os.path.join(output_dir, output_filename)
613
+ files_processed += 1
614
+ stop = time.time()
615
+ duration = stop - start
616
+ time_ls.append(duration)
617
+ files_to_process = len(all_filenames)
618
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type='Preprocessing filenames')
613
619
 
614
620
  if os.path.exists(output_path):
615
621
  print(f'WARNING: A file with the same name already exists at location {output_filename}')
@@ -624,18 +630,18 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
624
630
  os.makedirs(output_dir, exist_ok=True)
625
631
  output_filename = f'{plate}_{well}_{field}.tif'
626
632
  output_path = os.path.join(output_dir, output_filename)
633
+ files_processed += 1
634
+ stop = time.time()
635
+ duration = stop - start
636
+ time_ls.append(duration)
637
+ files_to_process = len(all_filenames)
638
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type='Preprocessing filenames')
627
639
 
628
640
  if os.path.exists(output_path):
629
641
  print(f'WARNING: A file with the same name already exists at location {output_filename}')
630
642
  else:
631
643
  mip_image.save(output_path)
632
644
  images_by_key.clear()
633
- stop = time.time()
634
- duration = stop - start
635
- time_ls.append(duration)
636
- files_processed += len(batch_filenames)
637
- files_to_process = len(all_filenames)
638
- print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type='Preprocessing filenames')
639
645
 
640
646
  # Move original images to a new directory
641
647
  valid_exts = [img_format]
@@ -968,7 +974,7 @@ def _concatenate_channel(src, channels, randomize=True, timelapse=False, batch_s
968
974
  time_ls.append(duration)
969
975
  files_processed = i+1
970
976
  files_to_process = time_stack_path_lists
971
- #print_progress(files_processed, files_to_process, n_jobs=1, time_ls=None, batch_size=None, operation_type="Concatinating")
977
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Concatinating")
972
978
  stack = np.stack(stack_region)
973
979
  save_loc = os.path.join(channel_stack_loc, f'{name}.npz')
974
980
  np.savez(save_loc, data=stack, filenames=filenames_region)
@@ -999,7 +1005,7 @@ def _concatenate_channel(src, channels, randomize=True, timelapse=False, batch_s
999
1005
  time_ls.append(duration)
1000
1006
  files_processed = i+1
1001
1007
  files_to_process = nr_files
1002
- print_progress(files_processed, files_to_process, n_jobs=1, time_ls=None, batch_size=None, operation_type="Concatinating")
1008
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Concatinating")
1003
1009
  if (i+1) % batch_size == 0 or i+1 == nr_files:
1004
1010
  unique_shapes = {arr.shape[:-1] for arr in stack_ls}
1005
1011
  if len(unique_shapes) > 1:
@@ -1097,7 +1103,7 @@ def _normalize_img_batch(stack, channels, save_dtype, settings):
1097
1103
  time_ls.append(duration)
1098
1104
  files_processed = i+1
1099
1105
  files_to_process = len(channels)
1100
- #print_progress(files_processed, files_to_process, n_jobs=1, time_ls=None, batch_size=None, operation_type=f"Normalizing: Channel: {channel}")
1106
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type=f"Normalizing")
1101
1107
 
1102
1108
  return normalized_stack.astype(save_dtype)
1103
1109
 
@@ -1144,7 +1150,6 @@ def concatenate_and_normalize(src, channels, save_dtype=np.float32, settings={})
1144
1150
  parts = file.split('_')
1145
1151
  name = parts[0] + '_' + parts[1] + '_' + parts[2]
1146
1152
  array = np.load(path)
1147
- #array = np.take(array, channels, axis=2)
1148
1153
  stack_region.append(array)
1149
1154
  filenames_region.append(os.path.basename(path))
1150
1155
  stop = time.time()
@@ -1152,7 +1157,7 @@ def concatenate_and_normalize(src, channels, save_dtype=np.float32, settings={})
1152
1157
  time_ls.append(duration)
1153
1158
  files_processed = i+1
1154
1159
  files_to_process = len(time_stack_path_lists)
1155
- print_progress(files_processed, files_to_process, n_jobs=1, time_ls=None, batch_size=None, operation_type="Concatinating")
1160
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Concatinating")
1156
1161
  stack = np.stack(stack_region)
1157
1162
 
1158
1163
  normalized_stack = _normalize_img_batch(stack=stack,
@@ -1181,6 +1186,7 @@ def concatenate_and_normalize(src, channels, save_dtype=np.float32, settings={})
1181
1186
  stack_ls = []
1182
1187
  filenames_batch = []
1183
1188
  time_ls = []
1189
+ files_processed = 0
1184
1190
  for i, path in enumerate(paths):
1185
1191
  start = time.time()
1186
1192
  array = np.load(path)
@@ -1189,7 +1195,7 @@ def concatenate_and_normalize(src, channels, save_dtype=np.float32, settings={})
1189
1195
  stop = time.time()
1190
1196
  duration = stop - start
1191
1197
  time_ls.append(duration)
1192
- files_processed = i+1
1198
+ files_processed += 1
1193
1199
  files_to_process = nr_files
1194
1200
  print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Concatinating")
1195
1201
 
@@ -1612,8 +1618,8 @@ def preprocess_img_data(settings):
1612
1618
  save_dtype=np.float32,
1613
1619
  settings=settings)
1614
1620
 
1615
- if plot:
1616
- _plot_4D_arrays(src+'/norm_channel_stack', nr_npz=1, nr=nr)
1621
+ #if plot:
1622
+ # _plot_4D_arrays(src+'/norm_channel_stack', nr_npz=1, nr=nr)
1617
1623
 
1618
1624
  return settings, src
1619
1625
 
@@ -1943,7 +1949,7 @@ def _load_and_concatenate_arrays(src, channels, cell_chann_dim, nucleus_chann_di
1943
1949
  all_imgs = len(os.listdir(reference_folder))
1944
1950
  time_ls = []
1945
1951
  # Iterate through each file in the reference folder
1946
- for filename in os.listdir(reference_folder):
1952
+ for idx, filename in enumerate(os.listdir(reference_folder)):
1947
1953
  start = time.time()
1948
1954
  stack_ls = []
1949
1955
  if filename.endswith('.npy'):
@@ -2004,7 +2010,7 @@ def _load_and_concatenate_arrays(src, channels, cell_chann_dim, nucleus_chann_di
2004
2010
  stop = time.time()
2005
2011
  duration = stop - start
2006
2012
  time_ls.append(duration)
2007
- files_processed = count
2013
+ files_processed = idx+1
2008
2014
  files_to_process = all_imgs
2009
2015
  print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Merging Arrays")
2010
2016
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spacr
3
- Version: 0.2.45
3
+ Version: 0.2.46
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes