spacr 0.2.41__py3-none-any.whl → 0.2.46__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_utils.py CHANGED
@@ -1,48 +1,19 @@
1
- import os, io, sys, ast, ctypes, re, ast, sqlite3
1
+ import os, io, sys, ast, ctypes, ast, sqlite3, requests, time, traceback
2
+ import traceback
2
3
  import tkinter as tk
3
4
  from tkinter import ttk
5
+ import matplotlib
6
+ import matplotlib.pyplot as plt
7
+ matplotlib.use('Agg')
8
+ from huggingface_hub import list_repo_files
4
9
 
5
10
  from . gui_core import initiate_root
6
- from .gui_elements import spacrLabel, spacrCheckbutton, AnnotateApp, spacrEntry, spacrCheck, spacrCombo, set_default_font
11
+ from .gui_elements import AnnotateApp, spacrEntry, spacrCheck, spacrCombo, set_default_font
7
12
 
8
13
  try:
9
14
  ctypes.windll.shcore.SetProcessDpiAwareness(True)
10
15
  except AttributeError:
11
16
  pass
12
-
13
- def proceed_with_app_v1(root, app_name, app_func):
14
- from .gui import gui_app
15
-
16
- # Clear the current content frame
17
- if hasattr(root, 'content_frame'):
18
- for widget in root.content_frame.winfo_children():
19
- try:
20
- widget.destroy()
21
- except tk.TclError as e:
22
- print(f"Error destroying widget: {e}")
23
- else:
24
- root.content_frame = tk.Frame(root)
25
- root.content_frame.grid(row=1, column=0, sticky="nsew")
26
- root.grid_rowconfigure(1, weight=1)
27
- root.grid_columnconfigure(0, weight=1)
28
-
29
- # Initialize the new app in the content frame
30
- if app_name == "Mask":
31
- initiate_root(root.content_frame, 'mask')
32
- elif app_name == "Measure":
33
- initiate_root(root.content_frame, 'measure')
34
- elif app_name == "Classify":
35
- initiate_root(root.content_frame, 'classify')
36
- elif app_name == "Sequencing":
37
- initiate_root(root.content_frame, 'sequencing')
38
- elif app_name == "Umap":
39
- initiate_root(root.content_frame, 'umap')
40
- elif app_name == "Annotate":
41
- initiate_root(root.content_frame, 'annotate')
42
- elif app_name == "Make Masks":
43
- initiate_root(root.content_frame, 'make_masks')
44
- else:
45
- raise ValueError(f"Invalid app name: {app_name}")
46
17
 
47
18
  def proceed_with_app(root, app_name, app_func):
48
19
  # Clear the current content frame
@@ -93,19 +64,25 @@ def parse_list(value):
93
64
 
94
65
  # Usage example in your create_input_field function
95
66
  def create_input_field(frame, label_text, row, var_type='entry', options=None, default_value=None):
67
+ from .gui_elements import set_dark_style
96
68
  label_column = 0
97
69
  widget_column = 1
98
70
 
71
+ style_out = set_dark_style(ttk.Style())
72
+
73
+ # Replace underscores with spaces and capitalize the first letter
74
+ label_text = label_text.replace('_', ' ').capitalize()
75
+
99
76
  # Configure the column widths
100
77
  frame.grid_columnconfigure(label_column, weight=0) # Allow the label column to expand
101
78
  frame.grid_columnconfigure(widget_column, weight=1) # Allow the widget column to expand
102
79
 
103
- # Right-align the label text and the label itself
104
- label = ttk.Label(frame, text=label_text, background="black", foreground="white", anchor='e', justify='right')
105
- label.grid(column=label_column, row=row, sticky=tk.E, padx=(5, 2), pady=5) # Align label to the right
80
+ # Create and configure the label
81
+ label = ttk.Label(frame, text=label_text, background=style_out['bg_color'], foreground=style_out['fg_color'], font=(style_out['font_family'], style_out['font_size']), anchor='e', justify='right')
82
+ label.grid(column=label_column, row=row, sticky=tk.E, padx=(5, 2), pady=5)
106
83
 
107
84
  if var_type == 'entry':
108
- var = tk.StringVar(value=default_value) # Set default value
85
+ var = tk.StringVar(value=default_value)
109
86
  entry = spacrEntry(frame, textvariable=var, outline=False)
110
87
  entry.grid(column=widget_column, row=row, sticky=tk.W, padx=(2, 5), pady=5) # Align widget to the left
111
88
  return (label, entry, var) # Return both the label and the entry, and the variable
@@ -157,23 +134,6 @@ def main_thread_update_function(root, q, fig_queue, canvas_widget):
157
134
  #ansi_escape_pattern = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
158
135
  while not q.empty():
159
136
  message = q.get_nowait()
160
- #clean_message = ansi_escape_pattern.sub('', message)
161
- #if clean_message.startswith("Progress"):
162
- # progress_label.config(text=clean_message)
163
- #if clean_message.startswith("\rProgress"):
164
- # progress_label.config(text=clean_message)
165
- #elif clean_message.startswith("Successfully"):
166
- # progress_label.config(text=clean_message)
167
- #elif clean_message.startswith("Processing"):
168
- # progress_label.config(text=clean_message)
169
- #elif clean_message.startswith("scale"):
170
- # pass
171
- #elif clean_message.startswith("plot_cropped_arrays"):
172
- # pass
173
- #elif clean_message == "" or clean_message == "\r" or clean_message.strip() == "":
174
- # pass
175
- #else:
176
- # print(clean_message)
177
137
  except Exception as e:
178
138
  print(f"Error updating GUI canvas: {e}")
179
139
  finally:
@@ -352,11 +312,313 @@ def annotate_with_image_refs(settings, root, shutdown_callback):
352
312
  def set_element_size(widget):
353
313
  screen_width = widget.winfo_screenwidth()
354
314
  screen_height = widget.winfo_screenheight()
355
- btn_size = screen_width/50
356
- bar_size = screen_width/75
357
-
358
- size_dict = {'btn_size':btn_size,
359
- 'bar_size':bar_size}
315
+ btn_size = screen_width // 40
316
+ bar_size = screen_width // 50
317
+ settings_width = screen_width // 5
318
+ panel_height = screen_height // 12
319
+ panel_width = settings_width
320
+ size_dict = {
321
+ 'btn_size': btn_size,
322
+ 'bar_size': bar_size,
323
+ 'settings_width': settings_width,
324
+ 'panel_width': panel_width,
325
+ 'panel_height': panel_height
326
+ }
360
327
  return size_dict
361
328
 
329
+ def convert_settings_dict_for_gui(settings):
330
+ from torchvision import models as torch_models
331
+ torchvision_models = [name for name, obj in torch_models.__dict__.items() if callable(obj)]
332
+ chans = ['0', '1', '2', '3', '4', '5', '6', '7', '8', None]
333
+ chans_v2 = [0, 1, 2, 3, None]
334
+ variables = {}
335
+ special_cases = {
336
+ 'metadata_type': ('combo', ['cellvoyager', 'cq1', 'nikon', 'zeis', 'custom'], 'cellvoyager'),
337
+ 'channels': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
338
+ 'channel_dims': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
339
+ 'cell_mask_dim': ('combo', chans, None),
340
+ 'cell_chann_dim': ('combo', chans, None),
341
+ 'nucleus_mask_dim': ('combo', chans, None),
342
+ 'nucleus_chann_dim': ('combo', chans, None),
343
+ 'pathogen_mask_dim': ('combo', chans, None),
344
+ 'pathogen_chann_dim': ('combo', chans, None),
345
+ 'crop_mode': ('combo', ['cell', 'nucleus', 'pathogen', '[cell, nucleus, pathogen]', '[cell,nucleus, pathogen]'], ['cell']),
346
+ 'magnification': ('combo', [20, 40, 60], 20),
347
+ 'nucleus_channel': ('combo', chans_v2, None),
348
+ 'cell_channel': ('combo', chans_v2, None),
349
+ 'channel_of_interest': ('combo', chans_v2, None),
350
+ 'pathogen_channel': ('combo', chans_v2, None),
351
+ 'timelapse_mode': ('combo', ['trackpy', 'btrack'], 'trackpy'),
352
+ 'train_mode': ('combo', ['erm', 'irm'], 'erm'),
353
+ 'clustering': ('combo', ['dbscan', 'kmean'], 'dbscan'),
354
+ 'reduction_method': ('combo', ['umap', 'tsne'], 'umap'),
355
+ 'model_name': ('combo', ['cyto', 'cyto_2', 'cyto_3', 'nuclei'], 'cyto'),
356
+ 'regression_type': ('combo', ['ols','gls','wls','rlm','glm','mixed','quantile','logit','probit','poisson','lasso','ridge'], 'ols'),
357
+ 'timelapse_objects': ('combo', ['cell', 'nucleus', 'pathogen', 'cytoplasm', None], None),
358
+ 'model_type': ('combo', torchvision_models, 'resnet50'),
359
+ 'optimizer_type': ('combo', ['adamw', 'adam'], 'adamw'),
360
+ 'schedule': ('combo', ['reduce_lr_on_plateau', 'step_lr'], 'reduce_lr_on_plateau'),
361
+ 'loss_type': ('combo', ['focal_loss', 'binary_cross_entropy_with_logits'], 'focal_loss'),
362
+ 'normalize_by': ('combo', ['fov', 'png'], 'png'),
363
+ 'agg_type': ('combo', ['mean', 'median'], 'mean'),
364
+ 'grouping': ('combo', ['mean', 'median'], 'mean'),
365
+ 'min_max': ('combo', ['allq', 'all'], 'allq'),
366
+ 'transform': ('combo', ['log', 'sqrt', 'square', None], None)
367
+ }
368
+
369
+ for key, value in settings.items():
370
+ if key in special_cases:
371
+ variables[key] = special_cases[key]
372
+ elif isinstance(value, bool):
373
+ variables[key] = ('check', None, value)
374
+ elif isinstance(value, int) or isinstance(value, float):
375
+ variables[key] = ('entry', None, value)
376
+ elif isinstance(value, str):
377
+ variables[key] = ('entry', None, value)
378
+ elif value is None:
379
+ variables[key] = ('entry', None, value)
380
+ elif isinstance(value, list):
381
+ variables[key] = ('entry', None, str(value))
382
+ else:
383
+ variables[key] = ('entry', None, str(value))
384
+ return variables
362
385
 
386
+ def spacrFigShow(fig_queue=None):
387
+ """
388
+ Replacement for plt.show() that queues figures instead of displaying them.
389
+ """
390
+ fig = plt.gcf()
391
+ if fig_queue:
392
+ fig_queue.put(fig)
393
+ else:
394
+ fig.show()
395
+ plt.close(fig)
396
+
397
+ def function_gui_wrapper(function=None, settings={}, q=None, fig_queue=None, imports=1):
398
+
399
+ """
400
+ Wraps the run_multiple_simulations function to integrate with GUI processes.
401
+
402
+ Parameters:
403
+ - settings: dict, The settings for the run_multiple_simulations function.
404
+ - q: multiprocessing.Queue, Queue for logging messages to the GUI.
405
+ - fig_queue: multiprocessing.Queue, Queue for sending figures to the GUI.
406
+ """
407
+
408
+ # Temporarily override plt.show
409
+ original_show = plt.show
410
+ plt.show = lambda: spacrFigShow(fig_queue)
411
+
412
+ try:
413
+ if imports == 1:
414
+ function(settings=settings)
415
+ elif imports == 2:
416
+ function(src=settings['src'], settings=settings)
417
+ except Exception as e:
418
+ # Send the error message to the GUI via the queue
419
+ errorMessage = f"Error during processing: {e}"
420
+ q.put(errorMessage)
421
+ traceback.print_exc()
422
+ finally:
423
+ # Restore the original plt.show function
424
+ plt.show = original_show
425
+
426
+ def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
427
+ from .gui_utils import process_stdout_stderr
428
+ 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
429
+ from .io import generate_cellpose_train_test
430
+ from .measure import measure_crop
431
+ from .sim import run_multiple_simulations
432
+ from .deep_spacr import train_test_model
433
+ from .sequencing import analyze_reads, map_barcodes_folder, perform_regression
434
+ process_stdout_stderr(q)
435
+
436
+ print(f'run_function_gui settings_type: {settings_type}')
437
+
438
+ if settings_type == 'mask':
439
+ function = preprocess_generate_masks
440
+ imports = 2
441
+ elif settings_type == 'measure':
442
+ function = measure_crop
443
+ imports = 1
444
+ elif settings_type == 'simulation':
445
+ function = run_multiple_simulations
446
+ imports = 1
447
+ elif settings_type == 'sequencing':
448
+ function = analyze_reads
449
+ imports = 1
450
+ elif settings_type == 'classify':
451
+ function = train_test_model
452
+ imports = 2
453
+ elif settings_type == 'train_cellpose':
454
+ function = train_cellpose
455
+ imports = 1
456
+ elif settings_type == 'ml_analyze':
457
+ function = generate_ml_scores
458
+ imports = 2
459
+ elif settings_type == 'cellpose_masks':
460
+ function = identify_masks_finetune
461
+ imports = 1
462
+ elif settings_type == 'cellpose_all':
463
+ function = check_cellpose_models
464
+ imports = 1
465
+ elif settings_type == 'map_barcodes':
466
+ function = map_barcodes_folder
467
+ imports = 2
468
+ elif settings_type == 'regression':
469
+ function = perform_regression
470
+ imports = 2
471
+ elif settings_type == 'recruitment':
472
+ function = analyze_recruitment
473
+ imports = 2
474
+ else:
475
+ raise ValueError(f"Invalid settings type: {settings_type}")
476
+ try:
477
+ function_gui_wrapper(function, settings, q, fig_queue, imports)
478
+ except Exception as e:
479
+ q.put(f"Error during processing: {e}")
480
+ traceback.print_exc()
481
+ finally:
482
+ stop_requested.value = 1
483
+
484
+ def hide_all_settings(vars_dict, categories):
485
+ """
486
+ Function to initially hide all settings in the GUI.
487
+
488
+ Parameters:
489
+ - categories: dict, The categories of settings with their corresponding settings.
490
+ - vars_dict: dict, The dictionary containing the settings and their corresponding widgets.
491
+ """
492
+
493
+ if categories is None:
494
+ from .settings import categories
495
+
496
+ for category, settings in categories.items():
497
+ if any(setting in vars_dict for setting in settings):
498
+ vars_dict[category] = (None, None, tk.IntVar(value=0))
499
+
500
+ # Initially hide all settings
501
+ for setting in settings:
502
+ if setting in vars_dict:
503
+ label, widget, _ = vars_dict[setting]
504
+ label.grid_remove()
505
+ widget.grid_remove()
506
+ return vars_dict
507
+
508
+ def setup_frame(parent_frame):
509
+ from .gui_elements import set_dark_style, set_default_font
510
+
511
+ style = ttk.Style(parent_frame)
512
+ size_dict = set_element_size(parent_frame)
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'])
518
+
519
+ parent_frame.grid_rowconfigure(0, weight=1)
520
+ parent_frame.grid_rowconfigure(1, weight=0)
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")
527
+
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)
536
+
537
+ set_dark_style(style, parent_frame, [settings_container, vertical_container, horizontal_container])
538
+
539
+ size = style_out['font_size'] - 2
540
+
541
+ set_default_font(parent_frame, font_name=style_out['font_family'], size=size)
542
+
543
+ return parent_frame, vertical_container, horizontal_container, settings_container
544
+
545
+ def download_hug_dataset(q, vars_dict):
546
+ dataset_repo_id = "einarolafsson/toxo_mito"
547
+ settings_repo_id = "einarolafsson/spacr_settings"
548
+ dataset_subfolder = "plate1"
549
+ local_dir = os.path.join(os.path.expanduser("~"), "datasets")
550
+
551
+ # Download the dataset
552
+ try:
553
+ dataset_path = download_dataset(q, dataset_repo_id, dataset_subfolder, local_dir)
554
+ if 'src' in vars_dict:
555
+ vars_dict['src'][2].set(dataset_path)
556
+ q.put(f"Set source path to: {vars_dict['src'][2].get()}\n")
557
+ q.put(f"Dataset downloaded to: {dataset_path}\n")
558
+ except Exception as e:
559
+ q.put(f"Failed to download dataset: {e}\n")
560
+
561
+ # Download the settings files
562
+ try:
563
+ settings_path = download_dataset(q, settings_repo_id, "", local_dir)
564
+ q.put(f"Settings downloaded to: {settings_path}\n")
565
+ except Exception as e:
566
+ q.put(f"Failed to download settings: {e}\n")
567
+
568
+ def download_dataset(q, repo_id, subfolder, local_dir=None, retries=5, delay=5):
569
+ """
570
+ Downloads a dataset or settings files from Hugging Face and returns the local path.
571
+
572
+ Args:
573
+ repo_id (str): The repository ID (e.g., 'einarolafsson/toxo_mito' or 'einarolafsson/spacr_settings').
574
+ subfolder (str): The subfolder path within the repository (e.g., 'plate1' or the settings subfolder).
575
+ local_dir (str): The local directory where the files will be saved. Defaults to the user's home directory.
576
+ retries (int): Number of retry attempts in case of failure.
577
+ delay (int): Delay in seconds between retries.
578
+
579
+ Returns:
580
+ str: The local path to the downloaded files.
581
+ """
582
+ if local_dir is None:
583
+ local_dir = os.path.join(os.path.expanduser("~"), "datasets")
584
+
585
+ local_subfolder_dir = os.path.join(local_dir, subfolder if subfolder else "settings")
586
+ if not os.path.exists(local_subfolder_dir):
587
+ os.makedirs(local_subfolder_dir)
588
+ elif len(os.listdir(local_subfolder_dir)) > 0:
589
+ q.put(f"Files already downloaded to: {local_subfolder_dir}")
590
+ return local_subfolder_dir
591
+
592
+ attempt = 0
593
+ while attempt < retries:
594
+ try:
595
+ files = list_repo_files(repo_id, repo_type="dataset")
596
+ subfolder_files = [file for file in files if file.startswith(subfolder) or (subfolder == "" and file.endswith('.csv'))]
597
+
598
+ for file_name in subfolder_files:
599
+ for download_attempt in range(retries):
600
+ try:
601
+ url = f"https://huggingface.co/datasets/{repo_id}/resolve/main/{file_name}?download=true"
602
+ response = requests.get(url, stream=True)
603
+ response.raise_for_status()
604
+
605
+ local_file_path = os.path.join(local_subfolder_dir, os.path.basename(file_name))
606
+ with open(local_file_path, 'wb') as file:
607
+ for chunk in response.iter_content(chunk_size=8192):
608
+ file.write(chunk)
609
+ q.put(f"Downloaded file: {file_name}")
610
+ break
611
+ except (requests.HTTPError, requests.Timeout) as e:
612
+ q.put(f"Error downloading {file_name}: {e}. Retrying in {delay} seconds...")
613
+ time.sleep(delay)
614
+ else:
615
+ raise Exception(f"Failed to download {file_name} after multiple attempts.")
616
+
617
+ return local_subfolder_dir
618
+
619
+ except (requests.HTTPError, requests.Timeout) as e:
620
+ q.put(f"Error downloading files: {e}. Retrying in {delay} seconds...")
621
+ attempt += 1
622
+ time.sleep(delay)
623
+
624
+ raise Exception("Failed to download files after multiple attempts.")
spacr/io.py CHANGED
@@ -588,20 +588,21 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
588
588
  regular_expression = re.compile(regex)
589
589
  images_by_key = defaultdict(list)
590
590
  stack_path = os.path.join(src, 'stack')
591
+ files_processed = 0
591
592
  if not os.path.exists(stack_path) or (os.path.isdir(stack_path) and len(os.listdir(stack_path)) == 0):
592
593
  all_filenames = [filename for filename in os.listdir(src) if filename.endswith(img_format)]
593
- print(f'All_files:{len(all_filenames)} in {src}')
594
+ print(f'All_files: {len(all_filenames)} in {src}')
594
595
  time_ls = []
595
- processed = 0
596
- for i in range(0, len(all_filenames), batch_size):
596
+
597
+ for idx in range(0, len(all_filenames), batch_size):
597
598
  start = time.time()
598
- batch_filenames = all_filenames[i:i+batch_size]
599
- processed += len(batch_filenames)
599
+ batch_filenames = all_filenames[idx:idx+batch_size]
600
+ files_processed = 0
600
601
  for filename in batch_filenames:
601
602
  images_by_key = _extract_filename_metadata(batch_filenames, src, images_by_key, regular_expression, metadata_type, pick_slice, skip_mode)
602
-
603
+
603
604
  if pick_slice:
604
- for key in images_by_key:
605
+ for i, key in enumerate(images_by_key):
605
606
  plate, well, field, channel, mode = key
606
607
  max_intensity_slice = max(images_by_key[key], key=lambda x: np.percentile(x, 90))
607
608
  mip_image = Image.fromarray(max_intensity_slice)
@@ -609,21 +610,19 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
609
610
  os.makedirs(output_dir, exist_ok=True)
610
611
  output_filename = f'{plate}_{well}_{field}.tif'
611
612
  output_path = os.path.join(output_dir, output_filename)
612
-
613
- if os.path.exists(output_path):
614
- print(f'WARNING: A file with the same name already exists at location {output_filename}')
615
- else:
616
- mip_image.save(output_path)
617
-
613
+ files_processed += 1
618
614
  stop = time.time()
619
615
  duration = stop - start
620
616
  time_ls.append(duration)
621
- files_processed = processed
622
617
  files_to_process = len(all_filenames)
623
618
  print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type='Preprocessing filenames')
624
619
 
620
+ if os.path.exists(output_path):
621
+ print(f'WARNING: A file with the same name already exists at location {output_filename}')
622
+ else:
623
+ mip_image.save(output_path)
625
624
  else:
626
- for key, images in images_by_key.items():
625
+ for i, (key, images) in enumerate(images_by_key.items()):
627
626
  mip = np.max(np.stack(images), axis=0)
628
627
  mip_image = Image.fromarray(mip)
629
628
  plate, well, field, channel = key[:4]
@@ -631,18 +630,17 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
631
630
  os.makedirs(output_dir, exist_ok=True)
632
631
  output_filename = f'{plate}_{well}_{field}.tif'
633
632
  output_path = os.path.join(output_dir, output_filename)
634
-
635
- if os.path.exists(output_path):
636
- print(f'WARNING: A file with the same name already exists at location {output_filename}')
637
- else:
638
- mip_image.save(output_path)
633
+ files_processed += 1
639
634
  stop = time.time()
640
635
  duration = stop - start
641
636
  time_ls.append(duration)
642
- files_processed = processed
643
637
  files_to_process = len(all_filenames)
644
638
  print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type='Preprocessing filenames')
645
639
 
640
+ if os.path.exists(output_path):
641
+ print(f'WARNING: A file with the same name already exists at location {output_filename}')
642
+ else:
643
+ mip_image.save(output_path)
646
644
  images_by_key.clear()
647
645
 
648
646
  # Move original images to a new directory
@@ -656,6 +654,7 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
656
654
  print(f'WARNING: A file with the same name already exists at location {move}')
657
655
  else:
658
656
  shutil.move(os.path.join(src, filename), move)
657
+ files_processed = 0
659
658
  return
660
659
 
661
660
  def _merge_file(chan_dirs, stack_dir, file_name):
@@ -975,7 +974,7 @@ def _concatenate_channel(src, channels, randomize=True, timelapse=False, batch_s
975
974
  time_ls.append(duration)
976
975
  files_processed = i+1
977
976
  files_to_process = time_stack_path_lists
978
- 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")
979
978
  stack = np.stack(stack_region)
980
979
  save_loc = os.path.join(channel_stack_loc, f'{name}.npz')
981
980
  np.savez(save_loc, data=stack, filenames=filenames_region)
@@ -1006,7 +1005,7 @@ def _concatenate_channel(src, channels, randomize=True, timelapse=False, batch_s
1006
1005
  time_ls.append(duration)
1007
1006
  files_processed = i+1
1008
1007
  files_to_process = nr_files
1009
- 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")
1010
1009
  if (i+1) % batch_size == 0 or i+1 == nr_files:
1011
1010
  unique_shapes = {arr.shape[:-1] for arr in stack_ls}
1012
1011
  if len(unique_shapes) > 1:
@@ -1104,7 +1103,7 @@ def _normalize_img_batch(stack, channels, save_dtype, settings):
1104
1103
  time_ls.append(duration)
1105
1104
  files_processed = i+1
1106
1105
  files_to_process = len(channels)
1107
- 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")
1108
1107
 
1109
1108
  return normalized_stack.astype(save_dtype)
1110
1109
 
@@ -1151,7 +1150,6 @@ def concatenate_and_normalize(src, channels, save_dtype=np.float32, settings={})
1151
1150
  parts = file.split('_')
1152
1151
  name = parts[0] + '_' + parts[1] + '_' + parts[2]
1153
1152
  array = np.load(path)
1154
- #array = np.take(array, channels, axis=2)
1155
1153
  stack_region.append(array)
1156
1154
  filenames_region.append(os.path.basename(path))
1157
1155
  stop = time.time()
@@ -1159,7 +1157,7 @@ def concatenate_and_normalize(src, channels, save_dtype=np.float32, settings={})
1159
1157
  time_ls.append(duration)
1160
1158
  files_processed = i+1
1161
1159
  files_to_process = len(time_stack_path_lists)
1162
- 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")
1163
1161
  stack = np.stack(stack_region)
1164
1162
 
1165
1163
  normalized_stack = _normalize_img_batch(stack=stack,
@@ -1188,18 +1186,18 @@ def concatenate_and_normalize(src, channels, save_dtype=np.float32, settings={})
1188
1186
  stack_ls = []
1189
1187
  filenames_batch = []
1190
1188
  time_ls = []
1189
+ files_processed = 0
1191
1190
  for i, path in enumerate(paths):
1192
1191
  start = time.time()
1193
1192
  array = np.load(path)
1194
- #array = np.take(array, channels, axis=2)
1195
1193
  stack_ls.append(array)
1196
1194
  filenames_batch.append(os.path.basename(path))
1197
1195
  stop = time.time()
1198
1196
  duration = stop - start
1199
1197
  time_ls.append(duration)
1200
- files_processed = i+1
1198
+ files_processed += 1
1201
1199
  files_to_process = nr_files
1202
- print_progress(files_processed, files_to_process, n_jobs=1, time_ls=None, batch_size=None, operation_type="Concatinating")
1200
+ print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Concatinating")
1203
1201
 
1204
1202
  if (i + 1) % settings['batch_size'] == 0 or i + 1 == nr_files:
1205
1203
  unique_shapes = {arr.shape[:-1] for arr in stack_ls}
@@ -1350,12 +1348,12 @@ def _normalize_stack(src, backgrounds=[100, 100, 100], remove_backgrounds=[False
1350
1348
  average_time = np.mean(time_ls) if len(time_ls) > 0 else 0
1351
1349
  print(f'channels:{chan_index}/{stack.shape[-1] - 1}, arrays:{array_index + 1}/{single_channel.shape[0]}, Signal:{upper:.1f}, noise:{lower:.1f}, Signal-to-noise:{average_stnr:.1f}, Time/channel:{average_time:.2f}sec')
1352
1350
 
1353
- stop = time.time()
1354
- duration = stop - start
1355
- time_ls.append(duration)
1356
- files_processed = file_index + 1
1357
- files_to_process = len(paths)
1358
- print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Normalizing")
1351
+ #stop = time.time()
1352
+ #duration = stop - start
1353
+ #time_ls.append(duration)
1354
+ #files_processed = file_index + 1
1355
+ #files_to_process = len(paths)
1356
+ #print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Normalizing")
1359
1357
 
1360
1358
  normalized_stack[:, :, :, channel] = arr_2d_normalized
1361
1359
 
@@ -1405,12 +1403,12 @@ def _normalize_timelapse(src, lower_percentile=2, save_dtype=np.float32):
1405
1403
 
1406
1404
  print(f'channels:{chan_index+1}/{stack.shape[-1]}, arrays:{array_index+1}/{single_channel.shape[0]}', end='\r')
1407
1405
 
1408
- stop = time.time()
1409
- duration = stop - start
1410
- time_ls.append(duration)
1411
- files_processed = file_index+1
1412
- files_to_process = len(paths)
1413
- print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Normalizing")
1406
+ #stop = time.time()
1407
+ #duration = stop - start
1408
+ #time_ls.append(duration)
1409
+ #files_processed = file_index+1
1410
+ #files_to_process = len(paths)
1411
+ #print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Normalizing")
1414
1412
 
1415
1413
  save_loc = os.path.join(output_fldr, f'{name}_norm_timelapse.npz')
1416
1414
  np.savez(save_loc, data=normalized_stack, filenames=filenames)
@@ -1620,8 +1618,8 @@ def preprocess_img_data(settings):
1620
1618
  save_dtype=np.float32,
1621
1619
  settings=settings)
1622
1620
 
1623
- if plot:
1624
- _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)
1625
1623
 
1626
1624
  return settings, src
1627
1625
 
@@ -1951,7 +1949,7 @@ def _load_and_concatenate_arrays(src, channels, cell_chann_dim, nucleus_chann_di
1951
1949
  all_imgs = len(os.listdir(reference_folder))
1952
1950
  time_ls = []
1953
1951
  # Iterate through each file in the reference folder
1954
- for filename in os.listdir(reference_folder):
1952
+ for idx, filename in enumerate(os.listdir(reference_folder)):
1955
1953
  start = time.time()
1956
1954
  stack_ls = []
1957
1955
  if filename.endswith('.npy'):
@@ -2012,7 +2010,7 @@ def _load_and_concatenate_arrays(src, channels, cell_chann_dim, nucleus_chann_di
2012
2010
  stop = time.time()
2013
2011
  duration = stop - start
2014
2012
  time_ls.append(duration)
2015
- files_processed = count
2013
+ files_processed = idx+1
2016
2014
  files_to_process = all_imgs
2017
2015
  print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=None, operation_type="Merging Arrays")
2018
2016
 
@@ -2550,7 +2548,6 @@ def _read_mask(mask_path):
2550
2548
  mask = img_as_uint(mask)
2551
2549
  return mask
2552
2550
 
2553
-
2554
2551
  def convert_numpy_to_tiff(folder_path, limit=None):
2555
2552
  """
2556
2553
  Converts all numpy files in a folder to TIFF format and saves them in a subdirectory 'tiff'.