spacr 0.2.53__py3-none-any.whl → 0.2.56__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.
spacr/gui_core.py CHANGED
@@ -15,7 +15,7 @@ try:
15
15
  except AttributeError:
16
16
  pass
17
17
 
18
- from .settings import set_default_train_test_model, get_measure_crop_settings, set_default_settings_preprocess_generate_masks, get_analyze_reads_default_settings, set_default_umap_image_settings
18
+ from .settings import set_default_train_test_model, get_measure_crop_settings, set_default_settings_preprocess_generate_masks, set_default_generate_barecode_mapping, set_default_umap_image_settings
19
19
  from .gui_elements import spacrProgressBar, spacrButton, spacrLabel, spacrFrame, spacrDropdownMenu ,set_dark_style
20
20
 
21
21
  # Define global variables
@@ -122,7 +122,7 @@ def set_globals(thread_control_var, q_var, console_output_var, parent_frame_var,
122
122
  def import_settings(settings_type='mask'):
123
123
  from .gui_utils import convert_settings_dict_for_gui, hide_all_settings
124
124
  global vars_dict, scrollable_frame, button_scrollable_frame
125
- from .settings import generate_fields
125
+ from .settings import generate_fields, set_default_settings_preprocess_generate_masks, get_measure_crop_settings, set_default_train_test_model, set_default_generate_barecode_mapping, set_default_umap_image_settings
126
126
 
127
127
  def read_settings_from_csv(csv_file_path):
128
128
  settings = {}
@@ -158,7 +158,7 @@ def import_settings(settings_type='mask'):
158
158
  elif settings_type == 'classify':
159
159
  settings = set_default_train_test_model(settings={})
160
160
  elif settings_type == 'sequencing':
161
- settings = get_analyze_reads_default_settings(settings={})
161
+ settings = set_default_generate_barecode_mapping(settings={})
162
162
  elif settings_type == 'umap':
163
163
  settings = set_default_umap_image_settings(settings={})
164
164
  else:
@@ -171,7 +171,7 @@ def import_settings(settings_type='mask'):
171
171
 
172
172
  def setup_settings_panel(vertical_container, settings_type='mask'):
173
173
  global vars_dict, scrollable_frame
174
- from .settings import get_identify_masks_finetune_default_settings, set_default_analyze_screen, set_default_settings_preprocess_generate_masks, get_measure_crop_settings, set_default_train_test_model, get_analyze_reads_default_settings, set_default_umap_image_settings, generate_fields, get_perform_regression_default_settings, get_train_cellpose_default_settings, get_map_barcodes_default_settings, get_analyze_recruitment_default_settings, get_check_cellpose_models_default_settings
174
+ from .settings import get_identify_masks_finetune_default_settings, set_default_analyze_screen, set_default_settings_preprocess_generate_masks, get_measure_crop_settings, deep_spacr_defaults, set_default_generate_barecode_mapping, set_default_umap_image_settings, generate_fields, get_perform_regression_default_settings, get_train_cellpose_default_settings, get_map_barcodes_default_settings, get_analyze_recruitment_default_settings, get_check_cellpose_models_default_settings
175
175
  from .gui_utils import convert_settings_dict_for_gui
176
176
  from .gui_elements import set_element_size
177
177
 
@@ -197,9 +197,7 @@ def setup_settings_panel(vertical_container, settings_type='mask'):
197
197
  elif settings_type == 'measure':
198
198
  settings = get_measure_crop_settings(settings={})
199
199
  elif settings_type == 'classify':
200
- settings = set_default_train_test_model(settings={})
201
- elif settings_type == 'sequencing':
202
- settings = get_analyze_reads_default_settings(settings={})
200
+ settings = deep_spacr_defaults(settings={})
203
201
  elif settings_type == 'umap':
204
202
  settings = set_default_umap_image_settings(settings={})
205
203
  elif settings_type == 'train_cellpose':
@@ -211,7 +209,7 @@ def setup_settings_panel(vertical_container, settings_type='mask'):
211
209
  elif settings_type == 'cellpose_all':
212
210
  settings = get_check_cellpose_models_default_settings(settings={})
213
211
  elif settings_type == 'map_barcodes':
214
- settings = get_map_barcodes_default_settings(settings={})
212
+ settings = set_default_generate_barecode_mapping(settings={})
215
213
  elif settings_type == 'regression':
216
214
  settings = get_perform_regression_default_settings(settings={})
217
215
  elif settings_type == 'recruitment':
@@ -350,7 +348,7 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
350
348
  widgets.append(run_button)
351
349
  btn_col += 1
352
350
 
353
- if abort and settings_type in ['mask', 'measure', 'classify', 'sequencing', 'umap']:
351
+ if abort and settings_type in ['mask', 'measure', 'classify', 'sequencing', 'umap', 'map_barcodes']:
354
352
  abort_button = spacrButton(button_scrollable_frame.scrollable_frame, text="abort", command=lambda: initiate_abort(), show_text=False, size=size_dict['btn_size'], animation=False)
355
353
  abort_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
356
354
  widgets.append(abort_button)
@@ -551,7 +549,7 @@ def start_process(q=None, fig_queue=None, settings_type='mask'):
551
549
 
552
550
  process_args = (settings_type, settings, q, fig_queue, stop_requested)
553
551
  if settings_type in [
554
- 'mask', 'measure', 'simulation', 'sequencing', 'classify', 'cellpose_dataset',
552
+ 'mask', 'umap', 'measure', 'simulation', 'sequencing', 'classify', 'cellpose_dataset',
555
553
  'train_cellpose', 'ml_analyze', 'cellpose_masks', 'cellpose_all', 'map_barcodes',
556
554
  'regression', 'recruitment', 'plaques', 'cellpose_compare', 'vision_scores',
557
555
  'vision_dataset'
spacr/gui_elements.py CHANGED
@@ -603,6 +603,76 @@ class spacrCheckbutton(ttk.Checkbutton):
603
603
  _ = set_dark_style(style, widgets=[self])
604
604
 
605
605
  class spacrProgressBar(ttk.Progressbar):
606
+ def __init__(self, parent, label=True, *args, **kwargs):
607
+ super().__init__(parent, *args, **kwargs)
608
+
609
+ # Get the style colors
610
+ style_out = set_dark_style(ttk.Style())
611
+
612
+ self.fg_color = style_out['fg_color']
613
+ self.bg_color = style_out['bg_color']
614
+ self.active_color = style_out['active_color']
615
+ self.inactive_color = style_out['inactive_color']
616
+
617
+ # Configure the style for the progress bar
618
+ self.style = ttk.Style()
619
+ self.style.configure(
620
+ "spacr.Horizontal.TProgressbar",
621
+ troughcolor=self.bg_color,
622
+ background=self.active_color,
623
+ thickness=20,
624
+ troughrelief='flat',
625
+ borderwidth=0
626
+ )
627
+ self.configure(style="spacr.Horizontal.TProgressbar")
628
+
629
+ # Set initial value to 0
630
+ self['value'] = 0
631
+
632
+ # Track whether to show the progress label
633
+ self.label = label
634
+
635
+ # Create the progress label with text wrapping
636
+ if self.label:
637
+ self.progress_label = tk.Label(
638
+ parent,
639
+ text="Processing: 0/0",
640
+ anchor='w',
641
+ justify='left',
642
+ bg=self.inactive_color,
643
+ fg=self.fg_color,
644
+ wraplength=300 # Adjust the wraplength as needed
645
+ )
646
+ self.progress_label.grid_forget() # Temporarily hide it
647
+
648
+ # Initialize attributes for time and operation
649
+ self.operation_type = None
650
+ self.time_image = None
651
+ self.time_batch = None
652
+ self.time_left = None
653
+
654
+ def set_label_position(self):
655
+ if self.label and self.progress_label:
656
+ row_info = self.grid_info().get('row', 0)
657
+ col_info = self.grid_info().get('column', 0)
658
+ col_span = self.grid_info().get('columnspan', 1)
659
+ self.progress_label.grid(row=row_info + 1, column=col_info, columnspan=col_span, pady=5, padx=5, sticky='ew')
660
+
661
+ def update_label(self):
662
+ if self.label and self.progress_label:
663
+ # Update the progress label with current progress and additional info
664
+ label_text = f"Processing: {self['value']}/{self['maximum']}"
665
+ if self.operation_type:
666
+ label_text += f", {self.operation_type}"
667
+ if self.time_image:
668
+ label_text += f", Time/image: {self.time_image:.3f} sec"
669
+ if self.time_batch:
670
+ label_text += f", Time/batch: {self.time_batch:.3f} sec"
671
+ if self.time_left:
672
+ label_text += f", Time_left: {self.time_left:.3f} min"
673
+ self.progress_label.config(text=label_text)
674
+
675
+ class spacrProgressBar_v1(ttk.Progressbar):
606
676
  def __init__(self, parent, label=True, *args, **kwargs):
607
677
  super().__init__(parent, *args, **kwargs)
608
678
 
spacr/gui_utils.py CHANGED
@@ -44,7 +44,7 @@ def load_app(root, app_name, app_func):
44
44
  else:
45
45
  proceed_with_app(root, app_name, app_func)
46
46
 
47
- def parse_list(value):
47
+ def parse_list_v1(value):
48
48
  try:
49
49
  parsed_value = ast.literal_eval(value)
50
50
  if isinstance(parsed_value, list):
@@ -54,6 +54,22 @@ def parse_list(value):
54
54
  except (ValueError, SyntaxError) as e:
55
55
  raise ValueError(f"Invalid format for list: {value}. Error: {e}")
56
56
 
57
+ def parse_list(value):
58
+ try:
59
+ parsed_value = ast.literal_eval(value)
60
+ if isinstance(parsed_value, list):
61
+ # Check if the list elements are homogeneous (all int or all str)
62
+ if all(isinstance(item, int) for item in parsed_value):
63
+ return parsed_value
64
+ elif all(isinstance(item, str) for item in parsed_value):
65
+ return parsed_value
66
+ else:
67
+ raise ValueError("List contains mixed types or unsupported types")
68
+ else:
69
+ raise ValueError(f"Expected a list but got {type(parsed_value).__name__}")
70
+ except (ValueError, SyntaxError) as e:
71
+ raise ValueError(f"Invalid format for list: {value}. Error: {e}")
72
+
57
73
  # Usage example in your create_input_field function
58
74
  def create_input_field(frame, label_text, row, var_type='entry', options=None, default_value=None):
59
75
  from .gui_elements import set_dark_style, set_element_size
@@ -323,7 +339,9 @@ def convert_settings_dict_for_gui(settings):
323
339
  special_cases = {
324
340
  'metadata_type': ('combo', ['cellvoyager', 'cq1', 'nikon', 'zeis', 'custom'], 'cellvoyager'),
325
341
  'channels': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
342
+ 'train_channels': ('combo', ["['r','g','b']", "['r','g']", "['r','b']", "['g','b']", "['r']", "['g']", "['b']"], "['r','g','b']"),
326
343
  'channel_dims': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
344
+ 'dataset_mode': ('combo', ['annotation', 'metadata', 'recruitment'], 'annotate'),
327
345
  'cell_mask_dim': ('combo', chans, None),
328
346
  'cell_chann_dim': ('combo', chans, None),
329
347
  'nucleus_mask_dim': ('combo', chans, None),
@@ -369,6 +387,7 @@ def convert_settings_dict_for_gui(settings):
369
387
  variables[key] = ('entry', None, str(value))
370
388
  else:
371
389
  variables[key] = ('entry', None, str(value))
390
+
372
391
  return variables
373
392
 
374
393
 
@@ -413,13 +432,14 @@ def function_gui_wrapper(function=None, settings={}, q=None, fig_queue=None, imp
413
432
  plt.show = original_show
414
433
 
415
434
  def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
435
+
416
436
  from .gui_utils import process_stdout_stderr
417
- from .core import preprocess_generate_masks, generate_ml_scores, identify_masks_finetune, check_cellpose_models, analyze_recruitment, train_cellpose, compare_cellpose_masks, analyze_plaques, generate_dataset, apply_model_to_tar
437
+ from .core import generate_image_umap, preprocess_generate_masks, generate_ml_scores, identify_masks_finetune, check_cellpose_models, analyze_recruitment, train_cellpose, compare_cellpose_masks, analyze_plaques, generate_dataset, apply_model_to_tar
418
438
  from .io import generate_cellpose_train_test
419
439
  from .measure import measure_crop
420
440
  from .sim import run_multiple_simulations
421
- from .deep_spacr import train_test_model
422
- from .sequencing import analyze_reads, map_barcodes_folder, perform_regression
441
+ from .deep_spacr import deep_spacr
442
+ from .sequencing import generate_barecode_mapping, perform_regression
423
443
  process_stdout_stderr(q)
424
444
 
425
445
  print(f'run_function_gui settings_type: {settings_type}')
@@ -433,12 +453,9 @@ def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
433
453
  elif settings_type == 'simulation':
434
454
  function = run_multiple_simulations
435
455
  imports = 1
436
- elif settings_type == 'sequencing':
437
- function = analyze_reads
438
- imports = 1
439
456
  elif settings_type == 'classify':
440
- function = train_test_model
441
- imports = 2
457
+ function = deep_spacr
458
+ imports = 1
442
459
  elif settings_type == 'train_cellpose':
443
460
  function = train_cellpose
444
461
  imports = 1
@@ -452,7 +469,7 @@ def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
452
469
  function = check_cellpose_models
453
470
  imports = 1
454
471
  elif settings_type == 'map_barcodes':
455
- function = map_barcodes_folder
472
+ function = generate_barecode_mapping
456
473
  imports = 1
457
474
  elif settings_type == 'regression':
458
475
  function = perform_regression
@@ -460,6 +477,9 @@ def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
460
477
  elif settings_type == 'recruitment':
461
478
  function = analyze_recruitment
462
479
  imports = 2
480
+ elif settings_type == 'umap':
481
+ function = generate_image_umap
482
+ imports = 1
463
483
  else:
464
484
  raise ValueError(f"Invalid settings type: {settings_type}")
465
485
  try:
spacr/io.py CHANGED
@@ -2293,15 +2293,23 @@ def _save_model(model, model_type, results_df, dst, epoch, epochs, intermedeate_
2293
2293
  def save_model_at_threshold(threshold, epoch, suffix=""):
2294
2294
  percentile = str(threshold * 100)
2295
2295
  print(f'\rfound: {percentile}% accurate model')#, end='\r', flush=True)
2296
- torch.save(model, f'{dst}/{model_type}_epoch_{str(epoch)}{suffix}_acc_{percentile}_channels_{channels_str}.pth')
2296
+ model_path = f'{dst}/{model_type}_epoch_{str(epoch)}{suffix}_acc_{percentile}_channels_{channels_str}.pth'
2297
+ torch.save(model, model_path)
2298
+ return model_path
2297
2299
 
2298
2300
  if epoch % 100 == 0 or epoch == epochs:
2299
- torch.save(model, f'{dst}/{model_type}_epoch_{str(epoch)}_channels_{channels_str}.pth')
2301
+ model_path = f'{dst}/{model_type}_epoch_{str(epoch)}_channels_{channels_str}.pth'
2302
+ torch.save(model, model_path)
2303
+ return model_path
2300
2304
 
2301
2305
  for threshold in intermedeate_save:
2302
2306
  if results_df['neg_accuracy'].dropna().mean() >= threshold and results_df['pos_accuracy'].dropna().mean() >= threshold:
2303
- save_model_at_threshold(threshold, epoch)
2304
- break # Ensure we only save for the highest matching threshold
2307
+ model_path = save_model_at_threshold(threshold, epoch)
2308
+ break
2309
+ else:
2310
+ model_path = None
2311
+
2312
+ return model_path
2305
2313
 
2306
2314
  def _save_progress(dst, results_df, train_metrics_df, epoch, epochs):
2307
2315
  """