spacr 0.1.12__py3-none-any.whl → 0.1.50__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/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, style_text_boxes, create_menu_bar
16
+ from .gui_utils import ScrollableFrame, CustomButton, 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):
@@ -372,7 +372,6 @@ global_image_refs = []
372
372
  def initiate_annotation_app_root(parent_frame):
373
373
  style = ttk.Style(parent_frame)
374
374
  set_dark_style(style)
375
- style_text_boxes(style)
376
375
  set_default_font(parent_frame, font_name="Arial", size=8)
377
376
 
378
377
  parent_frame.configure(bg='black')
@@ -536,4 +535,4 @@ def gui_annotate():
536
535
  root.mainloop()
537
536
 
538
537
  if __name__ == "__main__":
539
- gui_annotate()
538
+ gui_annotate()
spacr/app_classify.py CHANGED
@@ -1,201 +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 .gui_utils import ScrollableFrame, StdoutRedirector, CustomButton, set_dark_style, set_default_font, generate_fields, process_stdout_stderr, clear_canvas, main_thread_update_function
19
- from .gui_utils import classify_variables, check_classify_gui_settings, train_test_model_wrapper, read_settings_from_csv, update_settings_from_csv, style_text_boxes, create_menu_bar
20
-
21
- thread_control = {"run_thread": None, "stop_requested": False}
22
-
23
- #@log_function_call
24
- def initiate_abort():
25
- global thread_control
26
- if thread_control.get("stop_requested") is not None:
27
- thread_control["stop_requested"].value = 1
28
-
29
- if thread_control.get("run_thread") is not None:
30
- thread_control["run_thread"].join(timeout=5)
31
- if thread_control["run_thread"].is_alive():
32
- thread_control["run_thread"].terminate()
33
- thread_control["run_thread"] = None
34
-
35
- #@log_function_call
36
- def run_classify_gui(q, fig_queue, stop_requested):
37
- global vars_dict
38
- process_stdout_stderr(q)
39
- try:
40
- settings = check_classify_gui_settings(vars_dict)
41
- for key in settings:
42
- value = settings[key]
43
- print(key, value, type(value))
44
- train_test_model_wrapper(settings['src'], settings)
45
- except Exception as e:
46
- q.put(f"Error during processing: {e}")
47
- traceback.print_exc()
48
- finally:
49
- stop_requested.value = 1
50
-
51
- #@log_function_call
52
- def start_process(q, fig_queue):
53
- global thread_control
54
- if thread_control.get("run_thread") is not None:
55
- initiate_abort()
56
-
57
- stop_requested = Value('i', 0) # multiprocessing shared value for inter-process communication
58
- thread_control["stop_requested"] = stop_requested
59
- thread_control["run_thread"] = Process(target=run_classify_gui, args=(q, fig_queue, stop_requested))
60
- thread_control["run_thread"].start()
61
-
62
- def import_settings(scrollable_frame):
63
- global vars_dict
64
-
65
- csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
66
- csv_settings = read_settings_from_csv(csv_file_path)
67
- variables = classify_variables()
68
- new_settings = update_settings_from_csv(variables, csv_settings)
69
- vars_dict = generate_fields(new_settings, scrollable_frame)
70
-
71
- #@log_function_call
72
- def initiate_classify_root(parent_frame):
73
- global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control
74
-
75
- style = ttk.Style(parent_frame)
76
- set_dark_style(style)
77
- style_text_boxes(style)
78
- set_default_font(parent_frame, font_name="Helvetica", size=8)
79
-
80
- parent_frame.configure(bg='black')
81
- parent_frame.grid_rowconfigure(0, weight=1)
82
- parent_frame.grid_columnconfigure(0, weight=1)
83
- fig_queue = Queue()
84
-
85
- def _process_fig_queue():
86
- global canvas
87
- try:
88
- while not fig_queue.empty():
89
- clear_canvas(canvas)
90
- fig = fig_queue.get_nowait()
91
- for ax in fig.get_axes():
92
- ax.set_xticks([]) # Remove x-axis ticks
93
- ax.set_yticks([]) # Remove y-axis ticks
94
- ax.xaxis.set_visible(False) # Hide the x-axis
95
- ax.yaxis.set_visible(False) # Hide the y-axis
96
- fig.tight_layout()
97
- fig.set_facecolor('black')
98
- canvas.figure = fig
99
- fig_width, fig_height = canvas_widget.winfo_width(), canvas_widget.winfo_height()
100
- fig.set_size_inches(fig_width / fig.dpi, fig_height / fig.dpi, forward=True)
101
- canvas.draw_idle()
102
- except Exception as e:
103
- traceback.print_exc()
104
- finally:
105
- canvas_widget.after(100, _process_fig_queue)
106
-
107
- def _process_console_queue():
108
- while not q.empty():
109
- message = q.get_nowait()
110
- console_output.insert(tk.END, message)
111
- console_output.see(tk.END)
112
- console_output.after(100, _process_console_queue)
113
-
114
- vertical_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
115
- vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
116
- parent_frame.grid_rowconfigure(0, weight=1)
117
- parent_frame.grid_columnconfigure(0, weight=1)
118
-
119
- # Settings Section
120
- settings_frame = tk.Frame(vertical_container, bg='black')
121
- vertical_container.add(settings_frame, stretch="always")
122
- settings_label = ttk.Label(settings_frame, text="Settings", background="black", foreground="white")
123
- settings_label.grid(row=0, column=0, pady=10, padx=10)
124
- scrollable_frame = ScrollableFrame(settings_frame, width=500)
125
- scrollable_frame.grid(row=1, column=0, sticky="nsew")
126
- settings_frame.grid_rowconfigure(1, weight=1)
127
- settings_frame.grid_columnconfigure(0, weight=1)
128
-
129
- # Setup for user input fields (variables)
130
- variables = classify_variables()
131
- vars_dict = generate_fields(variables, scrollable_frame)
132
-
133
- # Button section
134
- import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(scrollable_frame), font=('Helvetica', 10))
135
- import_btn.grid(row=47, column=0, pady=20, padx=20)
136
- run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue), font=('Helvetica', 10))
137
- run_button.grid(row=45, column=0, pady=20, padx=20)
138
- abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort, font=('Helvetica', 10))
139
- abort_button.grid(row=45, column=1, pady=20, padx=20)
140
- progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white") # Create progress field
141
- progress_label.grid(row=50, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
142
-
143
- # Plot Canvas Section
144
- plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
145
- vertical_container.add(plot_frame, stretch="always")
146
- figure = Figure(figsize=(30, 4), dpi=100, facecolor='black')
147
- plot = figure.add_subplot(111)
148
- plot.plot([], [])
149
- plot.axis('off')
150
- canvas = FigureCanvasTkAgg(figure, master=plot_frame)
151
- canvas.get_tk_widget().configure(cursor='arrow', background='black', highlightthickness=0)
152
- canvas_widget = canvas.get_tk_widget()
153
- plot_frame.add(canvas_widget, stretch="always")
154
- canvas.draw()
155
- canvas.figure = figure
156
-
157
- # Console Section
158
- console_frame = tk.Frame(vertical_container, bg='black')
159
- vertical_container.add(console_frame, stretch="always")
160
- console_label = ttk.Label(console_frame, text="Console", background="black", foreground="white")
161
- console_label.grid(row=0, column=0, pady=10, padx=10)
162
- console_output = scrolledtext.ScrolledText(console_frame, height=10, bg='black', fg='white', insertbackground='white')
163
- console_output.grid(row=1, column=0, sticky="nsew")
164
- console_frame.grid_rowconfigure(1, weight=1)
165
- console_frame.grid_columnconfigure(0, weight=1)
166
-
167
- q = Queue()
168
- sys.stdout = StdoutRedirector(console_output)
169
- sys.stderr = StdoutRedirector(console_output)
170
-
171
- _process_console_queue()
172
- _process_fig_queue()
173
-
174
- parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
175
-
176
- return parent_frame, vars_dict
177
-
178
- def gui_classify():
179
- root = tk.Tk()
180
- width = root.winfo_screenwidth()
181
- height = root.winfo_screenheight()
182
- root.geometry(f"{width}x{height}")
183
- root.title("SpaCr: classify objects")
184
-
185
- # Clear previous content if any
186
- if hasattr(root, 'content_frame'):
187
- for widget in root.content_frame.winfo_children():
188
- widget.destroy()
189
- root.content_frame.grid_forget()
190
- else:
191
- root.content_frame = tk.Frame(root)
192
- root.content_frame.grid(row=1, column=0, sticky="nsew")
193
- root.grid_rowconfigure(1, weight=1)
194
- root.grid_columnconfigure(0, weight=1)
195
-
196
- initiate_classify_root(root.content_frame)
197
- create_menu_bar(root)
198
- root.mainloop()
3
+ def start_classify_app():
4
+ app = MainApp(default_app="Classify")
5
+ app.mainloop()
199
6
 
200
7
  if __name__ == "__main__":
201
- 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, create_dark_mode, style_text_boxes, create_menu_bar
16
+ from .gui_utils import ScrollableFrame, CustomButton, set_dark_style, create_menu_bar, set_default_font
17
17
 
18
18
  class modify_masks:
19
19
 
@@ -864,7 +864,6 @@ class modify_masks:
864
864
  def initiate_mask_app_root(parent_frame):
865
865
  style = ttk.Style(parent_frame)
866
866
  set_dark_style(style)
867
- style_text_boxes(style)
868
867
  set_default_font(parent_frame, font_name="Arial", size=8)
869
868
 
870
869
  container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
@@ -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, style_text_boxes, create_menu_bar
16
+ from .gui_utils import ScrollableFrame, CustomButton, set_dark_style, create_dark_mode, create_menu_bar, set_default_font
17
17
 
18
18
  class ModifyMasks:
19
19
  def __init__(self, root, folder_path, scale_factor):
@@ -635,9 +635,7 @@ def initiate_mask_app_root(width, height):
635
635
  root = ThemedTk(theme=theme)
636
636
  style = ttk.Style(root)
637
637
  set_dark_style(style)
638
-
639
- style_text_boxes(style)
640
- set_default_font(root, font_name="Arial", size=8)
638
+ #set_default_font(root, font_name="Arial", size=8)
641
639
  root.geometry(f"{width}x{height}")
642
640
  root.title("Mask App")
643
641
  create_menu_bar(root)
spacr/app_mask.py CHANGED
@@ -1,251 +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 .gui_utils import ScrollableFrame, StdoutRedirector, ToggleSwitch, CustomButton, ToolTip
20
- from .gui_utils import clear_canvas, main_thread_update_function, set_dark_style, generate_fields, process_stdout_stderr, set_default_font, style_text_boxes
21
- from .gui_utils import mask_variables, check_mask_gui_settings, preprocess_generate_masks_wrapper, read_settings_from_csv, update_settings_from_csv, create_menu_bar
22
-
23
- thread_control = {"run_thread": None, "stop_requested": False}
24
-
25
- test_mode_button = None
26
-
27
- def toggle_test_mode():
28
- global vars_dict
29
- current_state = vars_dict['test_mode'][2].get()
30
- new_state = not current_state
31
- vars_dict['test_mode'][2].set(new_state)
32
- if new_state:
33
- test_mode_button.config(bg="blue")
34
- else:
35
- test_mode_button.config(bg="gray")
36
-
37
- def toggle_advanced_settings():
38
- global vars_dict
39
-
40
- timelapse_settings = ['timelapse', 'timelapse_memory', 'timelapse_remove_transient', 'timelapse_mode', 'timelapse_objects', 'timelapse_displacement', 'timelapse_frame_limits', 'fps']
41
- misc_settings = ['examples_to_plot', 'all_to_mip', 'pick_slice', 'skip_mode']
42
- opperational_settings = ['preprocess', 'masks', 'randomize', 'batch_size', 'custom_regex', 'merge', 'normalize_plots', 'workers', 'plot', 'remove_background', 'lower_quantile']
43
-
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
- variables = mask_variables()
98
- new_settings = update_settings_from_csv(variables, csv_settings)
99
- vars_dict = generate_fields(new_settings, scrollable_frame)
100
-
101
- #@log_function_call
102
- def initiate_mask_root(parent_frame):
103
- global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, advanced_var, scrollable_frame
104
-
105
- style = ttk.Style(parent_frame)
106
- set_dark_style(style)
107
- style_text_boxes(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)
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")
163
- settings_label.grid(row=0, column=0, pady=10, padx=10)
164
- scrollable_frame = ScrollableFrame(settings_frame, width=600)
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=48, column=0, pady=10, padx=10)
173
- variables = mask_variables()
174
- vars_dict = generate_fields(variables, scrollable_frame)
175
- toggle_advanced_settings()
176
- vars_dict['Test mode'] = (None, None, tk.BooleanVar(value=False))
177
-
178
- # Button section
179
- test_mode_button = CustomButton(scrollable_frame.scrollable_frame, text="Test Mode", command=toggle_test_mode, font=('Helvetica', 10))
180
- #CustomButton(buttons_frame, text=app_name, command=lambda app_name=app_name: self.load_app(app_name, app_func), font=('Helvetica', 12))
181
-
182
- test_mode_button.grid(row=47, column=1, pady=10, padx=10)
183
- import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(scrollable_frame), font=('Helvetica', 10))
184
- import_btn.grid(row=47, column=0, pady=10, padx=10)
185
- run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue))
186
- run_button.grid(row=45, column=0, pady=10, padx=10)
187
- abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort, font=('Helvetica', 10))
188
- abort_button.grid(row=45, column=1, pady=10, padx=10)
189
- progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white")
190
- progress_label.grid(row=50, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
191
-
192
- # Plot Canvas Section
193
- plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
194
- vertical_container.add(plot_frame, stretch="always")
195
- figure = Figure(figsize=(30, 4), dpi=100, facecolor='black')
196
- plot = figure.add_subplot(111)
197
- plot.plot([], []) # This creates an empty plot.
198
- plot.axis('off')
199
- canvas = FigureCanvasTkAgg(figure, master=plot_frame)
200
- canvas.get_tk_widget().configure(cursor='arrow', background='black', highlightthickness=0)
201
- canvas_widget = canvas.get_tk_widget()
202
- plot_frame.add(canvas_widget, stretch="always")
203
- canvas.draw()
204
- canvas.figure = figure
205
-
206
- # Console Section
207
- console_frame = tk.Frame(vertical_container, bg='black')
208
- vertical_container.add(console_frame, stretch="always")
209
- console_label = ttk.Label(console_frame, text="Console", background="black", foreground="white")
210
- console_label.grid(row=0, column=0, pady=10, padx=10)
211
- console_output = scrolledtext.ScrolledText(console_frame, height=10, bg='black', fg='white', insertbackground='white')
212
- console_output.grid(row=1, column=0, sticky="nsew")
213
- console_frame.grid_rowconfigure(1, weight=1)
214
- console_frame.grid_columnconfigure(0, weight=1)
215
-
216
- q = Queue()
217
- sys.stdout = StdoutRedirector(console_output)
218
- sys.stderr = StdoutRedirector(console_output)
219
-
220
- _process_console_queue()
221
- _process_fig_queue()
222
-
223
- after_id = parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
224
- parent_frame.after_tasks.append(after_id)
225
-
226
- return parent_frame, vars_dict
227
-
228
- def gui_mask():
229
- root = tk.Tk()
230
- width = root.winfo_screenwidth()
231
- height = root.winfo_screenheight()
232
- root.geometry(f"{width}x{height}")
233
- root.title("SpaCr: generate masks")
234
-
235
- # Clear previous content if any
236
- if hasattr(root, 'content_frame'):
237
- for widget in root.content_frame.winfo_children():
238
- widget.destroy()
239
- root.content_frame.grid_forget()
240
- else:
241
- root.content_frame = tk.Frame(root)
242
- root.content_frame.grid(row=1, column=0, sticky="nsew")
243
- root.grid_rowconfigure(1, weight=1)
244
- root.grid_columnconfigure(0, weight=1)
245
-
246
- initiate_mask_root(root.content_frame)
247
- create_menu_bar(root)
248
- root.mainloop()
3
+ def start_mask_app():
4
+ app = MainApp(default_app="Mask")
5
+ app.mainloop()
249
6
 
250
7
  if __name__ == "__main__":
251
- gui_mask()
8
+ start_mask_app()