spacr 0.0.1__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_measure_app.py CHANGED
@@ -1,12 +1,10 @@
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
8
  from tkinter import filedialog
11
9
 
12
10
  try:
@@ -15,22 +13,48 @@ except AttributeError:
15
13
  pass
16
14
 
17
15
  from .logger import log_function_call
18
- from .gui_utils import ScrollableFrame, StdoutRedirector, set_dark_style, set_default_font, measure_variables, generate_fields, create_dark_mode, check_measure_gui_settings, add_measure_gui_defaults, main_thread_update_function
19
- from .gui_utils import process_stdout_stderr, measure_crop_wrapper, clear_canvas, safe_literal_eval
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
 
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
23
34
 
24
- @log_function_call
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
25
52
  def run_measure_gui(q, fig_queue, stop_requested):
26
53
  global vars_dict
27
54
  process_stdout_stderr(q)
28
55
  try:
56
+ print('hello')
29
57
  settings = check_measure_gui_settings(vars_dict)
30
- settings = add_measure_gui_defaults(settings)
31
- #for key in settings:
32
- # value = settings[key]
33
- # print(key, value, type(value))
34
58
  measure_crop_wrapper(settings=settings, q=q, fig_queue=fig_queue)
35
59
  except Exception as e:
36
60
  q.put(f"Error during processing: {e}")
@@ -38,7 +62,7 @@ def run_measure_gui(q, fig_queue, stop_requested):
38
62
  finally:
39
63
  stop_requested.value = 1
40
64
 
41
- @log_function_call
65
+ #@log_function_call
42
66
  def start_process(q, fig_queue):
43
67
  global thread_control
44
68
  if thread_control.get("run_thread") is not None:
@@ -49,7 +73,7 @@ def start_process(q, fig_queue):
49
73
  thread_control["run_thread"] = Process(target=run_measure_gui, args=(q, fig_queue, stop_requested))
50
74
  thread_control["run_thread"].start()
51
75
 
52
- @log_function_call
76
+ #@log_function_call
53
77
  def initiate_abort():
54
78
  global thread_control
55
79
  if thread_control.get("stop_requested") is not None:
@@ -61,53 +85,28 @@ def initiate_abort():
61
85
  thread_control["run_thread"].terminate()
62
86
  thread_control["run_thread"] = None
63
87
 
88
+ #@log_function_call
64
89
  def import_settings(scrollable_frame):
65
- global vars_dict, original_variables_structure
90
+ global vars_dict
66
91
 
67
92
  csv_file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
93
+ csv_settings = read_settings_from_csv(csv_file_path)
94
+ variables = measure_variables()
95
+ new_settings = update_settings_from_csv(variables, csv_settings)
96
+ vars_dict = generate_fields(new_settings, scrollable_frame)
97
+
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
68
101
 
69
- if not csv_file_path:
70
- return
71
-
72
- imported_variables = {}
73
-
74
- with open(csv_file_path, newline='') as csvfile:
75
- reader = csv.DictReader(csvfile)
76
- for row in reader:
77
- key = row['Key']
78
- value = row['Value']
79
- # Evaluate the value safely using safe_literal_eval
80
- imported_variables[key] = safe_literal_eval(value)
81
-
82
- # Track changed variables and apply the imported ones, printing changes as we go
83
- for key, var in vars_dict.items():
84
- if key in imported_variables and var.get() != imported_variables[key]:
85
- print(f"Updating '{key}' from '{var.get()}' to '{imported_variables[key]}'")
86
- var.set(imported_variables[key])
87
-
88
- @log_function_call
89
- def initiate_measure_root(width, height):
90
- global root, vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, variables
91
-
92
- theme = 'breeze'
93
-
94
- if theme in ['clam']:
95
- root = tk.Tk()
96
- style = ttk.Style(root)
97
- style.theme_use(theme) #plastik, clearlooks, elegance, default was clam #alt, breeze, arc
98
- set_dark_style(style)
99
-
100
- elif theme in ['breeze']:
101
- root = ThemedTk(theme="breeze")
102
- style = ttk.Style(root)
103
- set_dark_style(style)
104
-
105
- set_default_font(root, font_name="Arial", size=10)
106
- #root.state('zoomed') # For Windows to maximize the window
107
- root.attributes('-fullscreen', True)
108
- root.geometry(f"{width}x{height}")
109
- root.configure(bg='#333333')
110
- 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)
111
110
  fig_queue = Queue()
112
111
 
113
112
  def _process_fig_queue():
@@ -116,27 +115,22 @@ def initiate_measure_root(width, height):
116
115
  while not fig_queue.empty():
117
116
  clear_canvas(canvas)
118
117
  fig = fig_queue.get_nowait()
119
- #set_fig_text_properties(fig, font_size=8)
120
118
  for ax in fig.get_axes():
121
119
  ax.set_xticks([]) # Remove x-axis ticks
122
120
  ax.set_yticks([]) # Remove y-axis ticks
123
121
  ax.xaxis.set_visible(False) # Hide the x-axis
124
122
  ax.yaxis.set_visible(False) # Hide the y-axis
125
- #ax.title.set_fontsize(14)
126
- #disable_interactivity(fig)
127
123
  fig.tight_layout()
128
- fig.set_facecolor('#333333')
124
+ fig.set_facecolor('black')
129
125
  canvas.figure = fig
130
126
  fig_width, fig_height = canvas_widget.winfo_width(), canvas_widget.winfo_height()
131
127
  fig.set_size_inches(fig_width / fig.dpi, fig_height / fig.dpi, forward=True)
132
- canvas.draw_idle()
128
+ canvas.draw_idle()
133
129
  except Exception as e:
134
130
  traceback.print_exc()
135
- #pass
136
131
  finally:
137
132
  canvas_widget.after(100, _process_fig_queue)
138
-
139
- # Process queue for console output
133
+
140
134
  def _process_console_queue():
141
135
  while not q.empty():
142
136
  message = q.get_nowait()
@@ -144,70 +138,83 @@ def initiate_measure_root(width, height):
144
138
  console_output.see(tk.END)
145
139
  console_output.after(100, _process_console_queue)
146
140
 
147
- # Vertical container for settings and console
148
- vertical_container = tk.PanedWindow(root, orient=tk.HORIZONTAL) #VERTICAL
149
- vertical_container.pack(fill=tk.BOTH, expand=True)
150
-
151
- # Scrollable Frame for user settings
152
- scrollable_frame = ScrollableFrame(vertical_container)
153
- vertical_container.add(scrollable_frame, stretch="always")
154
-
155
- # 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)
156
160
  variables = measure_variables()
157
161
  vars_dict = generate_fields(variables, scrollable_frame)
162
+ toggle_advanced_settings()
163
+ vars_dict['Test mode'] = (None, None, tk.BooleanVar(value=False))
158
164
 
159
- # Horizontal container for Matplotlib figure and the vertical pane (for settings and console)
160
- horizontal_container = tk.PanedWindow(vertical_container, orient=tk.VERTICAL) #HORIZONTAL
161
- vertical_container.add(horizontal_container, stretch="always")
162
-
163
- # Matplotlib figure setup
164
- 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')
165
181
  plot = figure.add_subplot(111)
166
- plot.plot([], []) # This creates an empty plot.
182
+ plot.plot([], [])
167
183
  plot.axis('off')
168
-
169
- # Embedding the Matplotlib figure in the Tkinter window
170
- canvas = FigureCanvasTkAgg(figure, master=horizontal_container)
171
- canvas.get_tk_widget().configure(cursor='arrow', background='#333333', highlightthickness=0)
172
- #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)
173
186
  canvas_widget = canvas.get_tk_widget()
174
- horizontal_container.add(canvas_widget, stretch="always")
187
+ plot_frame.add(canvas_widget, stretch="always")
175
188
  canvas.draw()
189
+ canvas.figure = figure
190
+
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)
176
200
 
177
- # Console output setup below the settings
178
- console_output = scrolledtext.ScrolledText(vertical_container, height=10)
179
- vertical_container.add(console_output, stretch="always")
180
-
181
- # Queue and redirection setup for updating console output safely
182
201
  q = Queue()
183
202
  sys.stdout = StdoutRedirector(console_output)
184
203
  sys.stderr = StdoutRedirector(console_output)
185
204
 
186
- # This is your GUI setup where you create the Run button
187
- run_button = ttk.Button(scrollable_frame.scrollable_frame, text="Run",command=lambda: start_process(q, fig_queue))
188
- run_button.grid(row=40, column=0, pady=10)
189
-
190
- abort_button = ttk.Button(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
191
- abort_button.grid(row=40, column=1, pady=10)
192
-
193
- progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Progress: 0%", background="#333333", foreground="white")
194
- progress_label.grid(row=41, column=0, columnspan=2, sticky="ew", pady=(5, 0))
195
-
196
- # Create the Import Settings button
197
- import_btn = tk.Button(root, text="Import Settings", command=lambda: import_settings(scrollable_frame))
198
- import_btn.pack(pady=20)
199
-
200
205
  _process_console_queue()
201
206
  _process_fig_queue()
202
- create_dark_mode(root, style, console_output)
203
207
 
204
- 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))
205
209
 
206
- return root, vars_dict
210
+ return parent_frame, vars_dict
207
211
 
208
212
  def gui_measure():
209
- global vars_dict, root
210
- 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)
211
218
  root.mainloop()
212
219
 
213
220
  if __name__ == "__main__":
spacr/gui_sim_app.py ADDED
File without changes