spacr 0.1.85__tar.gz → 0.2.1__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 (77) hide show
  1. {spacr-0.1.85/spacr.egg-info → spacr-0.2.1}/PKG-INFO +1 -1
  2. {spacr-0.1.85 → spacr-0.2.1}/setup.py +2 -2
  3. {spacr-0.1.85 → spacr-0.2.1}/spacr/__init__.py +6 -2
  4. {spacr-0.1.85 → spacr-0.2.1}/spacr/app_annotate.py +6 -5
  5. {spacr-0.1.85 → spacr-0.2.1}/spacr/app_make_masks.py +8 -15
  6. {spacr-0.1.85 → spacr-0.2.1}/spacr/core.py +1 -1
  7. spacr-0.2.1/spacr/gui.py +157 -0
  8. {spacr-0.1.85 → spacr-0.2.1}/spacr/gui_core.py +43 -16
  9. {spacr-0.1.85 → spacr-0.2.1}/spacr/gui_elements.py +116 -25
  10. {spacr-0.1.85 → spacr-0.2.1}/spacr/gui_utils.py +3 -3
  11. spacr-0.2.1/spacr/resources/icons/abort.png +0 -0
  12. spacr-0.2.1/spacr/resources/icons/annotate.png +0 -0
  13. spacr-0.2.1/spacr/resources/icons/cellpose_masks.png +0 -0
  14. spacr-0.2.1/spacr/resources/icons/classify.png +0 -0
  15. spacr-0.2.1/spacr/resources/icons/default.png +0 -0
  16. spacr-0.2.1/spacr/resources/icons/download.png +0 -0
  17. spacr-0.2.1/spacr/resources/icons/logo_spacr.png +0 -0
  18. spacr-0.2.1/spacr/resources/icons/make_masks.png +0 -0
  19. spacr-0.2.1/spacr/resources/icons/map_barcodes.png +0 -0
  20. spacr-0.2.1/spacr/resources/icons/mask.png +0 -0
  21. spacr-0.2.1/spacr/resources/icons/measure.png +0 -0
  22. spacr-0.2.1/spacr/resources/icons/regression.png +0 -0
  23. spacr-0.2.1/spacr/resources/icons/run.png +0 -0
  24. spacr-0.2.1/spacr/resources/icons/sequencing.png +0 -0
  25. spacr-0.2.1/spacr/resources/icons/settings.png +0 -0
  26. spacr-0.2.1/spacr/resources/icons/train_cellpose.png +0 -0
  27. spacr-0.2.1/spacr/resources/icons/umap.png +0 -0
  28. {spacr-0.1.85 → spacr-0.2.1}/spacr/settings.py +12 -12
  29. {spacr-0.1.85 → spacr-0.2.1/spacr.egg-info}/PKG-INFO +1 -1
  30. {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/SOURCES.txt +20 -3
  31. spacr-0.1.85/spacr/gui.py +0 -195
  32. {spacr-0.1.85 → spacr-0.2.1}/LICENSE +0 -0
  33. {spacr-0.1.85 → spacr-0.2.1}/MANIFEST.in +0 -0
  34. {spacr-0.1.85 → spacr-0.2.1}/README.rst +0 -0
  35. {spacr-0.1.85 → spacr-0.2.1}/setup.cfg +0 -0
  36. {spacr-0.1.85 → spacr-0.2.1}/spacr/__main__.py +0 -0
  37. {spacr-0.1.85 → spacr-0.2.1}/spacr/app_classify.py +0 -0
  38. {spacr-0.1.85 → spacr-0.2.1}/spacr/app_mask.py +0 -0
  39. {spacr-0.1.85 → spacr-0.2.1}/spacr/app_measure.py +0 -0
  40. {spacr-0.1.85 → spacr-0.2.1}/spacr/app_sequencing.py +0 -0
  41. {spacr-0.1.85 → spacr-0.2.1}/spacr/app_umap.py +0 -0
  42. {spacr-0.1.85 → spacr-0.2.1}/spacr/chris.py +0 -0
  43. {spacr-0.1.85 → spacr-0.2.1}/spacr/deep_spacr.py +0 -0
  44. {spacr-0.1.85 → spacr-0.2.1}/spacr/graph_learning.py +0 -0
  45. {spacr-0.1.85 → spacr-0.2.1}/spacr/io.py +0 -0
  46. {spacr-0.1.85 → spacr-0.2.1}/spacr/logger.py +0 -0
  47. {spacr-0.1.85 → spacr-0.2.1}/spacr/measure.py +0 -0
  48. {spacr-0.1.85 → spacr-0.2.1}/spacr/plot.py +0 -0
  49. {spacr-0.1.85/spacr → spacr-0.2.1/spacr/resources}/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model +0 -0
  50. {spacr-0.1.85/spacr → spacr-0.2.1/spacr/resources}/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model_settings.csv +0 -0
  51. {spacr-0.1.85/spacr → spacr-0.2.1/spacr/resources}/models/cp/toxo_pv_lumen.CP_model +0 -0
  52. {spacr-0.1.85 → spacr-0.2.1}/spacr/sequencing.py +0 -0
  53. {spacr-0.1.85 → spacr-0.2.1}/spacr/sim.py +0 -0
  54. {spacr-0.1.85 → spacr-0.2.1}/spacr/sim_app.py +0 -0
  55. {spacr-0.1.85 → spacr-0.2.1}/spacr/timelapse.py +0 -0
  56. {spacr-0.1.85 → spacr-0.2.1}/spacr/utils.py +0 -0
  57. {spacr-0.1.85 → spacr-0.2.1}/spacr/version.py +0 -0
  58. {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/dependency_links.txt +0 -0
  59. {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/entry_points.txt +0 -0
  60. {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/requires.txt +0 -0
  61. {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/top_level.txt +0 -0
  62. {spacr-0.1.85 → spacr-0.2.1}/tests/test_annotate_app.py +0 -0
  63. {spacr-0.1.85 → spacr-0.2.1}/tests/test_core.py +0 -0
  64. {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_classify_app.py +0 -0
  65. {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_mask_app.py +0 -0
  66. {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_measure_app.py +0 -0
  67. {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_sim_app.py +0 -0
  68. {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_utils.py +0 -0
  69. {spacr-0.1.85 → spacr-0.2.1}/tests/test_io.py +0 -0
  70. {spacr-0.1.85 → spacr-0.2.1}/tests/test_mask_app.py +0 -0
  71. {spacr-0.1.85 → spacr-0.2.1}/tests/test_measure.py +0 -0
  72. {spacr-0.1.85 → spacr-0.2.1}/tests/test_plot.py +0 -0
  73. {spacr-0.1.85 → spacr-0.2.1}/tests/test_sim.py +0 -0
  74. {spacr-0.1.85 → spacr-0.2.1}/tests/test_timelapse.py +0 -0
  75. {spacr-0.1.85 → spacr-0.2.1}/tests/test_train.py +0 -0
  76. {spacr-0.1.85 → spacr-0.2.1}/tests/test_umap.py +0 -0
  77. {spacr-0.1.85 → spacr-0.2.1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spacr
3
- Version: 0.1.85
3
+ Version: 0.2.1
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.1.85",
53
+ version="0.2.1",
54
54
  author="Einar Birnir Olafsson",
55
55
  author_email="olafsson@med.umich.com",
56
56
  description="Spatial phenotype analysis of crisp screens (SpaCr)",
@@ -58,7 +58,7 @@ setup(
58
58
  url="https://github.com/EinarOlafsson/spacr",
59
59
  packages=find_packages(exclude=["tests.*", "tests"]),
60
60
  include_package_data=True,
61
- package_data={'spacr': ['models/cp/*'],},
61
+ package_data={'spacr': ['resources/models/cp/*', 'resources/icons/*'],},
62
62
  install_requires=dependencies,
63
63
  entry_points={
64
64
  'console_scripts': [
@@ -16,8 +16,8 @@ from . import app_annotate
16
16
  from . import gui_utils
17
17
  from . import gui_elements
18
18
  from . import gui_core
19
- from . import gui_run
20
- from . import gui_wrappers
19
+ from . import gui
20
+ from . import gui
21
21
  from . import app_make_masks
22
22
  from . import app_mask
23
23
  from . import app_measure
@@ -40,6 +40,10 @@ __all__ = [
40
40
  "deep_spacr",
41
41
  "app_annotate",
42
42
  "gui_utils",
43
+ "gui_elements",
44
+ "gui_core",
45
+ "gui",
46
+ "gui",
43
47
  "app_make_masks",
44
48
  "app_mask",
45
49
  "app_measure",
@@ -1,15 +1,16 @@
1
1
  import tkinter as tk
2
+ from tkinter import ttk
2
3
  from .gui import MainApp
4
+ from .gui_elements import set_dark_style
3
5
 
4
6
  def initiate_annotation_app(parent_frame):
5
7
  from .gui_utils import generate_annotate_fields, annotate_app
6
8
  # Set up the settings window
7
9
  settings_window = tk.Toplevel(parent_frame)
8
10
  settings_window.title("Annotation Settings")
9
- settings_window.configure(bg='black') # Set the background color to black
10
-
11
- # Use the existing function to create the settings UI
12
- settings_frame = tk.Frame(settings_window, bg='black') # Set the background color to black
11
+ style_out = set_dark_style(ttk.Style())
12
+ settings_window.configure(bg=style_out['bg_color'])
13
+ settings_frame = tk.Frame(settings_window, bg=style_out['bg_color'])
13
14
  settings_frame.pack(fill=tk.BOTH, expand=True)
14
15
  vars_dict = generate_annotate_fields(settings_frame)
15
16
 
@@ -41,7 +42,7 @@ def initiate_annotation_app(parent_frame):
41
42
  settings_window.destroy()
42
43
  annotate_app(parent_frame, settings)
43
44
 
44
- start_button = tk.Button(settings_window, text="Start Annotation", command=start_annotation_app, bg='black', fg='white')
45
+ start_button = tk.Button(settings_window, text="Start Annotation", command=start_annotation_app, bg=style_out['bg_color'], fg=style_out['bg_color'])
45
46
  start_button.pack(pady=10)
46
47
 
47
48
  def start_annotate_app():
@@ -3,26 +3,22 @@ from tkinter import ttk
3
3
  from .gui import MainApp
4
4
 
5
5
  def initiate_make_mask_app(parent_frame):
6
- from .gui_elements import modify_masks
7
- # Set up the settings window
6
+ from .gui_elements import ModifyMaskApp, set_dark_style
8
7
  settings_window = tk.Toplevel(parent_frame)
9
8
  settings_window.title("Make Masks Settings")
10
- settings_window.configure(bg='black') # Set the background color to black
11
-
12
- # Use the existing function to create the settings UI
13
- settings_frame = tk.Frame(settings_window, bg='black') # Set the background color to black
9
+ style_out = set_dark_style(ttk.Style())
10
+ settings_window.configure(bg=style_out['bg_color'])
11
+ settings_frame = tk.Frame(settings_window, bg=style_out['bg_color'])
14
12
  settings_frame.pack(fill=tk.BOTH, expand=True)
15
13
 
16
14
  vars_dict = {
17
15
  'folder_path': ttk.Entry(settings_frame),
18
16
  'scale_factor': ttk.Entry(settings_frame)
19
17
  }
20
-
21
- # Arrange input fields and labels
22
18
  row = 0
23
19
  for name, entry in vars_dict.items():
24
20
  ttk.Label(settings_frame, text=f"{name.replace('_', ' ').capitalize()}:",
25
- background="black", foreground="white").grid(row=row, column=0)
21
+ background=style_out['bg_color'], foreground=style_out['fg_color']).grid(row=row, column=0)
26
22
  entry.grid(row=row, column=1)
27
23
  row += 1
28
24
 
@@ -32,15 +28,12 @@ def initiate_make_mask_app(parent_frame):
32
28
  try:
33
29
  scale_factor = float(vars_dict['scale_factor'].get())
34
30
  except ValueError:
35
- scale_factor = None # Handle invalid input gracefully
36
-
37
- # Convert empty strings to None
31
+ scale_factor = None
38
32
  folder_path = folder_path if folder_path != '' else None
39
-
40
33
  settings_window.destroy()
41
- modify_masks(parent_frame, folder_path, scale_factor)
34
+ ModifyMaskApp(parent_frame, folder_path, scale_factor)
42
35
 
43
- run_button = tk.Button(settings_window, text="Start Make Masks", command=start_make_mask_app, bg='black', fg='white')
36
+ run_button = tk.Button(settings_window, text="Start Make Masks", command=start_make_mask_app, bg=style_out['bg_color'], fg=style_out['fg_color'])
44
37
  run_button.pack(pady=10)
45
38
 
46
39
  def start_make_mask_app():
@@ -1738,7 +1738,7 @@ def preprocess_generate_masks(src, settings={}):
1738
1738
  if os.path.exists(os.path.join(src,'measurements')):
1739
1739
  _pivot_counts_table(db_path=os.path.join(src,'measurements', 'measurements.db'))
1740
1740
 
1741
- #Concatinate stack with masks
1741
+ #Concatenate stack with masks
1742
1742
  _load_and_concatenate_arrays(src, settings['channels'], settings['cell_channel'], settings['nucleus_channel'], settings['pathogen_channel'])
1743
1743
 
1744
1744
  if settings['plot']:
@@ -0,0 +1,157 @@
1
+ import tkinter as tk
2
+ from tkinter import ttk
3
+ from PIL import Image, ImageTk, ImageDraw
4
+ import os
5
+ from multiprocessing import set_start_method
6
+ from .gui_elements import spacrButton, create_menu_bar, set_dark_style
7
+ from .gui_core import initiate_root
8
+
9
+ class MainApp(tk.Tk):
10
+ def __init__(self, default_app=None):
11
+ super().__init__()
12
+ width = self.winfo_screenwidth()
13
+ height = self.winfo_screenheight()
14
+ self.geometry(f"{width}x{height}")
15
+ self.title("SpaCr GUI Collection")
16
+ self.configure(bg='#333333') # Set window background to dark gray
17
+
18
+ # Initialize style and apply dark style to the main window
19
+ style = ttk.Style()
20
+ self.color_settings = set_dark_style(style, parent_frame=self)
21
+ self.main_buttons = {} # Initialize main_buttons dictionary here
22
+ self.additional_buttons = {} # Initialize additional_buttons dictionary here
23
+
24
+ self.main_gui_apps = {
25
+ "Mask": (lambda frame: initiate_root(frame, 'mask'), "Generate cellpose masks for cells, nuclei and pathogen images."),
26
+ "Measure": (lambda frame: initiate_root(frame, 'measure'), "Measure single object intensity and morphological feature. Crop and save single object image"),
27
+ "Annotate": (lambda frame: initiate_root(frame, 'annotate'), "Annotation single object images on a grid. Annotations are saved to database."),
28
+ "Make Masks": (lambda frame: initiate_root(frame, 'make_masks'), "Adjust pre-existing Cellpose models to your specific dataset for improved performance"),
29
+ "Classify": (lambda frame: initiate_root(frame, 'classify'), "Train Torch Convolutional Neural Networks (CNNs) or Transformers to classify single object images."),
30
+ }
31
+
32
+ self.additional_gui_apps = {
33
+ "Sequencing": (lambda frame: initiate_root(frame, 'sequencing'), "Analyze sequencing data."),
34
+ "Umap": (lambda frame: initiate_root(frame, 'umap'), "Generate UMAP embeddings with datapoints represented as images."),
35
+ "Train Cellpose": (lambda frame: initiate_root(frame, 'train_cellpose'), "Train custom Cellpose models."),
36
+ "ML Analyze": (lambda frame: initiate_root(frame, 'ml_analyze'), "Machine learning analysis of data."),
37
+ "Cellpose Masks": (lambda frame: initiate_root(frame, 'cellpose_masks'), "Generate Cellpose masks."),
38
+ "Cellpose All": (lambda frame: initiate_root(frame, 'cellpose_all'), "Run Cellpose on all images."),
39
+ "Map Barcodes": (lambda frame: initiate_root(frame, 'map_barcodes'), "Map barcodes to data."),
40
+ "Regression": (lambda frame: initiate_root(frame, 'regression'), "Perform regression analysis."),
41
+ "Recruitment": (lambda frame: initiate_root(frame, 'recruitment'), "Analyze recruitment data.")
42
+ }
43
+
44
+ self.selected_app = tk.StringVar()
45
+ self.create_widgets()
46
+
47
+ if default_app in self.main_gui_apps:
48
+ self.load_app(default_app, self.main_gui_apps[default_app][0])
49
+ elif default_app in self.additional_gui_apps:
50
+ self.load_app(default_app, self.additional_gui_apps[default_app][0])
51
+
52
+ def create_widgets(self):
53
+ # Create the menu bar
54
+ create_menu_bar(self)
55
+
56
+ # Create a canvas to hold the selected app and other elements
57
+ self.canvas = tk.Canvas(self, highlightthickness=0)
58
+ self.canvas.grid(row=0, column=0, sticky="nsew")
59
+ self.grid_rowconfigure(0, weight=1)
60
+ self.grid_columnconfigure(0, weight=1)
61
+
62
+ # Create a frame inside the canvas to hold the main content
63
+ self.content_frame = tk.Frame(self.canvas)
64
+ self.content_frame.grid(row=0, column=0, sticky="nsew")
65
+
66
+ # Center the content frame within the canvas
67
+ self.canvas.create_window((self.winfo_screenwidth() // 2, self.winfo_screenheight() // 2), window=self.content_frame, anchor="center")
68
+
69
+ # Apply dark style to canvas and content_frame
70
+ set_dark_style(ttk.Style(), containers=[self.canvas, self.content_frame])
71
+
72
+ # Create startup screen with buttons for each main GUI app and drop-down for additional apps
73
+ self.create_startup_screen()
74
+
75
+ def create_startup_screen(self):
76
+ self.clear_frame(self.content_frame)
77
+
78
+ # Create frames for the grids
79
+ main_buttons_frame = tk.Frame(self.content_frame)
80
+ main_buttons_frame.pack(pady=10)
81
+ set_dark_style(ttk.Style(), containers=[main_buttons_frame])
82
+
83
+ additional_buttons_frame = tk.Frame(self.content_frame)
84
+ additional_buttons_frame.pack(pady=10)
85
+ set_dark_style(ttk.Style(), containers=[additional_buttons_frame])
86
+
87
+ # Create a frame for the description below the icon grids
88
+ description_frame = tk.Frame(self.content_frame, height=70)
89
+ description_frame.pack(fill=tk.X, pady=10)
90
+ description_frame.pack_propagate(False) # Prevent the frame from resizing based on its content
91
+ set_dark_style(ttk.Style(), containers=[description_frame])
92
+
93
+ # Use a Label widget to display descriptions
94
+ self.description_label = tk.Label(description_frame, text="", wraplength=800, justify="center", font=('Helvetica', 12), fg=self.color_settings['fg_color'], bg=self.color_settings['bg_color'])
95
+ self.description_label.pack(fill=tk.BOTH, pady=10)
96
+
97
+ # Load the logo image and place it in the main apps row
98
+ logo_button = spacrButton(main_buttons_frame, text="SpaCr", command=lambda: self.load_app("logo_spacr", initiate_root), icon_name="logo_spacr", size=100, show_text=False)
99
+ logo_button.grid(row=0, column=0, padx=5, pady=5)
100
+ self.main_buttons[logo_button] = "SpaCr: An advanced application suite for cellpose masks, measurements, annotations, and more."
101
+
102
+ # Create icon buttons for the main apps
103
+ for i, (app_name, app_data) in enumerate(self.main_gui_apps.items()):
104
+ app_func, app_desc = app_data
105
+ button = spacrButton(main_buttons_frame, text=app_name, command=lambda app_name=app_name, app_func=app_func: self.load_app(app_name, app_func), icon_name=app_name.lower(), size=100, show_text=False)
106
+ button.grid(row=0, column=i + 1, padx=5, pady=5)
107
+ self.main_buttons[button] = app_desc
108
+
109
+ # Create icon buttons for the additional apps
110
+ for i, (app_name, app_data) in enumerate(self.additional_gui_apps.items()):
111
+ app_func, app_desc = app_data
112
+ button = spacrButton(additional_buttons_frame, text=app_name, command=lambda app_name=app_name, app_func=app_func: self.load_app(app_name, app_func), icon_name=app_name.lower(), size=75, show_text=False)
113
+ button.grid(row=0, column=i, padx=5, pady=5)
114
+ self.additional_buttons[button] = app_desc
115
+
116
+ # Update description initially
117
+ self.update_description()
118
+
119
+ def update_description(self):
120
+ # Check all buttons and update description if any has the active color
121
+ for button, desc in {**self.main_buttons, **self.additional_buttons}.items():
122
+ if button.canvas.itemcget(button.button_bg, "fill") == self.color_settings['active_color']:
123
+ self.show_description(desc)
124
+ return
125
+ self.clear_description()
126
+
127
+ def show_description(self, description):
128
+ if self.description_label.winfo_exists():
129
+ self.description_label.config(text=description)
130
+ self.description_label.update_idletasks() # Ensure the label updates immediately
131
+
132
+ def clear_description(self):
133
+ if self.description_label.winfo_exists():
134
+ self.description_label.config(text="")
135
+ self.description_label.update_idletasks() # Ensure the label updates immediately
136
+
137
+ def load_app(self, app_name, app_func):
138
+ # Clear the current content frame
139
+ self.clear_frame(self.canvas)
140
+
141
+ # Initialize the selected app
142
+ app_frame = tk.Frame(self.canvas)
143
+ app_frame.pack(fill=tk.BOTH, expand=True)
144
+ set_dark_style(ttk.Style(), containers=[app_frame])
145
+ app_func(app_frame)
146
+
147
+ def clear_frame(self, frame):
148
+ for widget in frame.winfo_children():
149
+ widget.destroy()
150
+
151
+ def gui_app():
152
+ app = MainApp()
153
+ app.mainloop()
154
+
155
+ if __name__ == "__main__":
156
+ set_start_method('spawn', force=True)
157
+ gui_app()
@@ -231,25 +231,43 @@ def import_settings(settings_type='mask'):
231
231
  vars_dict = hide_all_settings(vars_dict, categories=None)
232
232
 
233
233
  def convert_settings_dict_for_gui(settings):
234
+ from torchvision import models as torch_models
235
+ torchvision_models = [name for name, obj in torch_models.__dict__.items() if callable(obj)]
236
+ chans = ['0', '1', '2', '3', '4', '5', '6', '7', '8', None]
237
+ chans_v2 = [0, 1, 2, 3, None]
234
238
  variables = {}
235
239
  special_cases = {
236
240
  'metadata_type': ('combo', ['cellvoyager', 'cq1', 'nikon', 'zeis', 'custom'], 'cellvoyager'),
237
241
  'channels': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
238
- 'cell_mask_dim': ('combo', ['0', '1', '2', '3', '4', '5', '6', '7', '8', None], None),
239
- 'nucleus_mask_dim': ('combo', ['0', '1', '2', '3', '4', '5', '6', '7', '8', None], None),
240
- 'pathogen_mask_dim': ('combo', ['0', '1', '2', '3', '4', '5', '6', '7', '8', None], None),
241
- #'crop_mode': ('combo', ['cell', 'nucleus', 'pathogen', '[cell, nucleus, pathogen]', '[cell,nucleus, pathogen]'], ['cell']),
242
+ 'channel_dims': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
243
+ 'cell_mask_dim': ('combo', chans, None),
244
+ 'cell_chann_dim': ('combo', chans, None),
245
+ 'nucleus_mask_dim': ('combo', chans, None),
246
+ 'nucleus_chann_dim': ('combo', chans, None),
247
+ 'pathogen_mask_dim': ('combo', chans, None),
248
+ 'pathogen_chann_dim': ('combo', chans, None),
249
+ 'crop_mode': ('combo', ['cell', 'nucleus', 'pathogen', '[cell, nucleus, pathogen]', '[cell,nucleus, pathogen]'], ['cell']),
242
250
  'magnification': ('combo', [20, 40, 60], 20),
243
- 'nucleus_channel': ('combo', [0, 1, 2, 3, None], None),
244
- 'cell_channel': ('combo', [0, 1, 2, 3, None], None),
245
- 'pathogen_channel': ('combo', [0, 1, 2, 3, None], None),
251
+ 'nucleus_channel': ('combo', chans_v2, None),
252
+ 'cell_channel': ('combo', chans_v2, None),
253
+ 'channel_of_interest': ('combo', chans_v2, None),
254
+ 'pathogen_channel': ('combo', chans_v2, None),
246
255
  'timelapse_mode': ('combo', ['trackpy', 'btrack'], 'trackpy'),
256
+ 'train_mode': ('combo', ['erm', 'irm'], 'erm'),
257
+ 'clustering': ('combo', ['dbscan', 'kmean'], 'dbscan'),
258
+ 'reduction_method': ('combo', ['umap', 'tsne'], 'umap'),
259
+ 'model_name': ('combo', ['cyto', 'cyto_2', 'cyto_3', 'nuclei'], 'cyto'),
260
+ 'regression_type': ('combo', ['ols','gls','wls','rlm','glm','mixed','quantile','logit','probit','poisson','lasso','ridge'], 'ols'),
247
261
  'timelapse_objects': ('combo', ['cell', 'nucleus', 'pathogen', 'cytoplasm', None], None),
248
- 'model_type': ('combo', ['resnet50', 'other_model'], 'resnet50'),
262
+ 'model_type': ('combo', torchvision_models, 'resnet50'),
249
263
  'optimizer_type': ('combo', ['adamw', 'adam'], 'adamw'),
250
264
  'schedule': ('combo', ['reduce_lr_on_plateau', 'step_lr'], 'reduce_lr_on_plateau'),
251
265
  'loss_type': ('combo', ['focal_loss', 'binary_cross_entropy_with_logits'], 'focal_loss'),
252
266
  'normalize_by': ('combo', ['fov', 'png'], 'png'),
267
+ 'agg_type': ('combo', ['mean', 'median'], 'mean'),
268
+ 'grouping': ('combo', ['mean', 'median'], 'mean'),
269
+ 'min_max': ('combo', ['allq', 'all'], 'allq'),
270
+ 'transform': ('combo', ['log', 'sqrt', 'square', None], None)
253
271
  }
254
272
 
255
273
  for key, value in settings.items():
@@ -338,9 +356,10 @@ def setup_plot_section(vertical_container):
338
356
  plot_frame.add(canvas_widget, stretch="always")
339
357
  canvas.draw()
340
358
  canvas.figure = figure
341
- # Set the figure and axes background to black
342
- figure.patch.set_facecolor('black')
343
- plot.set_facecolor('black')
359
+ style_out = set_dark_style(ttk.Style())
360
+
361
+ figure.patch.set_facecolor(style_out['bg_color'])
362
+ plot.set_facecolor(style_out['bg_color'])
344
363
  containers = [plot_frame]
345
364
  widgets = [canvas_widget]
346
365
  style = ttk.Style(vertical_container)
@@ -488,25 +507,25 @@ def setup_button_section(horizontal_container, settings_type='mask', window_dime
488
507
  btn_row = 1
489
508
 
490
509
  if run:
491
- run_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue, settings_type))
510
+ run_button = spacrButton(button_scrollable_frame.scrollable_frame, text="run", command=lambda: start_process(q, fig_queue, settings_type))
492
511
  run_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
493
512
  widgets.append(run_button)
494
513
  btn_row += 1
495
514
 
496
515
  if abort and settings_type in ['mask', 'measure', 'classify', 'sequencing', 'umap']:
497
- abort_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
516
+ abort_button = spacrButton(button_scrollable_frame.scrollable_frame, text="abort", command=initiate_abort)
498
517
  abort_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
499
518
  widgets.append(abort_button)
500
519
  btn_row += 1
501
520
 
502
521
  if download and settings_type in ['mask']:
503
- download_dataset_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Download", command=download_hug_dataset)
522
+ download_dataset_button = spacrButton(button_scrollable_frame.scrollable_frame, text="download", command=download_hug_dataset)
504
523
  download_dataset_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
505
524
  widgets.append(download_dataset_button)
506
525
  btn_row += 1
507
526
 
508
527
  if import_btn:
509
- import_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(settings_type))
528
+ import_button = spacrButton(button_scrollable_frame.scrollable_frame, text="settings", command=lambda: import_settings(settings_type))
510
529
  import_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
511
530
  widgets.append(import_button)
512
531
 
@@ -516,11 +535,19 @@ def setup_button_section(horizontal_container, settings_type='mask', window_dime
516
535
  description_frame = tk.Frame(horizontal_container)
517
536
  horizontal_container.add(description_frame, stretch="always", sticky="nsew")
518
537
  description_frame.grid_columnconfigure(0, weight=1)
538
+ description_frame.grid_rowconfigure(0, weight=1) # Add this line to make the row expandable
539
+
519
540
  description_label = tk.Label(description_frame, text="Module Description", anchor='nw', justify='left', wraplength=width - 50)
520
541
  description_label.grid(row=0, column=0, pady=50, padx=20, sticky='nsew')
521
542
  description_text = descriptions.get(settings_type, "No description available for this module.")
522
543
  description_label.config(text=description_text)
523
544
 
545
+ def update_wraplength(event):
546
+ new_width = event.width - 40 # Adjust as needed
547
+ description_label.config(wraplength=new_width)
548
+
549
+ description_label.bind('<Configure>', update_wraplength)
550
+
524
551
  containers = [button_frame, description_frame]
525
552
  widgets.extend([description_label])
526
553
 
@@ -588,7 +615,7 @@ def toggle_settings(button_scrollable_frame):
588
615
  category_var = tk.StringVar()
589
616
  non_empty_categories = [category for category, settings in categories.items() if any(setting in vars_dict for setting in settings)]
590
617
  category_dropdown = spacrDropdownMenu(button_scrollable_frame.scrollable_frame, category_var, non_empty_categories, command=on_category_select)
591
- category_dropdown.grid(row=1, column=3, sticky="ew", pady=2, padx=2)
618
+ category_dropdown.grid(row=5, column=0, sticky="ew", pady=2, padx=2)
592
619
  vars_dict = hide_all_settings(vars_dict, categories)
593
620
 
594
621
  def process_fig_queue():