spacr 1.0.7__py3-none-any.whl → 1.1.0__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_classify.py +10 -0
- spacr/app_mask.py +9 -0
- spacr/app_measure.py +9 -0
- spacr/app_sequencing.py +9 -0
- spacr/core.py +172 -1
- spacr/deep_spacr.py +296 -7
- spacr/gui.py +68 -0
- spacr/gui_core.py +319 -10
- spacr/gui_elements.py +772 -13
- spacr/gui_utils.py +301 -151
- spacr/io.py +887 -71
- spacr/logger.py +36 -0
- spacr/measure.py +206 -28
- spacr/ml.py +606 -142
- spacr/plot.py +797 -131
- spacr/sequencing.py +363 -8
- spacr/settings.py +1158 -38
- spacr/sp_stats.py +80 -12
- spacr/spacr_cellpose.py +115 -2
- spacr/submodules.py +747 -19
- spacr/timelapse.py +237 -53
- spacr/toxo.py +132 -6
- spacr/utils.py +2422 -80
- {spacr-1.0.7.dist-info → spacr-1.1.0.dist-info}/METADATA +31 -17
- {spacr-1.0.7.dist-info → spacr-1.1.0.dist-info}/RECORD +29 -29
- {spacr-1.0.7.dist-info → spacr-1.1.0.dist-info}/LICENSE +0 -0
- {spacr-1.0.7.dist-info → spacr-1.1.0.dist-info}/WHEEL +0 -0
- {spacr-1.0.7.dist-info → spacr-1.1.0.dist-info}/entry_points.txt +0 -0
- {spacr-1.0.7.dist-info → spacr-1.1.0.dist-info}/top_level.txt +0 -0
spacr/gui.py
CHANGED
@@ -7,7 +7,24 @@ from screeninfo import get_monitors
|
|
7
7
|
import webbrowser
|
8
8
|
|
9
9
|
class MainApp(tk.Tk):
|
10
|
+
"""
|
11
|
+
The main graphical user interface (GUI) window for launching various SpaCr modules.
|
12
|
+
|
13
|
+
This class creates a full-screen, themed Tkinter application with buttons to launch
|
14
|
+
sub-GUIs for image mask generation, measurement, classification, and advanced analysis
|
15
|
+
tools like regression, barcode mapping, and model activation visualization.
|
16
|
+
"""
|
10
17
|
def __init__(self, default_app=None):
|
18
|
+
"""
|
19
|
+
Initialize the SpaCr main application window.
|
20
|
+
|
21
|
+
Sets up the full-screen GUI, applies dark theme styling, registers available
|
22
|
+
sub-applications, and optionally launches a specific sub-application.
|
23
|
+
|
24
|
+
Args:
|
25
|
+
default_app (str, optional): If specified, directly launches the corresponding
|
26
|
+
application view. Should match a key in `main_gui_apps` or `additional_gui_apps`.
|
27
|
+
"""
|
11
28
|
super().__init__()
|
12
29
|
|
13
30
|
# Initialize the window
|
@@ -64,6 +81,12 @@ class MainApp(tk.Tk):
|
|
64
81
|
self.load_app(default_app, self.additional_gui_apps[default_app][0])
|
65
82
|
|
66
83
|
def create_widgets(self):
|
84
|
+
"""
|
85
|
+
Create and place all GUI widgets and layout frames.
|
86
|
+
|
87
|
+
This includes the content and inner frames, sets dark style themes,
|
88
|
+
and triggers the startup screen.
|
89
|
+
"""
|
67
90
|
create_menu_bar(self)
|
68
91
|
|
69
92
|
# Use a grid layout for centering
|
@@ -85,6 +108,12 @@ class MainApp(tk.Tk):
|
|
85
108
|
self.create_startup_screen()
|
86
109
|
|
87
110
|
def _update_wraplength(self, event):
|
111
|
+
"""
|
112
|
+
Update the wrap length of the description label based on current frame width.
|
113
|
+
|
114
|
+
Args:
|
115
|
+
event (tk.Event): The event triggering the resize (usually <Configure>).
|
116
|
+
"""
|
88
117
|
if self.description_label.winfo_exists():
|
89
118
|
# Use the actual width of the inner_frame as a proxy for full width
|
90
119
|
available_width = self.inner_frame.winfo_width()
|
@@ -92,6 +121,12 @@ class MainApp(tk.Tk):
|
|
92
121
|
self.description_label.config(wraplength=int(available_width * 0.9)) # or 0.9
|
93
122
|
|
94
123
|
def create_startup_screen(self):
|
124
|
+
"""
|
125
|
+
Create the initial screen with buttons to launch different SpaCr modules.
|
126
|
+
|
127
|
+
This function generates main and additional app buttons with tooltips and
|
128
|
+
handles layout and styling.
|
129
|
+
"""
|
95
130
|
self.clear_frame(self.inner_frame)
|
96
131
|
|
97
132
|
main_buttons_frame = tk.Frame(self.inner_frame)
|
@@ -142,6 +177,11 @@ class MainApp(tk.Tk):
|
|
142
177
|
self.inner_frame.bind("<Configure>", self._update_wraplength)
|
143
178
|
|
144
179
|
def update_description(self):
|
180
|
+
"""
|
181
|
+
Update the description label based on the currently active (highlighted) button.
|
182
|
+
|
183
|
+
If no button is active, the label is cleared.
|
184
|
+
"""
|
145
185
|
for button, desc in {**self.main_buttons, **self.additional_buttons}.items():
|
146
186
|
if button.canvas.itemcget(button.button_bg, "fill") == self.color_settings['active_color']:
|
147
187
|
self.show_description(desc)
|
@@ -149,16 +189,32 @@ class MainApp(tk.Tk):
|
|
149
189
|
self.clear_description()
|
150
190
|
|
151
191
|
def show_description(self, description):
|
192
|
+
"""
|
193
|
+
Show a specific description text in the description label.
|
194
|
+
|
195
|
+
Args:
|
196
|
+
description (str): The text to be displayed.
|
197
|
+
"""
|
152
198
|
if self.description_label.winfo_exists():
|
153
199
|
self.description_label.config(text=description)
|
154
200
|
self.description_label.update_idletasks()
|
155
201
|
|
156
202
|
def clear_description(self):
|
203
|
+
"""
|
204
|
+
Clear the content of the description label.
|
205
|
+
"""
|
157
206
|
if self.description_label.winfo_exists():
|
158
207
|
self.description_label.config(text="")
|
159
208
|
self.description_label.update_idletasks()
|
160
209
|
|
161
210
|
def load_app(self, app_name, app_func):
|
211
|
+
"""
|
212
|
+
Load and display the selected application GUI in a new frame.
|
213
|
+
|
214
|
+
Args:
|
215
|
+
app_name (str): The name of the app being loaded.
|
216
|
+
app_func (Callable): The function that initializes the app.
|
217
|
+
"""
|
162
218
|
self.clear_frame(self.inner_frame)
|
163
219
|
|
164
220
|
app_frame = tk.Frame(self.inner_frame)
|
@@ -167,10 +223,22 @@ class MainApp(tk.Tk):
|
|
167
223
|
app_func(app_frame)
|
168
224
|
|
169
225
|
def clear_frame(self, frame):
|
226
|
+
"""
|
227
|
+
Remove all widgets from a given Tkinter frame.
|
228
|
+
|
229
|
+
Args:
|
230
|
+
frame (tk.Frame): The frame to clear.
|
231
|
+
"""
|
170
232
|
for widget in frame.winfo_children():
|
171
233
|
widget.destroy()
|
172
234
|
|
173
235
|
def gui_app():
|
236
|
+
"""
|
237
|
+
Launch the main SpaCr GUI.
|
238
|
+
|
239
|
+
This function initializes and runs the `MainApp` class with no default app specified,
|
240
|
+
allowing users to select functionality from the startup screen.
|
241
|
+
"""
|
174
242
|
app = MainApp()
|
175
243
|
app.mainloop()
|
176
244
|
|
spacr/gui_core.py
CHANGED
@@ -39,6 +39,25 @@ index_control = None
|
|
39
39
|
thread_control = {"run_thread": None, "stop_requested": False}
|
40
40
|
|
41
41
|
def toggle_settings(button_scrollable_frame):
|
42
|
+
"""
|
43
|
+
Initializes and displays a dropdown menu to toggle visibility of categorized GUI settings.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
button_scrollable_frame (tk.Widget): A scrollable frame where the dropdown menu will be placed.
|
47
|
+
|
48
|
+
Raises:
|
49
|
+
ValueError: If `vars_dict` is not initialized.
|
50
|
+
|
51
|
+
Behavior:
|
52
|
+
- Imports setting categories and hides all setting widgets initially.
|
53
|
+
- Adds a dropdown menu that lets users toggle the visibility of settings belonging to each category.
|
54
|
+
- When a category is selected, it toggles visibility for all settings in that category.
|
55
|
+
- Updates the dropdown appearance based on which categories are currently active.
|
56
|
+
|
57
|
+
Globals:
|
58
|
+
vars_dict (dict): A dictionary mapping setting keys to (label, widget, _, frame) tuples.
|
59
|
+
Must be initialized before calling this function.
|
60
|
+
"""
|
42
61
|
global vars_dict
|
43
62
|
from .settings import categories
|
44
63
|
from .gui_utils import hide_all_settings
|
@@ -79,6 +98,37 @@ def toggle_settings(button_scrollable_frame):
|
|
79
98
|
vars_dict = hide_all_settings(vars_dict, categories)
|
80
99
|
|
81
100
|
def display_figure(fig):
|
101
|
+
"""
|
102
|
+
Displays a matplotlib figure within a Tkinter GUI canvas, enabling interactive features such as:
|
103
|
+
- Zooming with mouse scroll
|
104
|
+
- Navigation via left/right click
|
105
|
+
- Context menu for saving or modifying the figure
|
106
|
+
- Dynamic annotation visibility based on zoom level
|
107
|
+
|
108
|
+
Args:
|
109
|
+
fig (matplotlib.figure.Figure): The figure to display in the GUI.
|
110
|
+
|
111
|
+
Global Variables:
|
112
|
+
canvas (FigureCanvasTkAgg): The current canvas used for displaying the figure.
|
113
|
+
canvas_widget (tk.Widget): The widget associated with the canvas.
|
114
|
+
|
115
|
+
Behavior:
|
116
|
+
- Destroys any existing canvas before rendering the new figure.
|
117
|
+
- Initializes zooming around cursor position using scroll wheel.
|
118
|
+
- Binds left/right clicks to navigate between figures (via show_previous_figure / show_next_figure).
|
119
|
+
- Adds a right-click context menu to save as PNG/PDF, modify figure, or reset zoom.
|
120
|
+
- Preserves original axis limits for reset functionality.
|
121
|
+
- Dynamically toggles text label visibility depending on zoom.
|
122
|
+
- Applies consistent dark theme styling for background and context menu.
|
123
|
+
|
124
|
+
Notes:
|
125
|
+
- Assumes `show_previous_figure()`, `show_next_figure()`, `set_dark_style()`,
|
126
|
+
`save_figure_as_format()`, `modify_figure()`, and `process_fig_queue()` are defined elsewhere.
|
127
|
+
- Should be called after global `canvas` and `canvas_widget` have been initialized.
|
128
|
+
|
129
|
+
Raises:
|
130
|
+
RuntimeError: If canvas_widget is not properly initialized prior to calling this function.
|
131
|
+
"""
|
82
132
|
global canvas, canvas_widget
|
83
133
|
|
84
134
|
from .gui_elements import save_figure_as_format, modify_figure
|
@@ -290,6 +340,18 @@ def display_figure(fig):
|
|
290
340
|
process_fig_queue()
|
291
341
|
|
292
342
|
def clear_unused_figures():
|
343
|
+
"""
|
344
|
+
Clears figures from memory that are not within ±20 of the current figure index to reduce memory usage.
|
345
|
+
|
346
|
+
Globals:
|
347
|
+
figures (collections.deque): A deque of currently stored matplotlib figures.
|
348
|
+
figure_index (int): Index of the currently displayed figure.
|
349
|
+
|
350
|
+
Behavior:
|
351
|
+
- Retains only figures within 20 indices before and after the current figure_index.
|
352
|
+
- Updates the figure_index to remain within valid bounds of the updated figures deque.
|
353
|
+
"""
|
354
|
+
|
293
355
|
global figures, figure_index
|
294
356
|
|
295
357
|
lower_bound = max(0, figure_index - 20)
|
@@ -300,6 +362,20 @@ def clear_unused_figures():
|
|
300
362
|
figure_index = min(max(figure_index, 0), len(figures) - 1)
|
301
363
|
|
302
364
|
def show_previous_figure():
|
365
|
+
"""
|
366
|
+
Displays the previous figure in the global figures list, if available.
|
367
|
+
|
368
|
+
Globals:
|
369
|
+
figure_index (int): Current index of the displayed figure.
|
370
|
+
figures (list): List of matplotlib figures.
|
371
|
+
fig_queue (queue.Queue): Queue of figures to be displayed later (unused here).
|
372
|
+
index_control (tk.IntVar or custom object): UI controller for setting and tracking current index.
|
373
|
+
|
374
|
+
Behavior:
|
375
|
+
- Decrements figure_index.
|
376
|
+
- Standardizes and displays the previous figure.
|
377
|
+
- Updates index_control to reflect the new figure index.
|
378
|
+
"""
|
303
379
|
from .gui_elements import standardize_figure
|
304
380
|
global figure_index, figures, fig_queue, index_control
|
305
381
|
|
@@ -311,6 +387,20 @@ def show_previous_figure():
|
|
311
387
|
#clear_unused_figures()
|
312
388
|
|
313
389
|
def show_next_figure():
|
390
|
+
"""
|
391
|
+
Displays the next figure in the figures list or loads one from the queue if at the end.
|
392
|
+
|
393
|
+
Globals:
|
394
|
+
figure_index (int): Current index of the displayed figure.
|
395
|
+
figures (list): List of existing matplotlib figures.
|
396
|
+
fig_queue (queue.Queue): Queue of figures to display when user navigates forward.
|
397
|
+
index_control (tk.IntVar or custom object): UI control to sync figure index display.
|
398
|
+
|
399
|
+
Behavior:
|
400
|
+
- If not at the end of figures list, increments index and displays the next figure.
|
401
|
+
- If at the end and the figure queue is not empty, loads and displays the next figure from the queue.
|
402
|
+
- Updates index_control to reflect the current position.
|
403
|
+
"""
|
314
404
|
from .gui_elements import standardize_figure
|
315
405
|
global figure_index, figures, fig_queue, index_control
|
316
406
|
if figure_index is not None and figure_index < len(figures) - 1:
|
@@ -330,6 +420,27 @@ def show_next_figure():
|
|
330
420
|
display_figure(fig)
|
331
421
|
|
332
422
|
def process_fig_queue():
|
423
|
+
"""
|
424
|
+
Processes the figure queue and updates the GUI with new figures as they arrive.
|
425
|
+
|
426
|
+
Globals:
|
427
|
+
canvas (FigureCanvasTkAgg): The current canvas displaying the figure.
|
428
|
+
fig_queue (queue.Queue): Queue containing matplotlib figures to be displayed.
|
429
|
+
canvas_widget (tk.Widget): The widget holding the canvas.
|
430
|
+
parent_frame (tk.Frame): Parent frame that manages periodic GUI updates.
|
431
|
+
uppdate_frequency (int): Delay in milliseconds between re-checking the queue.
|
432
|
+
figures (collections.deque): A deque holding all currently active figures.
|
433
|
+
figure_index (int): Index of the currently displayed figure.
|
434
|
+
index_control (tk.IntVar or similar): Control object for syncing figure index in GUI.
|
435
|
+
|
436
|
+
Behavior:
|
437
|
+
- Retrieves and displays figures from fig_queue.
|
438
|
+
- Standardizes figure appearance using `standardize_figure`.
|
439
|
+
- Maintains a fixed-size deque (max 100) by discarding oldest figures.
|
440
|
+
- If no figure is currently displayed, it displays the first one.
|
441
|
+
- Sets slider/index control to match the latest figure.
|
442
|
+
- Reschedules itself using `after()` to poll for new figures continuously.
|
443
|
+
"""
|
333
444
|
global canvas, fig_queue, canvas_widget, parent_frame, uppdate_frequency, figures, figure_index, index_control
|
334
445
|
from .gui_elements import standardize_figure
|
335
446
|
|
@@ -370,8 +481,23 @@ def process_fig_queue():
|
|
370
481
|
after_id = canvas_widget.after(uppdate_frequency, process_fig_queue)
|
371
482
|
parent_frame.after_tasks.append(after_id)
|
372
483
|
|
373
|
-
|
374
484
|
def update_figure(value):
|
485
|
+
"""
|
486
|
+
Updates the currently displayed figure based on slider value.
|
487
|
+
|
488
|
+
Args:
|
489
|
+
value (str or int): Index of the figure to display.
|
490
|
+
|
491
|
+
Globals:
|
492
|
+
figure_index (int): Index of the current figure.
|
493
|
+
figures (deque): Deque of matplotlib figures.
|
494
|
+
index_control (spacrSlider): Slider control for index selection.
|
495
|
+
|
496
|
+
Effects:
|
497
|
+
- Updates the canvas with the selected figure.
|
498
|
+
- Applies standard formatting to the figure.
|
499
|
+
- Sets the slider and index state accordingly.
|
500
|
+
"""
|
375
501
|
from .gui_elements import standardize_figure
|
376
502
|
global figure_index, figures, index_control
|
377
503
|
|
@@ -388,6 +514,28 @@ def update_figure(value):
|
|
388
514
|
index_control.set_to(len(figures) - 1)
|
389
515
|
|
390
516
|
def setup_plot_section(vertical_container, settings_type):
|
517
|
+
"""
|
518
|
+
Initializes the figure display section and associated slider for navigating figures.
|
519
|
+
|
520
|
+
Args:
|
521
|
+
vertical_container (tk.PanedWindow or tk.Frame): Parent container.
|
522
|
+
settings_type (str): Mode to configure specific behaviors (e.g. 'map_barcodes').
|
523
|
+
|
524
|
+
Returns:
|
525
|
+
tuple: (canvas, canvas_widget)
|
526
|
+
|
527
|
+
Globals:
|
528
|
+
canvas, canvas_widget: For figure rendering.
|
529
|
+
figures (deque): Storage of figures.
|
530
|
+
figure_index (int): Current index.
|
531
|
+
index_control (spacrSlider): Slider widget for navigating figure list.
|
532
|
+
|
533
|
+
Behavior:
|
534
|
+
- Displays initial blank figure.
|
535
|
+
- Adds slider for figure navigation.
|
536
|
+
- Applies dark style.
|
537
|
+
- Optionally shows media for 'map_barcodes'.
|
538
|
+
"""
|
391
539
|
global canvas, canvas_widget, figures, figure_index, index_control
|
392
540
|
from .gui_utils import display_media_in_plot_frame
|
393
541
|
|
@@ -462,6 +610,17 @@ def setup_plot_section(vertical_container, settings_type):
|
|
462
610
|
return canvas, canvas_widget
|
463
611
|
|
464
612
|
def set_globals(thread_control_var, q_var, console_output_var, parent_frame_var, vars_dict_var, canvas_var, canvas_widget_var, scrollable_frame_var, fig_queue_var, progress_bar_var, usage_bars_var):
|
613
|
+
"""
|
614
|
+
Assigns external references to global variables for use throughout the GUI.
|
615
|
+
|
616
|
+
Args:
|
617
|
+
*_var: Various widget and control object references.
|
618
|
+
|
619
|
+
Globals Set:
|
620
|
+
thread_control, q, console_output, parent_frame, vars_dict,
|
621
|
+
canvas, canvas_widget, scrollable_frame, fig_queue,
|
622
|
+
progress_bar, usage_bars
|
623
|
+
"""
|
465
624
|
global thread_control, q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame, fig_queue, progress_bar, usage_bars
|
466
625
|
thread_control = thread_control_var
|
467
626
|
q = q_var
|
@@ -479,6 +638,21 @@ def set_globals(thread_control_var, q_var, console_output_var, parent_frame_var,
|
|
479
638
|
usage_bars = usage_bars_var
|
480
639
|
|
481
640
|
def import_settings(settings_type='mask'):
|
641
|
+
"""
|
642
|
+
Imports a settings CSV and applies it to the GUI panel for a specific mode.
|
643
|
+
|
644
|
+
Args:
|
645
|
+
settings_type (str): Type of settings to load ('mask', 'measure', 'classify', etc.)
|
646
|
+
|
647
|
+
Globals:
|
648
|
+
vars_dict: Dictionary of GUI widget references.
|
649
|
+
scrollable_frame: Frame that holds the settings widgets.
|
650
|
+
|
651
|
+
Behavior:
|
652
|
+
- Reads key-value settings from CSV.
|
653
|
+
- Applies them to the current settings panel.
|
654
|
+
- Updates `vars_dict` accordingly.
|
655
|
+
"""
|
482
656
|
global vars_dict, scrollable_frame, button_scrollable_frame
|
483
657
|
|
484
658
|
from .gui_utils import convert_settings_dict_for_gui, hide_all_settings
|
@@ -540,6 +714,25 @@ def import_settings(settings_type='mask'):
|
|
540
714
|
vars_dict = hide_all_settings(vars_dict, categories=None)
|
541
715
|
|
542
716
|
def setup_settings_panel(vertical_container, settings_type='mask'):
|
717
|
+
"""
|
718
|
+
Creates the scrollable settings panel for a given analysis type.
|
719
|
+
|
720
|
+
Args:
|
721
|
+
vertical_container (tk.PanedWindow or tk.Frame): Parent container.
|
722
|
+
settings_type (str): One of the predefined modes such as 'mask', 'classify', etc.
|
723
|
+
|
724
|
+
Returns:
|
725
|
+
tuple: (scrollable_frame, vars_dict)
|
726
|
+
|
727
|
+
Globals:
|
728
|
+
vars_dict: Dict mapping setting names to widget metadata.
|
729
|
+
scrollable_frame: Frame containing all input widgets.
|
730
|
+
|
731
|
+
Behavior:
|
732
|
+
- Initializes and populates settings UI.
|
733
|
+
- Loads defaults depending on `settings_type`.
|
734
|
+
- Applies theme and layout configuration.
|
735
|
+
"""
|
543
736
|
global vars_dict, scrollable_frame
|
544
737
|
from .settings import get_identify_masks_finetune_default_settings, set_default_analyze_screen, set_default_settings_preprocess_generate_masks
|
545
738
|
from .settings import get_measure_crop_settings, deep_spacr_defaults, set_default_generate_barecode_mapping, set_default_umap_image_settings
|
@@ -612,6 +805,20 @@ def setup_settings_panel(vertical_container, settings_type='mask'):
|
|
612
805
|
return scrollable_frame, vars_dict
|
613
806
|
|
614
807
|
def setup_console(vertical_container):
|
808
|
+
"""
|
809
|
+
Sets up a scrollable console output section with hover effect and dark theme styling.
|
810
|
+
|
811
|
+
Args:
|
812
|
+
vertical_container (tk.PanedWindow or tk.Frame): Parent container to attach the console.
|
813
|
+
|
814
|
+
Returns:
|
815
|
+
tuple:
|
816
|
+
console_output (tk.Text): The text widget for console output.
|
817
|
+
console_frame (tk.Frame): The frame containing the console.
|
818
|
+
|
819
|
+
Globals Set:
|
820
|
+
console_output: Reference to the console's text widget.
|
821
|
+
"""
|
615
822
|
global console_output
|
616
823
|
from .gui_elements import set_dark_style
|
617
824
|
|
@@ -669,6 +876,26 @@ def setup_console(vertical_container):
|
|
669
876
|
return console_output, console_frame
|
670
877
|
|
671
878
|
def setup_button_section(horizontal_container, settings_type='mask', run=True, abort=True, download=True, import_btn=True):
|
879
|
+
"""
|
880
|
+
Creates the button section with control buttons (run, abort, download, import) and a progress bar.
|
881
|
+
|
882
|
+
Args:
|
883
|
+
horizontal_container (tk.PanedWindow or tk.Frame): Container to add the button section.
|
884
|
+
settings_type (str): Workflow type to adjust button behavior.
|
885
|
+
run (bool): Whether to include a "Run" button.
|
886
|
+
abort (bool): Whether to include an "Abort" button.
|
887
|
+
download (bool): Whether to include a "Download" button.
|
888
|
+
import_btn (bool): Whether to include a "Settings Import" button.
|
889
|
+
|
890
|
+
Returns:
|
891
|
+
tuple:
|
892
|
+
button_scrollable_frame (spacrFrame): The frame holding the buttons.
|
893
|
+
btn_col (int): Final column index after placing buttons.
|
894
|
+
|
895
|
+
Globals Set:
|
896
|
+
run_button, abort_button, download_dataset_button, import_button, progress_bar
|
897
|
+
button_frame, button_scrollable_frame, thread_control, q, fig_queue, vars_dict
|
898
|
+
"""
|
672
899
|
global thread_control, parent_frame, button_frame, button_scrollable_frame, run_button, abort_button, download_dataset_button, import_button, q, fig_queue, vars_dict, progress_bar
|
673
900
|
from .gui_utils import download_hug_dataset
|
674
901
|
from .gui_elements import set_element_size
|
@@ -725,6 +952,23 @@ def setup_button_section(horizontal_container, settings_type='mask', run=True, a
|
|
725
952
|
return button_scrollable_frame, btn_col
|
726
953
|
|
727
954
|
def setup_usage_panel(horizontal_container, btn_col, uppdate_frequency):
|
955
|
+
"""
|
956
|
+
Creates the system usage panel displaying RAM, VRAM, GPU, and CPU core usage as progress bars.
|
957
|
+
|
958
|
+
Args:
|
959
|
+
horizontal_container (tk.PanedWindow or tk.Frame): Container for the usage panel.
|
960
|
+
btn_col (int): Starting column index from button section (not used directly here).
|
961
|
+
uppdate_frequency (int): Update interval for usage stats in milliseconds.
|
962
|
+
|
963
|
+
Returns:
|
964
|
+
tuple:
|
965
|
+
usage_scrollable_frame (spacrFrame): Frame containing the usage bars.
|
966
|
+
usage_bars (list): List of spacrProgressBar widgets for RAM, VRAM, GPU, and CPU cores.
|
967
|
+
usg_col (int): Column index used for placement in the parent container.
|
968
|
+
|
969
|
+
Globals Set:
|
970
|
+
usage_bars: List of progress bars used to update usage statistics.
|
971
|
+
"""
|
728
972
|
global usage_bars
|
729
973
|
from .gui_elements import set_dark_style, set_element_size
|
730
974
|
|
@@ -858,6 +1102,14 @@ def setup_usage_panel(horizontal_container, btn_col, uppdate_frequency):
|
|
858
1102
|
return usage_scrollable_frame, usage_bars, usg_col
|
859
1103
|
|
860
1104
|
def initiate_abort():
|
1105
|
+
"""
|
1106
|
+
Terminates the currently running threaded process if any, and resets the control flags.
|
1107
|
+
|
1108
|
+
Globals:
|
1109
|
+
thread_control (dict): Holds the active thread and abort flag.
|
1110
|
+
q (queue.Queue): Message queue for status updates.
|
1111
|
+
parent_frame: Not used directly, but kept for potential extension.
|
1112
|
+
"""
|
861
1113
|
global thread_control, q, parent_frame
|
862
1114
|
if thread_control.get("run_thread") is not None:
|
863
1115
|
try:
|
@@ -872,11 +1124,20 @@ def initiate_abort():
|
|
872
1124
|
|
873
1125
|
def check_src_folders_files(settings, settings_type, q):
|
874
1126
|
"""
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
1127
|
+
Verifies that source folder paths exist and contain the necessary subfolders and/or image files
|
1128
|
+
depending on the selected processing `settings_type`.
|
1129
|
+
|
1130
|
+
Args:
|
1131
|
+
settings (dict): A dictionary containing at least the key `"src"` with either a string path or a list of paths.
|
1132
|
+
settings_type (str): Type of operation. Supported values include:
|
1133
|
+
- 'mask': Requires image-containing subfolders or raw image files.
|
1134
|
+
- 'measure': Requires 'merged' subfolder containing `.npy` files.
|
1135
|
+
(Other types like 'regression', 'umap', 'classify' are commented out.)
|
1136
|
+
q (queue.Queue): A thread-safe queue to which error messages are pushed.
|
879
1137
|
|
1138
|
+
Returns:
|
1139
|
+
bool: `True` if validation fails (request should stop), `False` if all required paths and files exist.
|
1140
|
+
"""
|
880
1141
|
request_stop = False
|
881
1142
|
|
882
1143
|
def _folder_has_images(folder_path, image_extensions = {".png", ".jpg", ".jpeg", ".bmp", ".gif", ".tiff", ".tif", ".webp", ".npy", ".npz", "nd2", "czi", "lif"}):
|
@@ -1006,6 +1267,19 @@ def check_src_folders_files(settings, settings_type, q):
|
|
1006
1267
|
return request_stop
|
1007
1268
|
|
1008
1269
|
def start_process(q=None, fig_queue=None, settings_type='mask'):
|
1270
|
+
"""
|
1271
|
+
Starts a multiprocessing task based on the provided settings type and GUI settings.
|
1272
|
+
|
1273
|
+
Args:
|
1274
|
+
q (multiprocessing.Queue, optional): Queue for logging or progress updates.
|
1275
|
+
fig_queue (multiprocessing.Queue, optional): Queue for passing figures or plot data.
|
1276
|
+
settings_type (str): Type of processing task to run (e.g., 'mask', 'measure').
|
1277
|
+
|
1278
|
+
Globals Used:
|
1279
|
+
thread_control (dict): Controls the running thread and abort flags.
|
1280
|
+
vars_dict (dict): Holds current GUI settings.
|
1281
|
+
parent_frame (tk.Frame): Main parent GUI frame.
|
1282
|
+
"""
|
1009
1283
|
global thread_control, vars_dict, parent_frame
|
1010
1284
|
from .settings import check_settings, expected_types
|
1011
1285
|
from .gui_utils import run_function_gui, set_cpu_affinity, initialize_cuda, display_gif_in_plot_frame, print_widget_structure
|
@@ -1057,6 +1331,17 @@ def start_process(q=None, fig_queue=None, settings_type='mask'):
|
|
1057
1331
|
return
|
1058
1332
|
|
1059
1333
|
def process_console_queue():
|
1334
|
+
"""
|
1335
|
+
Periodically reads from the message queue and updates the console widget with formatted messages.
|
1336
|
+
Supports special formatting for errors, warnings, and progress updates.
|
1337
|
+
|
1338
|
+
Globals Used:
|
1339
|
+
q (Queue): Queue for status and log messages.
|
1340
|
+
console_output (tk.Text): The console widget.
|
1341
|
+
parent_frame (tk.Frame): The main GUI frame containing the console.
|
1342
|
+
progress_bar (spacrProgressBar): Progress bar updated with progress information.
|
1343
|
+
uppdate_frequency (int): Refresh rate in milliseconds.
|
1344
|
+
"""
|
1060
1345
|
global q, console_output, parent_frame, progress_bar, process_console_queue
|
1061
1346
|
|
1062
1347
|
# Initialize function attribute if it doesn't exist
|
@@ -1144,6 +1429,18 @@ def process_console_queue():
|
|
1144
1429
|
parent_frame.after_tasks.append(after_id)
|
1145
1430
|
|
1146
1431
|
def main_thread_update_function(root, q, fig_queue, canvas_widget):
|
1432
|
+
"""
|
1433
|
+
Periodically triggers updates on the GUI's canvas or figures from a queue.
|
1434
|
+
|
1435
|
+
Args:
|
1436
|
+
root (tk.Tk): Root GUI window.
|
1437
|
+
q (Queue): Message queue (currently unused inside function).
|
1438
|
+
fig_queue (Queue): Queue for figure data (currently unused inside function).
|
1439
|
+
canvas_widget (tk.Widget): Canvas widget to refresh.
|
1440
|
+
|
1441
|
+
Globals Used:
|
1442
|
+
uppdate_frequency (int): Interval for update scheduling.
|
1443
|
+
"""
|
1147
1444
|
global uppdate_frequency
|
1148
1445
|
try:
|
1149
1446
|
while not q.empty():
|
@@ -1155,7 +1452,12 @@ def main_thread_update_function(root, q, fig_queue, canvas_widget):
|
|
1155
1452
|
|
1156
1453
|
def cleanup_previous_instance():
|
1157
1454
|
"""
|
1158
|
-
Cleans up
|
1455
|
+
Cleans up any remnants of the previous application run, including GUI widgets,
|
1456
|
+
background tasks, queues, threads, and canvas elements.
|
1457
|
+
|
1458
|
+
Globals Modified:
|
1459
|
+
parent_frame, usage_bars, figures, figure_index, thread_control,
|
1460
|
+
canvas, q, fig_queue
|
1159
1461
|
"""
|
1160
1462
|
global parent_frame, usage_bars, figures, figure_index, thread_control, canvas, q, fig_queue
|
1161
1463
|
|
@@ -1215,14 +1517,21 @@ def cleanup_previous_instance():
|
|
1215
1517
|
|
1216
1518
|
def initiate_root(parent, settings_type='mask'):
|
1217
1519
|
"""
|
1218
|
-
Initializes
|
1520
|
+
Initializes and builds the GUI based on the selected settings type.
|
1219
1521
|
|
1220
1522
|
Args:
|
1221
|
-
parent (
|
1222
|
-
settings_type (str
|
1523
|
+
parent (tk.Tk or tk.Toplevel): Root window for the GUI.
|
1524
|
+
settings_type (str): Type of settings to configure (e.g., 'mask', 'measure').
|
1223
1525
|
|
1224
1526
|
Returns:
|
1225
|
-
tuple:
|
1527
|
+
tuple:
|
1528
|
+
parent_frame (tk.Frame): The root GUI container.
|
1529
|
+
vars_dict (dict): Dictionary of user-configurable variables.
|
1530
|
+
|
1531
|
+
Globals Set:
|
1532
|
+
q, fig_queue, thread_control, parent_frame, scrollable_frame,
|
1533
|
+
button_frame, vars_dict, canvas, canvas_widget, button_scrollable_frame,
|
1534
|
+
progress_bar, uppdate_frequency, figures, figure_index, index_control, usage_bars
|
1226
1535
|
"""
|
1227
1536
|
|
1228
1537
|
global q, fig_queue, thread_control, parent_frame, scrollable_frame, button_frame, vars_dict, canvas, canvas_widget, button_scrollable_frame, progress_bar, uppdate_frequency, figures, figure_index, index_control, usage_bars
|