spacr 0.1.11__py3-none-any.whl → 0.1.12__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_mask.py ADDED
@@ -0,0 +1,251 @@
1
+ #import customtkinter as ctk
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()
249
+
250
+ if __name__ == "__main__":
251
+ gui_mask()
spacr/app_measure.py ADDED
@@ -0,0 +1,248 @@
1
+ import sys, traceback, matplotlib, ctypes
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
+ matplotlib.use('Agg') # Use the non-GUI Agg backend
7
+ from multiprocessing import Process, Queue, Value
8
+ from tkinter import filedialog
9
+
10
+ try:
11
+ ctypes.windll.shcore.SetProcessDpiAwareness(True)
12
+ except AttributeError:
13
+ pass
14
+
15
+ from .logger import log_function_call
16
+ from .gui_utils import ScrollableFrame, StdoutRedirector, CustomButton, ToggleSwitch, ToolTip
17
+ from .gui_utils import process_stdout_stderr, set_dark_style, set_default_font, generate_fields, main_thread_update_function, create_menu_bar
18
+ from .gui_utils import measure_variables, measure_crop_wrapper, clear_canvas, check_measure_gui_settings, read_settings_from_csv, update_settings_from_csv, style_text_boxes
19
+
20
+ thread_control = {"run_thread": None, "stop_requested": False}
21
+
22
+ def import_settings(scrollable_frame):
23
+ global vars_dict
24
+
25
+ csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
26
+ csv_settings = read_settings_from_csv(csv_file_path)
27
+ variables = measure_variables()
28
+ new_settings = update_settings_from_csv(variables, csv_settings)
29
+ vars_dict = generate_fields(new_settings, scrollable_frame)
30
+
31
+ test_mode_button = None
32
+
33
+ def toggle_test_mode():
34
+ global vars_dict
35
+ current_state = vars_dict['test_mode'][2].get()
36
+ new_state = not current_state
37
+ vars_dict['test_mode'][2].set(new_state)
38
+ if new_state:
39
+ test_mode_button.config(bg="blue")
40
+ else:
41
+ test_mode_button.config(bg="gray")
42
+
43
+ def toggle_advanced_settings():
44
+ global vars_dict
45
+
46
+ timelapse_settings = ['timelapse', 'timelapse_objects']
47
+ misc_settings = ['representative_images', 'plot', 'plot_filtration', 'include_uninfected', 'dialate_pngs', 'dialate_png_ratios']
48
+ opperational_settings = ['max_workers','experiment','cells','cell_loc','pathogens','pathogen_loc','treatments','treatment_loc','channel_of_interest','compartments','measurement','nr_imgs', 'um_per_pixel']
49
+
50
+ advanced_settings = timelapse_settings+misc_settings+opperational_settings
51
+
52
+ # Toggle visibility of advanced settings
53
+ for setting in advanced_settings:
54
+ label, widget, var = vars_dict[setting]
55
+ if advanced_var.get() is False:
56
+ label.grid_remove() # Hide the label
57
+ widget.grid_remove() # Hide the widget
58
+ else:
59
+ label.grid() # Show the label
60
+ widget.grid() # Show the widget
61
+
62
+ #@log_function_call
63
+ def run_measure_gui(q, fig_queue, stop_requested):
64
+ global vars_dict
65
+ process_stdout_stderr(q)
66
+ try:
67
+ print('hello')
68
+ settings = check_measure_gui_settings(vars_dict)
69
+ measure_crop_wrapper(settings=settings, q=q, fig_queue=fig_queue)
70
+ except Exception as e:
71
+ q.put(f"Error during processing: {e}")
72
+ traceback.print_exc()
73
+ finally:
74
+ stop_requested.value = 1
75
+
76
+ #@log_function_call
77
+ def start_process(q, fig_queue):
78
+ global thread_control
79
+ if thread_control.get("run_thread") is not None:
80
+ initiate_abort()
81
+
82
+ stop_requested = Value('i', 0) # multiprocessing shared value for inter-process communication
83
+ thread_control["stop_requested"] = stop_requested
84
+ thread_control["run_thread"] = Process(target=run_measure_gui, args=(q, fig_queue, stop_requested))
85
+ thread_control["run_thread"].start()
86
+
87
+ #@log_function_call
88
+ def initiate_abort():
89
+ global thread_control
90
+ if thread_control.get("stop_requested") is not None:
91
+ thread_control["stop_requested"].value = 1
92
+
93
+ if thread_control.get("run_thread") is not None:
94
+ thread_control["run_thread"].join(timeout=5)
95
+ if thread_control["run_thread"].is_alive():
96
+ thread_control["run_thread"].terminate()
97
+ thread_control["run_thread"] = None
98
+
99
+ #@log_function_call
100
+ def initiate_measure_root(parent_frame):
101
+ global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, variables, advanced_var, scrollable_frame
102
+
103
+ style = ttk.Style(parent_frame)
104
+ set_dark_style(style)
105
+ style_text_boxes(style)
106
+ set_default_font(parent_frame, font_name="Helvetica", size=8)
107
+
108
+ parent_frame.configure(bg='black')
109
+ parent_frame.grid_rowconfigure(0, weight=1)
110
+ parent_frame.grid_columnconfigure(0, weight=1)
111
+
112
+ fig_queue = Queue()
113
+
114
+ # Initialize after_tasks if not already done
115
+ if not hasattr(parent_frame, 'after_tasks'):
116
+ parent_frame.after_tasks = []
117
+
118
+ def _process_fig_queue():
119
+ global canvas
120
+ try:
121
+ while not fig_queue.empty():
122
+ clear_canvas(canvas)
123
+ fig = fig_queue.get_nowait()
124
+ for ax in fig.get_axes():
125
+ ax.set_xticks([]) # Remove x-axis ticks
126
+ ax.set_yticks([]) # Remove y-axis ticks
127
+ ax.xaxis.set_visible(False) # Hide the x-axis
128
+ ax.yaxis.set_visible(False) # Hide the y-axis
129
+ fig.tight_layout()
130
+ fig.set_facecolor('black')
131
+ canvas.figure = fig
132
+ fig_width, fig_height = canvas_widget.winfo_width(), canvas_widget.winfo_height()
133
+ fig.set_size_inches(fig_width / fig.dpi, fig_height / fig.dpi, forward=True)
134
+ canvas.draw_idle()
135
+ except Exception as e:
136
+ traceback.print_exc()
137
+ finally:
138
+ after_id = canvas_widget.after(100, _process_fig_queue)
139
+ parent_frame.after_tasks.append(after_id)
140
+
141
+ def _process_console_queue():
142
+ while not q.empty():
143
+ message = q.get_nowait()
144
+ console_output.insert(tk.END, message)
145
+ console_output.see(tk.END)
146
+ after_id = console_output.after(100, _process_console_queue)
147
+ parent_frame.after_tasks.append(after_id)
148
+
149
+ # Clear previous content if any
150
+ for widget in parent_frame.winfo_children():
151
+ widget.destroy()
152
+
153
+ vertical_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
154
+ vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
155
+ parent_frame.grid_rowconfigure(0, weight=1)
156
+ parent_frame.grid_columnconfigure(0, weight=1)
157
+
158
+ # Settings Section
159
+ settings_frame = tk.Frame(vertical_container, bg='black')
160
+ vertical_container.add(settings_frame, stretch="always")
161
+ settings_label = ttk.Label(settings_frame, text="Settings", background="black", foreground="white")
162
+ settings_label.grid(row=0, column=0, pady=10, padx=10)
163
+ scrollable_frame = ScrollableFrame(settings_frame, width=500)
164
+ scrollable_frame.grid(row=1, column=0, sticky="nsew")
165
+ settings_frame.grid_rowconfigure(1, weight=1)
166
+ settings_frame.grid_columnconfigure(0, weight=1)
167
+
168
+ # Create advanced settings checkbox
169
+ advanced_var = tk.BooleanVar(value=False)
170
+ advanced_Toggle = ToggleSwitch(scrollable_frame.scrollable_frame, text="Advanced Settings", variable=advanced_var, command=toggle_advanced_settings)
171
+ advanced_Toggle.grid(row=48, column=0, pady=10, padx=10)
172
+ variables = measure_variables()
173
+ vars_dict = generate_fields(variables, scrollable_frame)
174
+ toggle_advanced_settings()
175
+ vars_dict['Test mode'] = (None, None, tk.BooleanVar(value=False))
176
+
177
+ # Button section
178
+ test_mode_button = CustomButton(scrollable_frame.scrollable_frame, text="Test Mode", command=toggle_test_mode)
179
+ test_mode_button.grid(row=47, column=1, pady=10, padx=10)
180
+ import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(scrollable_frame), font=('Helvetica', 10))
181
+ import_btn.grid(row=47, column=0, pady=20, padx=20)
182
+ run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue), font=('Helvetica', 10))
183
+ run_button.grid(row=45, column=0, pady=20, padx=20)
184
+ abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort, font=('Helvetica', 10))
185
+ abort_button.grid(row=45, column=1, pady=20, padx=20)
186
+ progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white") # Create progress field
187
+ progress_label.grid(row=50, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
188
+
189
+ # Plot Canvas Section
190
+ plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
191
+ vertical_container.add(plot_frame, stretch="always")
192
+ figure = Figure(figsize=(30, 4), dpi=100, facecolor='black')
193
+ plot = figure.add_subplot(111)
194
+ plot.plot([], [])
195
+ plot.axis('off')
196
+ canvas = FigureCanvasTkAgg(figure, master=plot_frame)
197
+ canvas.get_tk_widget().configure(cursor='arrow', background='black', highlightthickness=0)
198
+ canvas_widget = canvas.get_tk_widget()
199
+ plot_frame.add(canvas_widget, stretch="always")
200
+ canvas.draw()
201
+ canvas.figure = figure
202
+
203
+ # Console Section
204
+ console_frame = tk.Frame(vertical_container, bg='black')
205
+ vertical_container.add(console_frame, stretch="always")
206
+ console_label = ttk.Label(console_frame, text="Console", background="black", foreground="white")
207
+ console_label.grid(row=0, column=0, pady=10, padx=10)
208
+ console_output = scrolledtext.ScrolledText(console_frame, height=10, bg='black', fg='white', insertbackground='white')
209
+ console_output.grid(row=1, column=0, sticky="nsew")
210
+ console_frame.grid_rowconfigure(1, weight=1)
211
+ console_frame.grid_columnconfigure(0, weight=1)
212
+
213
+ q = Queue()
214
+ sys.stdout = StdoutRedirector(console_output)
215
+ sys.stderr = StdoutRedirector(console_output)
216
+
217
+ _process_console_queue()
218
+ _process_fig_queue()
219
+
220
+ after_id = parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
221
+ parent_frame.after_tasks.append(after_id)
222
+
223
+ return parent_frame, vars_dict
224
+
225
+ def gui_measure():
226
+ root = tk.Tk()
227
+ width = root.winfo_screenwidth()
228
+ height = root.winfo_screenheight()
229
+ root.geometry(f"{width}x{height}")
230
+ root.title("SpaCr: measure objects")
231
+
232
+ # Clear previous content if any
233
+ if hasattr(root, 'content_frame'):
234
+ for widget in root.content_frame.winfo_children():
235
+ widget.destroy()
236
+ root.content_frame.grid_forget()
237
+ else:
238
+ root.content_frame = tk.Frame(root)
239
+ root.content_frame.grid(row=1, column=0, sticky="nsew")
240
+ root.grid_rowconfigure(1, weight=1)
241
+ root.grid_columnconfigure(0, weight=1)
242
+
243
+ initiate_measure_root(root.content_frame)
244
+ create_menu_bar(root)
245
+ root.mainloop()
246
+
247
+ if __name__ == "__main__":
248
+ gui_measure()
spacr/gui.py CHANGED
@@ -6,21 +6,21 @@ import os
6
6
  import requests
7
7
 
8
8
  # Import your GUI apps
9
- from .gui_mask_app import initiate_mask_root
10
- from .gui_measure_app import initiate_measure_root
11
- from .annotate_app import initiate_annotation_app_root
12
- from .gui_make_masks_app import initiate_mask_app_root
13
- from .gui_classify_app import initiate_classify_root
9
+ from .app_mask import initiate_mask_root
10
+ from .app_measure import initiate_measure_root
11
+ from .app_annotate import initiate_annotation_app_root
12
+ from .app_make_masks import initiate_mask_app_root
13
+ from .app_classify import initiate_classify_root
14
14
  from .gui_utils import CustomButton, style_text_boxes, create_menu_bar
15
15
 
16
16
  class MainApp(tk.Tk):
17
17
  def __init__(self):
18
18
  super().__init__()
19
+ width = self.winfo_screenwidth()
20
+ height = self.winfo_screenheight()
21
+ self.geometry(f"{width}x{height}")
19
22
  self.title("SpaCr GUI Collection")
20
- self.geometry("1100x1500")
21
23
  self.configure(bg="black")
22
- #self.attributes('-fullscreen', True)
23
-
24
24
  style = ttk.Style()
25
25
  style_text_boxes(style)
26
26
 
@@ -37,7 +37,7 @@ class MainApp(tk.Tk):
37
37
 
38
38
  def create_widgets(self):
39
39
  # Create the menu bar
40
- self.gui_create_menu_bar()
40
+ create_menu_bar(self)
41
41
 
42
42
  # Create a canvas to hold the selected app and other elements
43
43
  self.canvas = tk.Canvas(self, bg="black", highlightthickness=0)
@@ -52,9 +52,6 @@ class MainApp(tk.Tk):
52
52
  # Create startup screen with buttons for each GUI app
53
53
  self.create_startup_screen()
54
54
 
55
- def gui_create_menu_bar(self):
56
- create_menu_bar(self)
57
-
58
55
  def create_startup_screen(self):
59
56
  self.clear_frame(self.content_frame)
60
57
 
spacr/gui_utils.py CHANGED
@@ -65,11 +65,11 @@ def load_app(root, app_name, app_func):
65
65
  app_func(root.content_frame)
66
66
 
67
67
  def create_menu_bar(root):
68
- from .gui_mask_app import initiate_mask_root
69
- from .gui_measure_app import initiate_measure_root
70
- from .annotate_app import initiate_annotation_app_root
71
- from .gui_make_masks_app import initiate_mask_app_root
72
- from .gui_classify_app import initiate_classify_root
68
+ from .app_mask import initiate_mask_root
69
+ from .app_measure import initiate_measure_root
70
+ from .app_annotate import initiate_annotation_app_root
71
+ from .app_make_masks import initiate_mask_app_root
72
+ from .app_classify import initiate_classify_root
73
73
 
74
74
  gui_apps = {
75
75
  "Mask": initiate_mask_root,
@@ -96,6 +96,42 @@ def create_menu_bar(root):
96
96
  # Configure the menu for the root window
97
97
  root.config(menu=menu_bar)
98
98
 
99
+ def proceed_with_app(root, app_name, app_func):
100
+
101
+ from .app_mask import gui_mask
102
+ from .app_measure import gui_measure
103
+ from .app_annotate import gui_annotate
104
+ from .app_make_masks import gui_make_masks
105
+ from .app_classify import gui_classify
106
+ from .gui import gui_app
107
+
108
+ # Clear the current content frame
109
+ if hasattr(root, 'content_frame'):
110
+ for widget in root.content_frame.winfo_children():
111
+ widget.destroy()
112
+ else:
113
+ root.content_frame = tk.Frame(root)
114
+ root.content_frame.grid(row=1, column=0, sticky="nsew")
115
+ root.grid_rowconfigure(1, weight=1)
116
+ root.grid_columnconfigure(0, weight=1)
117
+
118
+ # Initialize the new app in the content frame
119
+ if app_name == "Main App":
120
+ root.destroy() # Close the current window
121
+ gui_app() # Open the main app window
122
+ elif app_name == "Mask":
123
+ gui_mask()
124
+ elif app_name == "Measure":
125
+ gui_measure()
126
+ elif app_name == "Annotate":
127
+ gui_annotate()
128
+ elif app_name == "Make Masks":
129
+ gui_make_masks()
130
+ elif app_name == "Classify":
131
+ gui_classify()
132
+ else:
133
+ raise ValueError(f"Invalid app name: {app_name}")
134
+
99
135
  def load_app(root, app_name, app_func):
100
136
  # Cancel all scheduled after tasks
101
137
  if hasattr(root, 'after_tasks'):
@@ -103,35 +139,25 @@ def load_app(root, app_name, app_func):
103
139
  root.after_cancel(task)
104
140
  root.after_tasks = []
105
141
 
106
- def proceed_with_app():
107
- # Clear the current content frame
108
- if hasattr(root, 'content_frame'):
109
- for widget in root.content_frame.winfo_children():
110
- widget.destroy()
111
- else:
112
- root.content_frame = tk.Frame(root)
113
- root.content_frame.grid(row=1, column=0, sticky="nsew")
114
- root.grid_rowconfigure(1, weight=1)
115
- root.grid_columnconfigure(0, weight=1)
116
-
117
- # Initialize the new app in the content frame
118
- app_func(root.content_frame)
119
-
120
142
  # Exit functionality only for the annotation app
121
143
  if app_name != "Annotate" and hasattr(root, 'current_app_exit_func'):
122
144
  root.next_app_func = proceed_with_app
145
+ root.next_app_args = (app_name, app_func) # Ensure correct arguments
123
146
  root.current_app_exit_func()
124
147
  else:
125
- proceed_with_app()
148
+ proceed_with_app(root, app_name, app_func)
149
+
126
150
 
127
151
  def create_menu_bar(root):
128
- from .gui_mask_app import initiate_mask_root
129
- from .gui_measure_app import initiate_measure_root
130
- from .annotate_app import initiate_annotation_app_root
131
- from .gui_make_masks_app import initiate_mask_app_root
132
- from .gui_classify_app import initiate_classify_root
152
+ from .app_mask import initiate_mask_root
153
+ from .app_measure import initiate_measure_root
154
+ from .app_annotate import initiate_annotation_app_root
155
+ from .app_make_masks import initiate_mask_app_root
156
+ from .app_classify import initiate_classify_root
157
+ from .gui import gui_app
133
158
 
134
159
  gui_apps = {
160
+ "Main App": gui_app,
135
161
  "Mask": initiate_mask_root,
136
162
  "Measure": initiate_measure_root,
137
163
  "Annotate": initiate_annotation_app_root,
@@ -381,19 +407,19 @@ def style_text_boxes_v1(style):
381
407
  background=[('active', '#66b2b2'), ('disabled', '#004d4d'), ('!disabled', '#008080')],
382
408
  foreground=[('active', '#ffffff'), ('disabled', '#888888')])
383
409
  style.configure('Custom.TLabel', padding='5 5 5 5', borderwidth=1, relief='flat', background='#000000', foreground='#ffffff', font=font_style)
384
- style.configure('TCheckbutton', background='#333333', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
410
+ style.configure('TCheckbutton', background='black', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
385
411
  style.map('TCheckbutton', background=[('selected', '#555555'), ('active', '#555555')])
386
412
 
387
413
  def style_text_boxes(style):
388
414
  font_style = tkFont.Font(family="Helvetica", size=10)
389
- style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', fieldbackground='#333333', foreground='#ffffff', font=font_style)
390
- style.configure('TCombobox', fieldbackground='#333333', background='#333333', foreground='#ffffff', font=font_style)
415
+ style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', fieldbackground='black', foreground='#ffffff', font=font_style)
416
+ style.configure('TCombobox', fieldbackground='black', background='black', foreground='#ffffff', font=font_style)
391
417
  style.configure('Custom.TButton', padding='10 10 10 10', borderwidth=1, relief='solid', background='#008080', foreground='#ffffff', font=font_style)
392
418
  style.map('Custom.TButton',
393
419
  background=[('active', '#66b2b2'), ('disabled', '#004d4d'), ('!disabled', '#008080')],
394
420
  foreground=[('active', '#ffffff'), ('disabled', '#888888')])
395
421
  style.configure('Custom.TLabel', padding='5 5 5 5', borderwidth=1, relief='flat', background='#000000', foreground='#ffffff', font=font_style)
396
- style.configure('TCheckbutton', background='#333333', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
422
+ style.configure('TCheckbutton', background='black', foreground='#ffffff', indicatoron=False, relief='flat', font=font_style)
397
423
  style.map('TCheckbutton', background=[('selected', '#555555'), ('active', '#555555')])
398
424
 
399
425