spacr 0.1.16__py3-none-any.whl → 0.1.55__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/__init__.py CHANGED
@@ -15,10 +15,11 @@ from . import deep_spacr
15
15
  from . import app_annotate
16
16
  from . import gui_utils
17
17
  from . import app_make_masks
18
- from . import app_make_masks_v2
19
18
  from . import app_mask
20
19
  from . import app_measure
21
20
  from . import app_classify
21
+ from . import app_sequencing
22
+ from . import app_umap
22
23
  from . import logger
23
24
 
24
25
 
@@ -40,6 +41,8 @@ __all__ = [
40
41
  "app_mask",
41
42
  "app_measure",
42
43
  "app_classify",
44
+ "app_sequencing",
45
+ "app_umap",
43
46
  "logger"
44
47
  ]
45
48
 
spacr/app_annotate.py CHANGED
@@ -13,7 +13,7 @@ from IPython.display import display, HTML
13
13
  from tkinter import font as tkFont
14
14
  from tkinter import TclError
15
15
 
16
- from .gui_utils import ScrollableFrame, CustomButton, set_dark_style, set_default_font, set_dark_style, create_menu_bar
16
+ from .gui_utils import spacrFrame, spacrButton, set_dark_style, create_menu_bar, set_default_font
17
17
 
18
18
  class ImageApp:
19
19
  def __init__(self, root, db_path, src, image_type=None, channels=None, grid_rows=None, grid_cols=None, image_size=(200, 200), annotation_column='annotate', normalize=False, percentiles=(1,99), measurement=None, threshold=None):
@@ -379,7 +379,7 @@ def initiate_annotation_app_root(parent_frame):
379
379
  container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL, bg='black')
380
380
  container.pack(fill=tk.BOTH, expand=True)
381
381
 
382
- scrollable_frame = ScrollableFrame(container, bg='black')
382
+ scrollable_frame = spacrFrame(container, bg='black')
383
383
  container.add(scrollable_frame, stretch="always")
384
384
 
385
385
  # Setup input fields
@@ -444,7 +444,7 @@ def initiate_annotation_app_root(parent_frame):
444
444
  # Start the annotate application in the same root window
445
445
  annotate_app(parent_frame, settings)
446
446
 
447
- run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=run_app,
447
+ run_button = spacrButton(scrollable_frame.scrollable_frame, text="Run", command=run_app,
448
448
  font=tkFont.Font(family="Arial", size=12, weight=tkFont.NORMAL))
449
449
  run_button.grid(row=row, column=0, columnspan=2, pady=10, padx=10)
450
450
 
spacr/app_classify.py CHANGED
@@ -1,206 +1,8 @@
1
- import sys, ctypes, matplotlib
2
- import tkinter as tk
3
- from tkinter import ttk, scrolledtext
4
- from matplotlib.figure import Figure
5
- from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
6
- from matplotlib.figure import Figure
7
- matplotlib.use('Agg')
8
- from tkinter import filedialog
9
- from multiprocessing import Process, Queue, Value
10
- import traceback
1
+ from .gui import MainApp
11
2
 
12
- try:
13
- ctypes.windll.shcore.SetProcessDpiAwareness(True)
14
- except AttributeError:
15
- pass
16
-
17
- from .logger import log_function_call
18
- from .settings import set_default_train_test_model
19
- from .gui_utils import ScrollableFrame, StdoutRedirector, CustomButton, set_dark_style, set_default_font, generate_fields, process_stdout_stderr, clear_canvas, main_thread_update_function, convert_settings_dict_for_gui
20
- from .gui_utils import check_classify_gui_settings, train_test_model_wrapper, read_settings_from_csv, update_settings_from_csv, set_dark_style, create_menu_bar
21
-
22
- thread_control = {"run_thread": None, "stop_requested": False}
23
-
24
- #@log_function_call
25
- def initiate_abort():
26
- global thread_control
27
- if thread_control.get("stop_requested") is not None:
28
- thread_control["stop_requested"].value = 1
29
-
30
- if thread_control.get("run_thread") is not None:
31
- thread_control["run_thread"].join(timeout=5)
32
- if thread_control["run_thread"].is_alive():
33
- thread_control["run_thread"].terminate()
34
- thread_control["run_thread"] = None
35
-
36
- #@log_function_call
37
- def run_classify_gui(q, fig_queue, stop_requested):
38
- global vars_dict
39
- process_stdout_stderr(q)
40
- try:
41
- settings = check_classify_gui_settings(vars_dict)
42
- for key in settings:
43
- value = settings[key]
44
- print(key, value, type(value))
45
- train_test_model_wrapper(settings['src'], settings)
46
- except Exception as e:
47
- q.put(f"Error during processing: {e}")
48
- traceback.print_exc()
49
- finally:
50
- stop_requested.value = 1
51
-
52
- #@log_function_call
53
- def start_process(q, fig_queue):
54
- global thread_control
55
- if thread_control.get("run_thread") is not None:
56
- initiate_abort()
57
-
58
- stop_requested = Value('i', 0) # multiprocessing shared value for inter-process communication
59
- thread_control["stop_requested"] = stop_requested
60
- thread_control["run_thread"] = Process(target=run_classify_gui, args=(q, fig_queue, stop_requested))
61
- thread_control["run_thread"].start()
62
-
63
- def import_settings(scrollable_frame):
64
- global vars_dict
65
-
66
- csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
67
- csv_settings = read_settings_from_csv(csv_file_path)
68
- settings = set_default_train_test_model({})
69
- variables = convert_settings_dict_for_gui(settings)
70
- new_settings = update_settings_from_csv(variables, csv_settings)
71
- vars_dict = generate_fields(new_settings, scrollable_frame)
72
-
73
- #@log_function_call
74
- def initiate_classify_root(parent_frame):
75
- global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control
76
-
77
- style = ttk.Style(parent_frame)
78
- set_dark_style(style)
79
- set_default_font(parent_frame, font_name="Helvetica", size=8)
80
-
81
- parent_frame.configure(bg='black')
82
- parent_frame.grid_rowconfigure(0, weight=1)
83
- parent_frame.grid_columnconfigure(0, weight=1)
84
- fig_queue = Queue()
85
-
86
- def _process_fig_queue():
87
- global canvas
88
- try:
89
- while not fig_queue.empty():
90
- clear_canvas(canvas)
91
- fig = fig_queue.get_nowait()
92
- for ax in fig.get_axes():
93
- ax.set_xticks([]) # Remove x-axis ticks
94
- ax.set_yticks([]) # Remove y-axis ticks
95
- ax.xaxis.set_visible(False) # Hide the x-axis
96
- ax.yaxis.set_visible(False) # Hide the y-axis
97
- fig.tight_layout()
98
- fig.set_facecolor('black')
99
- canvas.figure = fig
100
- fig_width, fig_height = canvas_widget.winfo_width(), canvas_widget.winfo_height()
101
- fig.set_size_inches(fig_width / fig.dpi, fig_height / fig.dpi, forward=True)
102
- canvas.draw_idle()
103
- except Exception as e:
104
- traceback.print_exc()
105
- finally:
106
- canvas_widget.after(100, _process_fig_queue)
107
-
108
- def _process_console_queue():
109
- while not q.empty():
110
- message = q.get_nowait()
111
- console_output.insert(tk.END, message)
112
- console_output.see(tk.END)
113
- console_output.after(100, _process_console_queue)
114
-
115
- vertical_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
116
- vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
117
- parent_frame.grid_rowconfigure(0, weight=1)
118
- parent_frame.grid_columnconfigure(0, weight=1)
119
-
120
- # Settings Section
121
- settings_frame = tk.Frame(vertical_container, bg='black')
122
- vertical_container.add(settings_frame, stretch="always")
123
- settings_label = ttk.Label(settings_frame, text="Settings", background="black", foreground="white")
124
- settings_label.grid(row=0, column=0, pady=10, padx=10)
125
- scrollable_frame = ScrollableFrame(settings_frame, bg='black')
126
- scrollable_frame.grid(row=1, column=0, sticky="nsew")
127
- settings_frame.grid_rowconfigure(1, weight=1)
128
- settings_frame.grid_columnconfigure(0, weight=1)
129
-
130
- # Setup for user input fields (variables)
131
- settings = set_default_train_test_model({})
132
- variables = convert_settings_dict_for_gui(settings)
133
- vars_dict = generate_fields(variables, scrollable_frame)
134
-
135
- # Button section
136
- btn_row = 1
137
- run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue), font=('Helvetica', 10))
138
- run_button.grid(row=btn_row, column=0, pady=20, padx=20)
139
- abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort, font=('Helvetica', 10))
140
- abort_button.grid(row=btn_row, column=1, pady=20, padx=20)
141
- btn_row += 1
142
- import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(scrollable_frame), font=('Helvetica', 10))
143
- import_btn.grid(row=btn_row, column=0, pady=20, padx=20)
144
- btn_row += 1
145
- progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white") # Create progress field
146
- progress_label.grid(row=btn_row, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
147
-
148
- # Plot Canvas Section
149
- plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
150
- vertical_container.add(plot_frame, stretch="always")
151
- figure = Figure(figsize=(30, 4), dpi=100, facecolor='black')
152
- plot = figure.add_subplot(111)
153
- plot.plot([], [])
154
- plot.axis('off')
155
- canvas = FigureCanvasTkAgg(figure, master=plot_frame)
156
- canvas.get_tk_widget().configure(cursor='arrow', background='black', highlightthickness=0)
157
- canvas_widget = canvas.get_tk_widget()
158
- plot_frame.add(canvas_widget, stretch="always")
159
- canvas.draw()
160
- canvas.figure = figure
161
-
162
- # Console Section
163
- console_frame = tk.Frame(vertical_container, bg='black')
164
- vertical_container.add(console_frame, stretch="always")
165
- console_label = ttk.Label(console_frame, text="Console", background="black", foreground="white")
166
- console_label.grid(row=0, column=0, pady=10, padx=10)
167
- console_output = scrolledtext.ScrolledText(console_frame, height=10, bg='black', fg='white', insertbackground='white')
168
- console_output.grid(row=1, column=0, sticky="nsew")
169
- console_frame.grid_rowconfigure(1, weight=1)
170
- console_frame.grid_columnconfigure(0, weight=1)
171
-
172
- q = Queue()
173
- sys.stdout = StdoutRedirector(console_output)
174
- sys.stderr = StdoutRedirector(console_output)
175
-
176
- _process_console_queue()
177
- _process_fig_queue()
178
-
179
- parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
180
-
181
- return parent_frame, vars_dict
182
-
183
- def gui_classify():
184
- root = tk.Tk()
185
- width = root.winfo_screenwidth()
186
- height = root.winfo_screenheight()
187
- root.geometry(f"{width}x{height}")
188
- root.title("SpaCr: classify objects")
189
-
190
- # Clear previous content if any
191
- if hasattr(root, 'content_frame'):
192
- for widget in root.content_frame.winfo_children():
193
- widget.destroy()
194
- root.content_frame.grid_forget()
195
- else:
196
- root.content_frame = tk.Frame(root)
197
- root.content_frame.grid(row=1, column=0, sticky="nsew")
198
- root.grid_rowconfigure(1, weight=1)
199
- root.grid_columnconfigure(0, weight=1)
200
-
201
- initiate_classify_root(root.content_frame)
202
- create_menu_bar(root)
203
- root.mainloop()
3
+ def start_classify_app():
4
+ app = MainApp(default_app="Classify")
5
+ app.mainloop()
204
6
 
205
7
  if __name__ == "__main__":
206
- gui_classify()
8
+ start_classify_app()
spacr/app_make_masks.py CHANGED
@@ -13,7 +13,7 @@ from ttkthemes import ThemedTk
13
13
 
14
14
  from .logger import log_function_call
15
15
 
16
- from .gui_utils import ScrollableFrame, CustomButton, set_dark_style, set_default_font, set_dark_style, create_menu_bar
16
+ from .gui_utils import spacrFrame, spacrButton, set_dark_style, create_menu_bar, set_default_font
17
17
 
18
18
  class modify_masks:
19
19
 
@@ -869,7 +869,7 @@ def initiate_mask_app_root(parent_frame):
869
869
  container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
870
870
  container.pack(fill=tk.BOTH, expand=True)
871
871
 
872
- scrollable_frame = ScrollableFrame(container, bg='black')
872
+ scrollable_frame = spacrFrame(container, bg='black')
873
873
  container.add(scrollable_frame, stretch="always")
874
874
 
875
875
  # Setup input fields
@@ -897,7 +897,7 @@ def initiate_mask_app_root(parent_frame):
897
897
  # Start the modify_masks application in the same root window
898
898
  app_instance = modify_masks(parent_frame, folder_path, scale_factor)
899
899
 
900
- run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=run_app)
900
+ run_button = spacrButton(scrollable_frame.scrollable_frame, text="Run", command=run_app)
901
901
  run_button.grid(row=row, column=0, columnspan=2, pady=10, padx=10)
902
902
 
903
903
  return parent_frame
@@ -13,7 +13,7 @@ from ttkthemes import ThemedTk
13
13
  from pyqtgraph import GraphicsLayoutWidget, ViewBox, ImageItem, mkQApp
14
14
 
15
15
  from .logger import log_function_call
16
- from .gui_utils import ScrollableFrame, CustomButton, set_dark_style, set_default_font, create_dark_mode, set_dark_style, create_menu_bar
16
+ from .gui_utils import spacrFrame, spacrButton, set_dark_style, create_menu_bar, set_default_font
17
17
 
18
18
  class ModifyMasks:
19
19
  def __init__(self, root, folder_path, scale_factor):
@@ -643,7 +643,7 @@ def initiate_mask_app_root(width, height):
643
643
  container = tk.PanedWindow(root, orient=tk.HORIZONTAL)
644
644
  container.pack(fill=tk.BOTH, expand=True)
645
645
 
646
- scrollable_frame = ScrollableFrame(container, bg='black')
646
+ scrollable_frame = spacrFrame(container, bg='black')
647
647
  container.add(scrollable_frame, stretch="always")
648
648
 
649
649
  vars_dict = {
@@ -673,7 +673,7 @@ def initiate_mask_app_root(width, height):
673
673
 
674
674
  create_dark_mode(root, style, console_output=None)
675
675
 
676
- run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=run_app)
676
+ run_button = spacrButton(scrollable_frame.scrollable_frame, text="Run", command=run_app)
677
677
  run_button.grid(row=row, column=0, columnspan=2, pady=10, padx=10)
678
678
 
679
679
  return root
spacr/app_mask.py CHANGED
@@ -1,253 +1,8 @@
1
- #import customtkinter as ctk
1
+ from .gui import MainApp
2
2
 
3
- import sys, ctypes, matplotlib
4
- import tkinter as tk
5
- from tkinter import ttk, scrolledtext
6
- from matplotlib.figure import Figure
7
- from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
8
- matplotlib.use('Agg')
9
- from tkinter import filedialog
10
- from multiprocessing import Process, Queue, Value
11
- import traceback
12
-
13
- try:
14
- ctypes.windll.shcore.SetProcessDpiAwareness(True)
15
- except AttributeError:
16
- pass
17
-
18
- from .logger import log_function_call
19
- from .settings import set_default_settings_preprocess_generate_masks
20
- from .gui_utils import ScrollableFrame, StdoutRedirector, ToggleSwitch, CustomButton, ToolTip
21
- from .gui_utils import clear_canvas, main_thread_update_function, set_dark_style, generate_fields, process_stdout_stderr, set_default_font, set_dark_style, convert_settings_dict_for_gui
22
- from .gui_utils import check_mask_gui_settings, preprocess_generate_masks_wrapper, read_settings_from_csv, update_settings_from_csv, create_menu_bar
23
-
24
- thread_control = {"run_thread": None, "stop_requested": False}
25
-
26
- test_mode_button = None
27
-
28
- def toggle_test_mode():
29
- global vars_dict
30
- current_state = vars_dict['test_mode'][2].get()
31
- new_state = not current_state
32
- vars_dict['test_mode'][2].set(new_state)
33
- if new_state:
34
- test_mode_button.config(bg="blue")
35
- else:
36
- test_mode_button.config(bg="gray")
37
-
38
- def toggle_advanced_settings():
39
- global vars_dict
40
-
41
- timelapse_settings = ['timelapse','fps','timelapse_displacement','timelapse_memory','timelapse_frame_limits','timelapse_remove_transient','timelapse_mode','timelapse_objects']
42
- misc_settings = ['all_to_mip','pick_slice','skip_mode','upscale','upscale_factor','adjust_cells','lower_percentile','filter','merge_pathogens','pathogen_model']
43
- opperational_settings = ['examples_to_plot','normalize_plots','normalize','cmap','figuresize','plot','pathogen_FT','cell_FT','nucleus_FT','nucleus_CP_prob','nucleus_Signal_to_noise','nucleus_background','cell_CP_prob','cell_Signal_to_noise','cell_background','pathogen_CP_prob','pathogen_Signal_to_noise','pathogen_background','remove_background_pathogen','remove_background_nucleus','remove_background_cell','verbose','randomize','workers','metadata_type','custom_regex','test_images','batch_size','save','masks','preprocess']
44
- advanced_settings = timelapse_settings+misc_settings+opperational_settings
45
-
46
- # Toggle visibility of advanced settings
47
- for setting in advanced_settings:
48
- label, widget, var = vars_dict[setting]
49
- if advanced_var.get() is False:
50
- label.grid_remove() # Hide the label
51
- widget.grid_remove() # Hide the widget
52
- else:
53
- label.grid() # Show the label
54
- widget.grid() # Show the widget
55
-
56
- #@log_function_call
57
- def initiate_abort():
58
- global thread_control
59
- if thread_control.get("stop_requested") is not None:
60
- thread_control["stop_requested"].value = 1
61
-
62
- if thread_control.get("run_thread") is not None:
63
- thread_control["run_thread"].join(timeout=5)
64
- if thread_control["run_thread"].is_alive():
65
- thread_control["run_thread"].terminate()
66
- thread_control["run_thread"] = None
67
-
68
- #@log_function_call
69
- def run_mask_gui(q, fig_queue, stop_requested):
70
- global vars_dict
71
- process_stdout_stderr(q)
72
- try:
73
- settings = check_mask_gui_settings(vars_dict)
74
- preprocess_generate_masks_wrapper(settings, q, fig_queue)
75
- except Exception as e:
76
- q.put(f"Error during processing: {e}")
77
- traceback.print_exc()
78
- finally:
79
- stop_requested.value = 1
80
-
81
- #@log_function_call
82
- def start_process(q, fig_queue):
83
- global thread_control
84
- if thread_control.get("run_thread") is not None:
85
- initiate_abort()
86
-
87
- stop_requested = Value('i', 0) # multiprocessing shared value for inter-process communication
88
- thread_control["stop_requested"] = stop_requested
89
- thread_control["run_thread"] = Process(target=run_mask_gui, args=(q, fig_queue, stop_requested))
90
- thread_control["run_thread"].start()
91
-
92
- def import_settings(scrollable_frame):
93
- global vars_dict
94
-
95
- csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
96
- csv_settings = read_settings_from_csv(csv_file_path)
97
- settings = set_default_settings_preprocess_generate_masks({})
98
- variables = convert_settings_dict_for_gui(settings)
99
- new_settings = update_settings_from_csv(variables, csv_settings)
100
- vars_dict = generate_fields(new_settings, scrollable_frame)
101
-
102
- #@log_function_call
103
- def initiate_mask_root(parent_frame):
104
- global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, advanced_var, scrollable_frame
105
-
106
- style = ttk.Style(parent_frame)
107
- set_dark_style(style)
108
- set_default_font(parent_frame, font_name="Helvetica", size=8)
109
- parent_frame.configure(bg='black')
110
- parent_frame.grid_rowconfigure(0, weight=1)
111
- parent_frame.grid_columnconfigure(0, weight=1)
112
-
113
- fig_queue = Queue()
114
-
115
- # Initialize after_tasks if not already done
116
- if not hasattr(parent_frame, 'after_tasks'):
117
- parent_frame.after_tasks = []
118
-
119
- def _process_fig_queue():
120
- global canvas
121
- try:
122
- while not fig_queue.empty():
123
- clear_canvas(canvas)
124
- fig = fig_queue.get_nowait()
125
- for ax in fig.get_axes():
126
- ax.set_xticks([]) # Remove x-axis ticks
127
- ax.set_yticks([]) # Remove y-axis ticks
128
- ax.xaxis.set_visible(False) # Hide the x-axis
129
- ax.yaxis.set_visible(False) # Hide the y-axis
130
- fig.tight_layout()
131
- fig.set_facecolor('black')
132
- canvas.figure = fig
133
- fig_width, fig_height = canvas_widget.winfo_width(), canvas_widget.winfo_height()
134
- fig.set_size_inches(fig_width / fig.dpi, fig_height / fig.dpi, forward=True)
135
- canvas.draw_idle()
136
- except Exception as e:
137
- traceback.print_exc()
138
- finally:
139
- after_id = canvas_widget.after(100, _process_fig_queue)
140
- parent_frame.after_tasks.append(after_id)
141
-
142
- def _process_console_queue():
143
- while not q.empty():
144
- message = q.get_nowait()
145
- console_output.insert(tk.END, message)
146
- console_output.see(tk.END)
147
- after_id = console_output.after(100, _process_console_queue)
148
- parent_frame.after_tasks.append(after_id)
149
-
150
- # Clear previous content if any
151
- for widget in parent_frame.winfo_children():
152
- widget.destroy()
153
-
154
- vertical_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL, bg='black')
155
- vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
156
- parent_frame.grid_rowconfigure(0, weight=1)
157
- parent_frame.grid_columnconfigure(0, weight=1)
158
-
159
- # Settings Section
160
- settings_frame = tk.Frame(vertical_container, bg='black')
161
- vertical_container.add(settings_frame, stretch="always")
162
- settings_label = ttk.Label(settings_frame, text="Settings", style="Custom.TLabel", background="black", foreground="white")
163
- settings_label.grid(row=0, column=0, pady=10, padx=10)
164
- scrollable_frame = ScrollableFrame(settings_frame, bg='black')
165
- scrollable_frame.grid(row=1, column=0, sticky="nsew")
166
- settings_frame.grid_rowconfigure(1, weight=1)
167
- settings_frame.grid_columnconfigure(0, weight=1)
168
-
169
- # Create advanced settings checkbox
170
- advanced_var = tk.BooleanVar(value=False)
171
- advanced_Toggle = ToggleSwitch(scrollable_frame.scrollable_frame, text="Advanced Settings", variable=advanced_var, command=toggle_advanced_settings)
172
- advanced_Toggle.grid(row=4, column=0, pady=10, padx=10)
173
- settings = set_default_settings_preprocess_generate_masks({})
174
- variables = convert_settings_dict_for_gui(settings)
175
- vars_dict = generate_fields(variables, scrollable_frame)
176
- toggle_advanced_settings()
177
- vars_dict['Test mode'] = (None, None, tk.BooleanVar(value=False))
178
-
179
- # Button section
180
- btn_row = 1
181
- run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue))
182
- run_button.grid(row=btn_row, column=0, pady=5, padx=5)
183
- abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort, font=('Helvetica', 10))
184
- abort_button.grid(row=btn_row, column=1, pady=5, padx=5)
185
- btn_row += 1
186
- test_mode_button = CustomButton(scrollable_frame.scrollable_frame, text="Test", command=toggle_test_mode, font=('Helvetica', 10))
187
- test_mode_button.grid(row=btn_row, column=0, pady=5, padx=5)
188
- import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(scrollable_frame), font=('Helvetica', 10))
189
- import_btn.grid(row=btn_row, column=1, pady=5, padx=5)
190
- btn_row += 1
191
- progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white")
192
- progress_label.grid(row=btn_row, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
193
-
194
- # Plot Canvas Section
195
- plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
196
- vertical_container.add(plot_frame, stretch="always")
197
- figure = Figure(figsize=(30, 4), dpi=100, facecolor='black')
198
- plot = figure.add_subplot(111)
199
- plot.plot([], []) # This creates an empty plot.
200
- plot.axis('off')
201
- canvas = FigureCanvasTkAgg(figure, master=plot_frame)
202
- canvas.get_tk_widget().configure(cursor='arrow', background='black', highlightthickness=0)
203
- canvas_widget = canvas.get_tk_widget()
204
- plot_frame.add(canvas_widget, stretch="always")
205
- canvas.draw()
206
- canvas.figure = figure
207
-
208
- # Console Section
209
- console_frame = tk.Frame(vertical_container, bg='black')
210
- vertical_container.add(console_frame, stretch="always")
211
- console_label = ttk.Label(console_frame, text="Console", background="black", foreground="white")
212
- console_label.grid(row=0, column=0, pady=10, padx=10)
213
- console_output = scrolledtext.ScrolledText(console_frame, height=10, bg='black', fg='white', insertbackground='white')
214
- console_output.grid(row=1, column=0, sticky="nsew")
215
- console_frame.grid_rowconfigure(1, weight=1)
216
- console_frame.grid_columnconfigure(0, weight=1)
217
-
218
- q = Queue()
219
- sys.stdout = StdoutRedirector(console_output)
220
- sys.stderr = StdoutRedirector(console_output)
221
-
222
- _process_console_queue()
223
- _process_fig_queue()
224
-
225
- after_id = parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
226
- parent_frame.after_tasks.append(after_id)
227
-
228
- return parent_frame, vars_dict
229
-
230
- def gui_mask():
231
- root = tk.Tk()
232
- width = root.winfo_screenwidth()
233
- height = root.winfo_screenheight()
234
- root.geometry(f"{width}x{height}")
235
- root.title("SpaCr: generate masks")
236
-
237
- # Clear previous content if any
238
- if hasattr(root, 'content_frame'):
239
- for widget in root.content_frame.winfo_children():
240
- widget.destroy()
241
- root.content_frame.grid_forget()
242
- else:
243
- root.content_frame = tk.Frame(root)
244
- root.content_frame.grid(row=1, column=0, sticky="nsew")
245
- root.grid_rowconfigure(1, weight=1)
246
- root.grid_columnconfigure(0, weight=1)
247
-
248
- initiate_mask_root(root.content_frame)
249
- create_menu_bar(root)
250
- root.mainloop()
3
+ def start_mask_app():
4
+ app = MainApp(default_app="Mask")
5
+ app.mainloop()
251
6
 
252
7
  if __name__ == "__main__":
253
- gui_mask()
8
+ start_mask_app()