spacr 0.1.11__py3-none-any.whl → 0.1.16__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,253 @@
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 .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()
251
+
252
+ if __name__ == "__main__":
253
+ gui_mask()
spacr/app_measure.py ADDED
@@ -0,0 +1,253 @@
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 .settings import get_measure_crop_settings
17
+ from .gui_utils import ScrollableFrame, StdoutRedirector, CustomButton, ToggleSwitch
18
+ from .gui_utils import process_stdout_stderr, set_dark_style, set_default_font, generate_fields, main_thread_update_function, create_menu_bar, convert_settings_dict_for_gui
19
+ from .gui_utils import measure_crop_wrapper, clear_canvas, check_measure_gui_settings, read_settings_from_csv, update_settings_from_csv, set_dark_style
20
+
21
+ thread_control = {"run_thread": None, "stop_requested": False}
22
+
23
+ def import_settings(scrollable_frame):
24
+ global vars_dict
25
+
26
+ csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
27
+ csv_settings = read_settings_from_csv(csv_file_path)
28
+ settings = get_measure_crop_settings({})
29
+ variables = convert_settings_dict_for_gui(settings)
30
+ new_settings = update_settings_from_csv(variables, csv_settings)
31
+ vars_dict = generate_fields(new_settings, scrollable_frame)
32
+
33
+ test_mode_button = None
34
+
35
+ def toggle_test_mode():
36
+ global vars_dict
37
+ current_state = vars_dict['test_mode'][2].get()
38
+ new_state = not current_state
39
+ vars_dict['test_mode'][2].set(new_state)
40
+ if new_state:
41
+ test_mode_button.config(bg="blue")
42
+ else:
43
+ test_mode_button.config(bg="gray")
44
+
45
+ def toggle_advanced_settings():
46
+ global vars_dict
47
+
48
+ timelapse_settings = ['timelapse', 'timelapse_objects']
49
+ misc_settings = ['representative_images', 'plot', 'plot_filtration', 'include_uninfected', 'dialate_pngs', 'dialate_png_ratios']
50
+ opperational_settings = ['max_workers','experiment','cells','cell_loc','pathogens','pathogen_loc','treatments','treatment_loc','channel_of_interest','compartments','measurement','nr_imgs', 'um_per_pixel']
51
+
52
+ advanced_settings = timelapse_settings+misc_settings+opperational_settings
53
+
54
+ # Toggle visibility of advanced settings
55
+ for setting in advanced_settings:
56
+ label, widget, var = vars_dict[setting]
57
+ if advanced_var.get() is False:
58
+ label.grid_remove() # Hide the label
59
+ widget.grid_remove() # Hide the widget
60
+ else:
61
+ label.grid() # Show the label
62
+ widget.grid() # Show the widget
63
+
64
+ #@log_function_call
65
+ def run_measure_gui(q, fig_queue, stop_requested):
66
+ global vars_dict
67
+ process_stdout_stderr(q)
68
+ try:
69
+ print('hello')
70
+ settings = check_measure_gui_settings(vars_dict)
71
+ measure_crop_wrapper(settings=settings, q=q, fig_queue=fig_queue)
72
+ except Exception as e:
73
+ q.put(f"Error during processing: {e}")
74
+ traceback.print_exc()
75
+ finally:
76
+ stop_requested.value = 1
77
+
78
+ #@log_function_call
79
+ def start_process(q, fig_queue):
80
+ global thread_control
81
+ if thread_control.get("run_thread") is not None:
82
+ initiate_abort()
83
+
84
+ stop_requested = Value('i', 0) # multiprocessing shared value for inter-process communication
85
+ thread_control["stop_requested"] = stop_requested
86
+ thread_control["run_thread"] = Process(target=run_measure_gui, args=(q, fig_queue, stop_requested))
87
+ thread_control["run_thread"].start()
88
+
89
+ #@log_function_call
90
+ def initiate_abort():
91
+ global thread_control
92
+ if thread_control.get("stop_requested") is not None:
93
+ thread_control["stop_requested"].value = 1
94
+
95
+ if thread_control.get("run_thread") is not None:
96
+ thread_control["run_thread"].join(timeout=5)
97
+ if thread_control["run_thread"].is_alive():
98
+ thread_control["run_thread"].terminate()
99
+ thread_control["run_thread"] = None
100
+
101
+ #@log_function_call
102
+ def initiate_measure_root(parent_frame):
103
+ global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, variables, advanced_var, scrollable_frame
104
+
105
+ style = ttk.Style(parent_frame)
106
+ set_dark_style(style)
107
+ set_default_font(parent_frame, font_name="Helvetica", size=8)
108
+
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", 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 = get_measure_crop_settings({})
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), font=('Helvetica', 10))
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 Mode", command=toggle_test_mode)
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") # Create progress field
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([], [])
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_measure():
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: measure objects")
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_measure_root(root.content_frame)
249
+ create_menu_bar(root)
250
+ root.mainloop()
251
+
252
+ if __name__ == "__main__":
253
+ gui_measure()
spacr/gui.py CHANGED
@@ -6,23 +6,23 @@ 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
14
- from .gui_utils import CustomButton, style_text_boxes, create_menu_bar
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
+ from .gui_utils import CustomButton, set_dark_style, 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
- style_text_boxes(style)
25
+ set_dark_style(style)
26
26
 
27
27
  self.gui_apps = {
28
28
  "Mask": (initiate_mask_root, "Generate cellpose masks for cells, nuclei and pathogen images."),
@@ -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
 
@@ -77,7 +74,7 @@ class MainApp(tk.Tk):
77
74
  app_func, app_desc = app_data
78
75
 
79
76
  # Create custom button with text
80
- button = CustomButton(buttons_frame, text=app_name, command=lambda app_name=app_name: self.load_app(app_name, app_func), font=('Helvetica', 12))
77
+ button = CustomButton(buttons_frame, text=app_name, command=lambda app_name=app_name, app_func=app_func: self.load_app(app_name, app_func), font=('Helvetica', 12))
81
78
  button.grid(row=i, column=0, pady=10, padx=10, sticky="w")
82
79
 
83
80
  description_label = tk.Label(buttons_frame, text=app_desc, bg="black", fg="white", wraplength=800, justify="left", font=('Helvetica', 12))
@@ -103,7 +100,6 @@ class MainApp(tk.Tk):
103
100
 
104
101
  try:
105
102
  img_path = os.path.join(os.path.dirname(__file__), 'logo_spacr.png')
106
- print(f"Trying to load logo from {img_path}")
107
103
  logo_image = Image.open(img_path)
108
104
  except (FileNotFoundError, Image.UnidentifiedImageError):
109
105
  print(f"File {img_path} not found or is not a valid image. Attempting to download from GitHub.")
@@ -120,7 +116,9 @@ class MainApp(tk.Tk):
120
116
  print(f"An error occurred while loading the logo: {e}")
121
117
  return False
122
118
  try:
123
- logo_image = logo_image.resize((800, 800), Image.Resampling.LANCZOS)
119
+ screen_height = frame.winfo_screenheight()
120
+ new_height = int(screen_height // 4)
121
+ logo_image = logo_image.resize((new_height, new_height), Image.Resampling.LANCZOS)
124
122
  logo_photo = ImageTk.PhotoImage(logo_image)
125
123
  logo_label = tk.Label(frame, image=logo_photo, bg="black")
126
124
  logo_label.image = logo_photo # Keep a reference to avoid garbage collection