spacr 0.0.21__py3-none-any.whl → 0.0.36__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/annotate_app.py +6 -4
- spacr/chris.py +50 -0
- spacr/gui.py +144 -0
- spacr/gui_classify_app.py +69 -78
- spacr/gui_mask_app.py +111 -108
- spacr/gui_measure_app.py +109 -86
- spacr/gui_utils.py +267 -37
- spacr/io.py +4 -3
- spacr/mask_app.py +7 -4
- spacr/measure.py +4 -4
- spacr/old_code.py +1 -1
- spacr/utils.py +0 -6
- {spacr-0.0.21.dist-info → spacr-0.0.36.dist-info}/METADATA +1 -1
- {spacr-0.0.21.dist-info → spacr-0.0.36.dist-info}/RECORD +18 -16
- spacr-0.0.36.dist-info/entry_points.txt +8 -0
- spacr-0.0.21.dist-info/entry_points.txt +0 -7
- {spacr-0.0.21.dist-info → spacr-0.0.36.dist-info}/LICENSE +0 -0
- {spacr-0.0.21.dist-info → spacr-0.0.36.dist-info}/WHEEL +0 -0
- {spacr-0.0.21.dist-info → spacr-0.0.36.dist-info}/top_level.txt +0 -0
spacr/gui_mask_app.py
CHANGED
@@ -4,7 +4,6 @@ from tkinter import ttk, scrolledtext
|
|
4
4
|
from ttkthemes import ThemedTk
|
5
5
|
from matplotlib.figure import Figure
|
6
6
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
7
|
-
from matplotlib.figure import Figure
|
8
7
|
matplotlib.use('Agg')
|
9
8
|
from tkinter import filedialog
|
10
9
|
from multiprocessing import Process, Queue, Value
|
@@ -16,20 +15,42 @@ except AttributeError:
|
|
16
15
|
pass
|
17
16
|
|
18
17
|
from .logger import log_function_call
|
19
|
-
from .gui_utils import ScrollableFrame, StdoutRedirector,
|
20
|
-
from .gui_utils import
|
18
|
+
from .gui_utils import ScrollableFrame, StdoutRedirector, ToggleSwitch, CustomButton
|
19
|
+
from .gui_utils import clear_canvas, main_thread_update_function, set_dark_style, generate_fields, process_stdout_stderr, set_default_font, style_text_boxes
|
20
|
+
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
|
21
21
|
|
22
22
|
thread_control = {"run_thread": None, "stop_requested": False}
|
23
23
|
|
24
|
+
def toggle_test_mode():
|
25
|
+
global vars_dict
|
26
|
+
current_state = vars_dict['test_mode'][2].get()
|
27
|
+
new_state = not current_state
|
28
|
+
vars_dict['test_mode'][2].set(new_state)
|
29
|
+
if new_state:
|
30
|
+
test_mode_button.config(bg="blue")
|
31
|
+
else:
|
32
|
+
test_mode_button.config(bg="gray")
|
33
|
+
|
24
34
|
def toggle_advanced_settings():
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
35
|
+
global vars_dict
|
36
|
+
|
37
|
+
timelapse_settings = ['timelapse', 'timelapse_memory', 'timelapse_remove_transient', 'timelapse_mode', 'timelapse_objects', 'timelapse_displacement', 'timelapse_frame_limits', 'fps']
|
38
|
+
misc_settings = ['examples_to_plot', 'all_to_mip', 'pick_slice', 'skip_mode']
|
39
|
+
opperational_settings = ['preprocess', 'masks', 'randomize', 'batch_size', 'custom_regex', 'merge', 'normalize_plots', 'workers', 'plot', 'remove_background', 'lower_quantile']
|
40
|
+
|
41
|
+
advanced_settings = timelapse_settings+misc_settings+opperational_settings
|
42
|
+
|
43
|
+
# Toggle visibility of advanced settings
|
44
|
+
for setting in advanced_settings:
|
45
|
+
label, widget, var = vars_dict[setting]
|
46
|
+
if advanced_var.get() is False:
|
47
|
+
label.grid_remove() # Hide the label
|
48
|
+
widget.grid_remove() # Hide the widget
|
29
49
|
else:
|
30
|
-
|
50
|
+
label.grid() # Show the label
|
51
|
+
widget.grid() # Show the widget
|
31
52
|
|
32
|
-
|
53
|
+
#@log_function_call
|
33
54
|
def initiate_abort():
|
34
55
|
global thread_control
|
35
56
|
if thread_control.get("stop_requested") is not None:
|
@@ -40,25 +61,21 @@ def initiate_abort():
|
|
40
61
|
if thread_control["run_thread"].is_alive():
|
41
62
|
thread_control["run_thread"].terminate()
|
42
63
|
thread_control["run_thread"] = None
|
43
|
-
|
44
|
-
|
64
|
+
|
65
|
+
#@log_function_call
|
45
66
|
def run_mask_gui(q, fig_queue, stop_requested):
|
46
67
|
global vars_dict
|
47
68
|
process_stdout_stderr(q)
|
48
69
|
try:
|
49
70
|
settings = check_mask_gui_settings(vars_dict)
|
50
|
-
#settings = add_mask_gui_defaults(settings)
|
51
|
-
#for key in settings:
|
52
|
-
# value = settings[key]
|
53
|
-
# print(key, value, type(value))
|
54
71
|
preprocess_generate_masks_wrapper(settings, q, fig_queue)
|
55
72
|
except Exception as e:
|
56
73
|
q.put(f"Error during processing: {e}")
|
57
74
|
traceback.print_exc()
|
58
75
|
finally:
|
59
76
|
stop_requested.value = 1
|
60
|
-
|
61
|
-
|
77
|
+
|
78
|
+
#@log_function_call
|
62
79
|
def start_process(q, fig_queue):
|
63
80
|
global thread_control
|
64
81
|
if thread_control.get("run_thread") is not None:
|
@@ -68,152 +85,138 @@ def start_process(q, fig_queue):
|
|
68
85
|
thread_control["stop_requested"] = stop_requested
|
69
86
|
thread_control["run_thread"] = Process(target=run_mask_gui, args=(q, fig_queue, stop_requested))
|
70
87
|
thread_control["run_thread"].start()
|
71
|
-
|
88
|
+
|
72
89
|
def import_settings(scrollable_frame):
|
73
90
|
global vars_dict
|
74
91
|
|
75
92
|
csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
|
76
93
|
csv_settings = read_settings_from_csv(csv_file_path)
|
77
94
|
variables = mask_variables()
|
78
|
-
#variables = add_mask_gui_defaults(variables)
|
79
95
|
new_settings = update_settings_from_csv(variables, csv_settings)
|
80
96
|
vars_dict = generate_fields(new_settings, scrollable_frame)
|
81
|
-
|
82
|
-
|
83
|
-
def initiate_mask_root(width, height):
|
84
|
-
global
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
if theme in ['clam']:
|
89
|
-
root = tk.Tk()
|
90
|
-
style = ttk.Style(root)
|
91
|
-
style.theme_use(theme) #plastik, clearlooks, elegance, default was clam #alt, breeze, arc
|
92
|
-
set_dark_style(style)
|
93
|
-
elif theme in ['breeze']:
|
94
|
-
root = ThemedTk(theme="breeze")
|
95
|
-
style = ttk.Style(root)
|
96
|
-
set_dark_style(style)
|
97
|
-
|
97
|
+
|
98
|
+
#@log_function_call
|
99
|
+
def initiate_mask_root(parent_frame, width, height):
|
100
|
+
global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, advanced_var, scrollable_frame
|
101
|
+
|
102
|
+
style = ttk.Style(parent_frame)
|
103
|
+
set_dark_style(style)
|
98
104
|
style_text_boxes(style)
|
99
|
-
set_default_font(
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
105
|
+
set_default_font(parent_frame, font_name="Open Sans", size=8)
|
106
|
+
parent_frame.configure(bg='black')
|
107
|
+
parent_frame.grid_rowconfigure(0, weight=1)
|
108
|
+
parent_frame.grid_columnconfigure(0, weight=1)
|
109
|
+
|
104
110
|
fig_queue = Queue()
|
105
|
-
|
111
|
+
|
106
112
|
def _process_fig_queue():
|
107
113
|
global canvas
|
108
114
|
try:
|
109
115
|
while not fig_queue.empty():
|
110
116
|
clear_canvas(canvas)
|
111
117
|
fig = fig_queue.get_nowait()
|
112
|
-
#set_fig_text_properties(fig, font_size=8)
|
113
118
|
for ax in fig.get_axes():
|
114
119
|
ax.set_xticks([]) # Remove x-axis ticks
|
115
120
|
ax.set_yticks([]) # Remove y-axis ticks
|
116
121
|
ax.xaxis.set_visible(False) # Hide the x-axis
|
117
122
|
ax.yaxis.set_visible(False) # Hide the y-axis
|
118
|
-
#ax.title.set_fontsize(14)
|
119
|
-
#disable_interactivity(fig)
|
120
123
|
fig.tight_layout()
|
121
|
-
fig.set_facecolor('
|
124
|
+
fig.set_facecolor('black')
|
122
125
|
canvas.figure = fig
|
123
126
|
fig_width, fig_height = canvas_widget.winfo_width(), canvas_widget.winfo_height()
|
124
127
|
fig.set_size_inches(fig_width / fig.dpi, fig_height / fig.dpi, forward=True)
|
125
|
-
canvas.draw_idle()
|
128
|
+
canvas.draw_idle()
|
126
129
|
except Exception as e:
|
127
130
|
traceback.print_exc()
|
128
|
-
#pass
|
129
131
|
finally:
|
130
132
|
canvas_widget.after(100, _process_fig_queue)
|
131
|
-
|
132
|
-
# Process queue for console output
|
133
|
+
|
133
134
|
def _process_console_queue():
|
134
135
|
while not q.empty():
|
135
136
|
message = q.get_nowait()
|
136
137
|
console_output.insert(tk.END, message)
|
137
138
|
console_output.see(tk.END)
|
138
139
|
console_output.after(100, _process_console_queue)
|
139
|
-
|
140
|
-
# Vertical container for settings and console
|
141
|
-
vertical_container = tk.PanedWindow(root, orient=tk.HORIZONTAL) #VERTICAL
|
142
|
-
vertical_container.pack(fill=tk.BOTH, expand=True)
|
143
140
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
141
|
+
vertical_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
|
142
|
+
vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
|
143
|
+
parent_frame.grid_rowconfigure(0, weight=1)
|
144
|
+
parent_frame.grid_columnconfigure(0, weight=1)
|
145
|
+
|
146
|
+
# Settings Section
|
147
|
+
settings_frame = tk.Frame(vertical_container, bg='black')
|
148
|
+
vertical_container.add(settings_frame, stretch="always")
|
149
|
+
settings_label = ttk.Label(settings_frame, text="Settings", style="Custom.TLabel")
|
150
|
+
settings_label.grid(row=0, column=0, pady=10, padx=10)
|
151
|
+
scrollable_frame = ScrollableFrame(settings_frame, width=600)
|
152
|
+
scrollable_frame.grid(row=1, column=0, sticky="nsew")
|
153
|
+
settings_frame.grid_rowconfigure(1, weight=1)
|
154
|
+
settings_frame.grid_columnconfigure(0, weight=1)
|
155
|
+
|
156
|
+
# Create advanced settings checkbox
|
157
|
+
advanced_var = tk.BooleanVar(value=False)
|
158
|
+
advanced_Toggle = ToggleSwitch(scrollable_frame.scrollable_frame, text="Advanced Settings", variable=advanced_var, command=toggle_advanced_settings)
|
159
|
+
advanced_Toggle.grid(row=48, column=0, pady=10, padx=10)
|
149
160
|
variables = mask_variables()
|
150
161
|
vars_dict = generate_fields(variables, scrollable_frame)
|
151
|
-
|
152
|
-
|
153
|
-
# Debugging: print vars_dict to ensure it is populated correctly
|
154
|
-
#print("vars_dict:", vars_dict)
|
162
|
+
toggle_advanced_settings()
|
163
|
+
vars_dict['Test mode'] = (None, None, tk.BooleanVar(value=False))
|
155
164
|
|
156
|
-
#
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
165
|
+
# Button section
|
166
|
+
test_mode_button = CustomButton(scrollable_frame.scrollable_frame, text="Test Mode", command=toggle_test_mode)
|
167
|
+
test_mode_button.grid(row=47, column=1, pady=10, padx=10)
|
168
|
+
import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import Settings", command=lambda: import_settings(scrollable_frame))
|
169
|
+
import_btn.grid(row=47, column=0, pady=20, padx=20)
|
170
|
+
run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue))
|
171
|
+
run_button.grid(row=45, column=0, pady=20, padx=20)
|
172
|
+
abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
|
173
|
+
abort_button.grid(row=45, column=1, pady=20, padx=20)
|
174
|
+
progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white") # Create progress field
|
175
|
+
progress_label.grid(row=50, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
|
176
|
+
|
177
|
+
# Plot Canvas Section
|
178
|
+
plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL) # Horizontal container for Matplotlib figure and the vertical pane (for settings and console)
|
179
|
+
vertical_container.add(plot_frame, stretch="always")
|
180
|
+
figure = Figure(figsize=(30, 4), dpi=100, facecolor='black') # Matplotlib figure setup
|
162
181
|
plot = figure.add_subplot(111)
|
163
182
|
plot.plot([], []) # This creates an empty plot.
|
164
183
|
plot.axis('off')
|
165
|
-
|
166
|
-
|
167
|
-
canvas = FigureCanvasTkAgg(figure, master=horizontal_container)
|
168
|
-
canvas.get_tk_widget().configure(cursor='arrow', background='#333333', highlightthickness=0)
|
169
|
-
#canvas.get_tk_widget().configure(cursor='arrow')
|
184
|
+
canvas = FigureCanvasTkAgg(figure, master=plot_frame) # Embedd Matplotlib figure in Tkinter window
|
185
|
+
canvas.get_tk_widget().configure(cursor='arrow', background='black', highlightthickness=0)
|
170
186
|
canvas_widget = canvas.get_tk_widget()
|
171
|
-
|
187
|
+
plot_frame.add(canvas_widget, stretch="always")
|
172
188
|
canvas.draw()
|
173
189
|
canvas.figure = figure
|
174
190
|
|
175
|
-
# Console
|
176
|
-
|
177
|
-
vertical_container.add(
|
191
|
+
# Console Section
|
192
|
+
console_frame = tk.Frame(vertical_container, bg='black')
|
193
|
+
vertical_container.add(console_frame, stretch="always")
|
194
|
+
console_label = ttk.Label(console_frame, text="Console", background="black", foreground="white")
|
195
|
+
console_label.grid(row=0, column=0, pady=10, padx=10)
|
196
|
+
console_output = scrolledtext.ScrolledText(console_frame, height=10, bg='black', fg='white', insertbackground='white')
|
197
|
+
console_output.grid(row=1, column=0, sticky="nsew")
|
198
|
+
console_frame.grid_rowconfigure(1, weight=1)
|
199
|
+
console_frame.grid_columnconfigure(0, weight=1)
|
178
200
|
|
179
|
-
# Queue and redirection setup for updating console output safely
|
180
201
|
q = Queue()
|
181
202
|
sys.stdout = StdoutRedirector(console_output)
|
182
203
|
sys.stderr = StdoutRedirector(console_output)
|
183
204
|
|
184
|
-
advanced_var = tk.BooleanVar()
|
185
|
-
advanced_checkbox = ttk.Checkbutton(scrollable_frame.scrollable_frame, text="Advanced Settings", variable=advanced_var, command=toggle_advanced_settings)
|
186
|
-
advanced_checkbox.grid(row=46, column=1, pady=10, padx=10)
|
187
|
-
|
188
|
-
# This is your GUI setup where you create the Run button
|
189
|
-
run_button = ttk.Button(scrollable_frame.scrollable_frame, text="Run",command=lambda: start_process(q, fig_queue))
|
190
|
-
run_button.grid(row=45, column=0, pady=10, padx=10)
|
191
|
-
|
192
|
-
abort_button = ttk.Button(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
|
193
|
-
abort_button.grid(row=45, column=1, pady=10, padx=10)
|
194
|
-
|
195
|
-
progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="#333333", foreground="white")
|
196
|
-
progress_label.grid(row=41, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
|
197
|
-
|
198
|
-
# Create the Import Settings button
|
199
|
-
import_btn = tk.Button(root, text="Import Settings", command=lambda: import_settings(scrollable_frame))
|
200
|
-
import_btn.pack(pady=20, padx=10)
|
201
|
-
|
202
|
-
|
203
|
-
|
204
205
|
_process_console_queue()
|
205
206
|
_process_fig_queue()
|
206
|
-
create_dark_mode(root, style, console_output)
|
207
|
-
|
208
|
-
root.after(100, lambda: main_thread_update_function(root, q, fig_queue, canvas_widget, progress_label))
|
209
207
|
|
210
|
-
|
208
|
+
parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
|
209
|
+
|
210
|
+
return parent_frame, vars_dict
|
211
211
|
|
212
212
|
def gui_mask():
|
213
|
-
|
214
|
-
root
|
215
|
-
|
213
|
+
root = tk.Tk()
|
214
|
+
root.geometry("1000x800")
|
215
|
+
root.title("SpaCer: generate masks")
|
216
|
+
initiate_mask_root(root, 1000, 800)
|
217
|
+
create_menu_bar(root)
|
216
218
|
root.mainloop()
|
217
|
-
|
219
|
+
|
218
220
|
if __name__ == "__main__":
|
219
|
-
gui_mask()
|
221
|
+
gui_mask()
|
222
|
+
|
spacr/gui_measure_app.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import sys, traceback, matplotlib, ctypes
|
1
|
+
import sys, traceback, matplotlib, ctypes
|
2
2
|
import tkinter as tk
|
3
3
|
from tkinter import ttk, scrolledtext
|
4
4
|
from matplotlib.figure import Figure
|
@@ -7,7 +7,7 @@ import matplotlib.pyplot as plt
|
|
7
7
|
matplotlib.use('Agg') # Use the non-GUI Agg backend
|
8
8
|
from multiprocessing import Process, Queue, Value
|
9
9
|
from ttkthemes import ThemedTk
|
10
|
-
from tkinter import filedialog
|
10
|
+
from tkinter import filedialog
|
11
11
|
|
12
12
|
try:
|
13
13
|
ctypes.windll.shcore.SetProcessDpiAwareness(True)
|
@@ -15,21 +15,48 @@ except AttributeError:
|
|
15
15
|
pass
|
16
16
|
|
17
17
|
from .logger import log_function_call
|
18
|
-
from .gui_utils import ScrollableFrame, StdoutRedirector,
|
19
|
-
from .gui_utils import
|
18
|
+
from .gui_utils import ScrollableFrame, StdoutRedirector, CustomButton, ToggleSwitch
|
19
|
+
from .gui_utils import process_stdout_stderr, set_dark_style, set_default_font, generate_fields, main_thread_update_function, create_menu_bar
|
20
|
+
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
|
20
21
|
|
21
22
|
thread_control = {"run_thread": None, "stop_requested": False}
|
22
23
|
|
23
|
-
|
24
|
+
def toggle_test_mode():
|
25
|
+
global vars_dict
|
26
|
+
current_state = vars_dict['test_mode'][2].get()
|
27
|
+
new_state = not current_state
|
28
|
+
vars_dict['test_mode'][2].set(new_state)
|
29
|
+
if new_state:
|
30
|
+
test_mode_button.config(bg="blue")
|
31
|
+
else:
|
32
|
+
test_mode_button.config(bg="gray")
|
33
|
+
|
34
|
+
def toggle_advanced_settings():
|
35
|
+
global vars_dict
|
36
|
+
|
37
|
+
timelapse_settings = ['timelapse', 'timelapse_objects']
|
38
|
+
misc_settings = ['representative_images', 'plot', 'plot_filtration', 'include_uninfected', 'dialate_pngs', 'dialate_png_ratios']
|
39
|
+
opperational_settings = ['max_workers','experiment','cells','cell_loc','pathogens','pathogen_loc','treatments','treatment_loc','channel_of_interest','compartments','measurement','nr_imgs', 'um_per_pixel']
|
40
|
+
|
41
|
+
advanced_settings = timelapse_settings+misc_settings+opperational_settings
|
42
|
+
|
43
|
+
# Toggle visibility of advanced settings
|
44
|
+
for setting in advanced_settings:
|
45
|
+
label, widget, var = vars_dict[setting]
|
46
|
+
if advanced_var.get() is False:
|
47
|
+
label.grid_remove() # Hide the label
|
48
|
+
widget.grid_remove() # Hide the widget
|
49
|
+
else:
|
50
|
+
label.grid() # Show the label
|
51
|
+
widget.grid() # Show the widget
|
52
|
+
|
53
|
+
#@log_function_call
|
24
54
|
def run_measure_gui(q, fig_queue, stop_requested):
|
25
55
|
global vars_dict
|
26
56
|
process_stdout_stderr(q)
|
27
57
|
try:
|
28
58
|
print('hello')
|
29
59
|
settings = check_measure_gui_settings(vars_dict)
|
30
|
-
#for key in settings:
|
31
|
-
# value = settings[key]
|
32
|
-
# print(key, value, type(value))
|
33
60
|
measure_crop_wrapper(settings=settings, q=q, fig_queue=fig_queue)
|
34
61
|
except Exception as e:
|
35
62
|
q.put(f"Error during processing: {e}")
|
@@ -37,7 +64,7 @@ def run_measure_gui(q, fig_queue, stop_requested):
|
|
37
64
|
finally:
|
38
65
|
stop_requested.value = 1
|
39
66
|
|
40
|
-
|
67
|
+
#@log_function_call
|
41
68
|
def start_process(q, fig_queue):
|
42
69
|
global thread_control
|
43
70
|
if thread_control.get("run_thread") is not None:
|
@@ -48,7 +75,7 @@ def start_process(q, fig_queue):
|
|
48
75
|
thread_control["run_thread"] = Process(target=run_measure_gui, args=(q, fig_queue, stop_requested))
|
49
76
|
thread_control["run_thread"].start()
|
50
77
|
|
51
|
-
|
78
|
+
#@log_function_call
|
52
79
|
def initiate_abort():
|
53
80
|
global thread_control
|
54
81
|
if thread_control.get("stop_requested") is not None:
|
@@ -60,7 +87,7 @@ def initiate_abort():
|
|
60
87
|
thread_control["run_thread"].terminate()
|
61
88
|
thread_control["run_thread"] = None
|
62
89
|
|
63
|
-
|
90
|
+
#@log_function_call
|
64
91
|
def import_settings(scrollable_frame):
|
65
92
|
global vars_dict
|
66
93
|
|
@@ -70,29 +97,18 @@ def import_settings(scrollable_frame):
|
|
70
97
|
new_settings = update_settings_from_csv(variables, csv_settings)
|
71
98
|
vars_dict = generate_fields(new_settings, scrollable_frame)
|
72
99
|
|
73
|
-
|
74
|
-
def initiate_measure_root(width, height):
|
75
|
-
global
|
76
|
-
|
77
|
-
theme = 'breeze'
|
100
|
+
#@log_function_call
|
101
|
+
def initiate_measure_root(parent_frame, width, height):
|
102
|
+
global vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, variables, advanced_var, scrollable_frame
|
78
103
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
style = ttk.Style(root)
|
88
|
-
set_dark_style(style)
|
89
|
-
|
90
|
-
set_default_font(root, font_name="Arial", size=10)
|
91
|
-
#root.state('zoomed') # For Windows to maximize the window
|
92
|
-
root.attributes('-fullscreen', True)
|
93
|
-
root.geometry(f"{width}x{height}")
|
94
|
-
root.configure(bg='#333333')
|
95
|
-
root.title("SpaCer: generate masks")
|
104
|
+
style = ttk.Style(parent_frame)
|
105
|
+
set_dark_style(style)
|
106
|
+
style_text_boxes(style)
|
107
|
+
set_default_font(parent_frame, font_name="Open Sans", 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)
|
96
112
|
fig_queue = Queue()
|
97
113
|
|
98
114
|
def _process_fig_queue():
|
@@ -101,27 +117,22 @@ def initiate_measure_root(width, height):
|
|
101
117
|
while not fig_queue.empty():
|
102
118
|
clear_canvas(canvas)
|
103
119
|
fig = fig_queue.get_nowait()
|
104
|
-
#set_fig_text_properties(fig, font_size=8)
|
105
120
|
for ax in fig.get_axes():
|
106
121
|
ax.set_xticks([]) # Remove x-axis ticks
|
107
122
|
ax.set_yticks([]) # Remove y-axis ticks
|
108
123
|
ax.xaxis.set_visible(False) # Hide the x-axis
|
109
124
|
ax.yaxis.set_visible(False) # Hide the y-axis
|
110
|
-
#ax.title.set_fontsize(14)
|
111
|
-
#disable_interactivity(fig)
|
112
125
|
fig.tight_layout()
|
113
|
-
fig.set_facecolor('
|
126
|
+
fig.set_facecolor('black')
|
114
127
|
canvas.figure = fig
|
115
128
|
fig_width, fig_height = canvas_widget.winfo_width(), canvas_widget.winfo_height()
|
116
129
|
fig.set_size_inches(fig_width / fig.dpi, fig_height / fig.dpi, forward=True)
|
117
|
-
canvas.draw_idle()
|
130
|
+
canvas.draw_idle()
|
118
131
|
except Exception as e:
|
119
132
|
traceback.print_exc()
|
120
|
-
#pass
|
121
133
|
finally:
|
122
134
|
canvas_widget.after(100, _process_fig_queue)
|
123
|
-
|
124
|
-
# Process queue for console output
|
135
|
+
|
125
136
|
def _process_console_queue():
|
126
137
|
while not q.empty():
|
127
138
|
message = q.get_nowait()
|
@@ -129,71 +140,83 @@ def initiate_measure_root(width, height):
|
|
129
140
|
console_output.see(tk.END)
|
130
141
|
console_output.after(100, _process_console_queue)
|
131
142
|
|
132
|
-
|
133
|
-
vertical_container
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
143
|
+
vertical_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL)
|
144
|
+
vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
|
145
|
+
parent_frame.grid_rowconfigure(0, weight=1)
|
146
|
+
parent_frame.grid_columnconfigure(0, weight=1)
|
147
|
+
|
148
|
+
# Settings Section
|
149
|
+
settings_frame = tk.Frame(vertical_container, bg='black')
|
150
|
+
vertical_container.add(settings_frame, stretch="always")
|
151
|
+
settings_label = ttk.Label(settings_frame, text="Settings", background="black", foreground="white")
|
152
|
+
settings_label.grid(row=0, column=0, pady=10, padx=10)
|
153
|
+
scrollable_frame = ScrollableFrame(settings_frame, width=500)
|
154
|
+
scrollable_frame.grid(row=1, column=0, sticky="nsew")
|
155
|
+
settings_frame.grid_rowconfigure(1, weight=1)
|
156
|
+
settings_frame.grid_columnconfigure(0, weight=1)
|
157
|
+
|
158
|
+
# Create advanced settings checkbox
|
159
|
+
advanced_var = tk.BooleanVar(value=False)
|
160
|
+
advanced_Toggle = ToggleSwitch(scrollable_frame.scrollable_frame, text="Advanced Settings", variable=advanced_var, command=toggle_advanced_settings)
|
161
|
+
advanced_Toggle.grid(row=48, column=0, pady=10, padx=10)
|
141
162
|
variables = measure_variables()
|
142
163
|
vars_dict = generate_fields(variables, scrollable_frame)
|
164
|
+
toggle_advanced_settings()
|
165
|
+
vars_dict['Test mode'] = (None, None, tk.BooleanVar(value=False))
|
143
166
|
|
144
|
-
#
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
167
|
+
# Button section
|
168
|
+
test_mode_button = CustomButton(scrollable_frame.scrollable_frame, text="Test Mode", command=toggle_test_mode)
|
169
|
+
test_mode_button.grid(row=47, column=1, pady=10, padx=10)
|
170
|
+
import_btn = CustomButton(scrollable_frame.scrollable_frame, text="Import Settings", command=lambda: import_settings(scrollable_frame))
|
171
|
+
import_btn.grid(row=47, column=0, pady=20, padx=20)
|
172
|
+
run_button = CustomButton(scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue))
|
173
|
+
run_button.grid(row=45, column=0, pady=20, padx=20)
|
174
|
+
abort_button = CustomButton(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
|
175
|
+
abort_button.grid(row=45, column=1, pady=20, padx=20)
|
176
|
+
progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="black", foreground="white") # Create progress field
|
177
|
+
progress_label.grid(row=50, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
|
178
|
+
|
179
|
+
# Plot Canvas Section
|
180
|
+
plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
|
181
|
+
vertical_container.add(plot_frame, stretch="always")
|
182
|
+
figure = Figure(figsize=(30, 4), dpi=100, facecolor='black')
|
150
183
|
plot = figure.add_subplot(111)
|
151
|
-
plot.plot([], [])
|
184
|
+
plot.plot([], [])
|
152
185
|
plot.axis('off')
|
153
|
-
|
154
|
-
|
155
|
-
canvas = FigureCanvasTkAgg(figure, master=horizontal_container)
|
156
|
-
canvas.get_tk_widget().configure(cursor='arrow', background='#333333', highlightthickness=0)
|
157
|
-
#canvas.get_tk_widget().configure(cursor='arrow')
|
186
|
+
canvas = FigureCanvasTkAgg(figure, master=plot_frame)
|
187
|
+
canvas.get_tk_widget().configure(cursor='arrow', background='black', highlightthickness=0)
|
158
188
|
canvas_widget = canvas.get_tk_widget()
|
159
|
-
|
189
|
+
plot_frame.add(canvas_widget, stretch="always")
|
160
190
|
canvas.draw()
|
161
191
|
canvas.figure = figure
|
162
192
|
|
163
|
-
# Console
|
164
|
-
|
165
|
-
vertical_container.add(
|
193
|
+
# Console Section
|
194
|
+
console_frame = tk.Frame(vertical_container, bg='black')
|
195
|
+
vertical_container.add(console_frame, stretch="always")
|
196
|
+
console_label = ttk.Label(console_frame, text="Console", background="black", foreground="white")
|
197
|
+
console_label.grid(row=0, column=0, pady=10, padx=10)
|
198
|
+
console_output = scrolledtext.ScrolledText(console_frame, height=10, bg='black', fg='white', insertbackground='white')
|
199
|
+
console_output.grid(row=1, column=0, sticky="nsew")
|
200
|
+
console_frame.grid_rowconfigure(1, weight=1)
|
201
|
+
console_frame.grid_columnconfigure(0, weight=1)
|
166
202
|
|
167
|
-
# Queue and redirection setup for updating console output safely
|
168
203
|
q = Queue()
|
169
204
|
sys.stdout = StdoutRedirector(console_output)
|
170
205
|
sys.stderr = StdoutRedirector(console_output)
|
171
206
|
|
172
|
-
# This is your GUI setup where you create the Run button
|
173
|
-
run_button = ttk.Button(scrollable_frame.scrollable_frame, text="Run",command=lambda: start_process(q, fig_queue))
|
174
|
-
run_button.grid(row=40, column=0, pady=10)
|
175
|
-
|
176
|
-
abort_button = ttk.Button(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
|
177
|
-
abort_button.grid(row=40, column=1, pady=10)
|
178
|
-
|
179
|
-
progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Progress: ", background="#333333", foreground="white")
|
180
|
-
progress_label.grid(row=41, column=0, columnspan=2, sticky="ew", pady=(5, 0))
|
181
|
-
|
182
|
-
# Create the Import Settings button
|
183
|
-
import_btn = tk.Button(root, text="Import Settings", command=lambda: import_settings(scrollable_frame))
|
184
|
-
import_btn.pack(pady=20)
|
185
|
-
|
186
207
|
_process_console_queue()
|
187
208
|
_process_fig_queue()
|
188
|
-
create_dark_mode(root, style, console_output)
|
189
209
|
|
190
|
-
|
210
|
+
parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
|
191
211
|
|
192
|
-
return
|
212
|
+
return parent_frame, vars_dict
|
193
213
|
|
194
214
|
def gui_measure():
|
195
|
-
|
196
|
-
root
|
215
|
+
root = tk.Tk()
|
216
|
+
root.geometry("1000x800")
|
217
|
+
root.title("SpaCer: generate masks")
|
218
|
+
initiate_measure_root(root, 1000, 800)
|
219
|
+
create_menu_bar(root)
|
197
220
|
root.mainloop()
|
198
221
|
|
199
222
|
if __name__ == "__main__":
|