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