spacr 0.1.6__py3-none-any.whl → 0.1.8__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/__init__.py +0 -1
- spacr/app_annotate.py +38 -524
- spacr/app_make_masks.py +30 -904
- spacr/core.py +22 -22
- spacr/deep_spacr.py +6 -6
- spacr/gui.py +38 -26
- spacr/gui_core.py +254 -160
- spacr/gui_elements.py +1192 -15
- spacr/gui_utils.py +197 -10
- spacr/gui_wrappers.py +27 -15
- spacr/measure.py +11 -12
- spacr/plot.py +53 -1
- spacr/settings.py +590 -346
- spacr/utils.py +25 -19
- {spacr-0.1.6.dist-info → spacr-0.1.8.dist-info}/METADATA +1 -1
- {spacr-0.1.6.dist-info → spacr-0.1.8.dist-info}/RECORD +20 -20
- {spacr-0.1.6.dist-info → spacr-0.1.8.dist-info}/LICENSE +0 -0
- {spacr-0.1.6.dist-info → spacr-0.1.8.dist-info}/WHEEL +0 -0
- {spacr-0.1.6.dist-info → spacr-0.1.8.dist-info}/entry_points.txt +0 -0
- {spacr-0.1.6.dist-info → spacr-0.1.8.dist-info}/top_level.txt +0 -0
spacr/gui_core.py
CHANGED
@@ -1,27 +1,24 @@
|
|
1
|
-
import os, traceback, ctypes, matplotlib, requests, csv,
|
1
|
+
import os, traceback, ctypes, matplotlib, requests, csv, matplotlib, time, requests
|
2
|
+
import matplotlib.pyplot as plt
|
2
3
|
matplotlib.use('Agg')
|
3
4
|
import tkinter as tk
|
4
5
|
from tkinter import ttk
|
5
|
-
import tkinter.font as tkFont
|
6
6
|
from tkinter import filedialog
|
7
|
-
from
|
8
|
-
from multiprocessing import
|
7
|
+
from multiprocessing import Process, Value, Queue, set_start_method
|
8
|
+
from multiprocessing.sharedctypes import Synchronized
|
9
9
|
from tkinter import ttk, scrolledtext
|
10
10
|
from matplotlib.figure import Figure
|
11
11
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
12
|
-
import time
|
13
|
-
import requests
|
14
12
|
from huggingface_hub import list_repo_files
|
15
13
|
|
16
|
-
from .settings import set_default_train_test_model, get_measure_crop_settings, set_default_settings_preprocess_generate_masks, get_analyze_reads_default_settings, set_default_umap_image_settings
|
17
|
-
from .gui_elements import create_menu_bar, spacrButton, spacrLabel, spacrFrame, spacrCheckbutton, spacrDropdownMenu ,set_dark_style, set_default_font
|
18
|
-
from . gui_run import run_mask_gui, run_measure_gui, run_classify_gui, run_sequencing_gui, run_umap_gui
|
19
|
-
|
20
14
|
try:
|
21
15
|
ctypes.windll.shcore.SetProcessDpiAwareness(True)
|
22
16
|
except AttributeError:
|
23
17
|
pass
|
24
18
|
|
19
|
+
from .settings import set_default_train_test_model, get_measure_crop_settings, set_default_settings_preprocess_generate_masks, get_analyze_reads_default_settings, set_default_umap_image_settings
|
20
|
+
from .gui_elements import create_menu_bar, spacrButton, spacrLabel, spacrFrame, spacrDropdownMenu ,set_dark_style, set_default_font
|
21
|
+
|
25
22
|
# Define global variables
|
26
23
|
q = None
|
27
24
|
console_output = None
|
@@ -37,40 +34,155 @@ thread_control = {"run_thread": None, "stop_requested": False}
|
|
37
34
|
|
38
35
|
def initiate_abort():
|
39
36
|
global thread_control
|
40
|
-
if thread_control.get("stop_requested")
|
41
|
-
|
42
|
-
thread_control["stop_requested"].value = 1
|
43
|
-
|
37
|
+
if isinstance(thread_control.get("stop_requested"), Synchronized):
|
38
|
+
thread_control["stop_requested"].value = 1
|
44
39
|
if thread_control.get("run_thread") is not None:
|
45
|
-
thread_control["run_thread"].
|
46
|
-
|
47
|
-
thread_control["run_thread"].terminate()
|
40
|
+
thread_control["run_thread"].terminate()
|
41
|
+
thread_control["run_thread"].join()
|
48
42
|
thread_control["run_thread"] = None
|
49
43
|
|
50
|
-
def
|
44
|
+
def spacrFigShow(fig_queue=None):
|
45
|
+
"""
|
46
|
+
Replacement for plt.show() that queues figures instead of displaying them.
|
47
|
+
"""
|
48
|
+
fig = plt.gcf()
|
49
|
+
if fig_queue:
|
50
|
+
fig_queue.put(fig)
|
51
|
+
else:
|
52
|
+
fig.show()
|
53
|
+
plt.close(fig)
|
54
|
+
|
55
|
+
def function_gui_wrapper(function=None, settings={}, q=None, fig_queue=None, imports=1):
|
56
|
+
|
57
|
+
"""
|
58
|
+
Wraps the run_multiple_simulations function to integrate with GUI processes.
|
59
|
+
|
60
|
+
Parameters:
|
61
|
+
- settings: dict, The settings for the run_multiple_simulations function.
|
62
|
+
- q: multiprocessing.Queue, Queue for logging messages to the GUI.
|
63
|
+
- fig_queue: multiprocessing.Queue, Queue for sending figures to the GUI.
|
64
|
+
"""
|
65
|
+
|
66
|
+
# Temporarily override plt.show
|
67
|
+
original_show = plt.show
|
68
|
+
plt.show = lambda: spacrFigShow(fig_queue)
|
69
|
+
|
70
|
+
try:
|
71
|
+
if imports == 1:
|
72
|
+
function(settings=settings)
|
73
|
+
elif imports == 2:
|
74
|
+
function(src=settings['src'], settings=settings)
|
75
|
+
except Exception as e:
|
76
|
+
# Send the error message to the GUI via the queue
|
77
|
+
errorMessage = f"Error during processing: {e}"
|
78
|
+
q.put(errorMessage)
|
79
|
+
traceback.print_exc()
|
80
|
+
finally:
|
81
|
+
# Restore the original plt.show function
|
82
|
+
plt.show = original_show
|
83
|
+
|
84
|
+
def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
|
85
|
+
from .gui_utils import process_stdout_stderr
|
86
|
+
from .core import preprocess_generate_masks, generate_ml_scores, identify_masks_finetune, check_cellpose_models, analyze_recruitment, train_cellpose, compare_cellpose_masks, analyze_plaques, generate_dataset, apply_model_to_tar
|
87
|
+
from .io import generate_cellpose_train_test
|
88
|
+
from .measure import measure_crop
|
89
|
+
from .sim import run_multiple_simulations
|
90
|
+
from .deep_spacr import train_test_model
|
91
|
+
from .sequencing import analyze_reads, map_barcodes_folder, perform_regression
|
92
|
+
process_stdout_stderr(q)
|
93
|
+
|
94
|
+
if settings_type == 'mask':
|
95
|
+
function = preprocess_generate_masks
|
96
|
+
imports = 2
|
97
|
+
elif settings_type == 'measure':
|
98
|
+
function = measure_crop
|
99
|
+
imports = 1
|
100
|
+
elif settings_type == 'simulation':
|
101
|
+
function = run_multiple_simulations
|
102
|
+
imports = 1
|
103
|
+
elif settings_type == 'sequencing':
|
104
|
+
function = analyze_reads
|
105
|
+
imports = 1
|
106
|
+
elif settings_type == 'classify':
|
107
|
+
function = train_test_model
|
108
|
+
imports = 2
|
109
|
+
elif settings_type == 'train_cellpose':
|
110
|
+
function = train_cellpose
|
111
|
+
imports = 1
|
112
|
+
elif settings_type == 'ml_analyze':
|
113
|
+
function = generate_ml_scores
|
114
|
+
imports = 2
|
115
|
+
elif settings_type == 'cellpose_masks':
|
116
|
+
function = identify_masks_finetune
|
117
|
+
imports = 1
|
118
|
+
elif settings_type == 'cellpose_all':
|
119
|
+
function = check_cellpose_models
|
120
|
+
imports = 1
|
121
|
+
elif settings_type == 'map_barcodes':
|
122
|
+
function = map_barcodes_folder
|
123
|
+
imports = 2
|
124
|
+
elif settings_type == 'regression':
|
125
|
+
function = perform_regression
|
126
|
+
imports = 2
|
127
|
+
elif settings_type == 'recruitment':
|
128
|
+
function = analyze_recruitment
|
129
|
+
imports = 2
|
130
|
+
#elif settings_type == 'cellpose_dataset':
|
131
|
+
# function = generate_cellpose_train_test
|
132
|
+
# imports = 1
|
133
|
+
#elif settings_type == 'plaques':
|
134
|
+
# function = analyze_plaques
|
135
|
+
# imports = 1
|
136
|
+
#elif settings_type == 'cellpose_compare':
|
137
|
+
# function = compare_cellpose_masks
|
138
|
+
# imports = 1
|
139
|
+
#elif settings_type == 'vision_scores':
|
140
|
+
# function = apply_model_to_tar
|
141
|
+
# imports = 1
|
142
|
+
#elif settings_type == 'vision_dataset':
|
143
|
+
# function = generate_dataset
|
144
|
+
# imports = 1
|
145
|
+
else:
|
146
|
+
raise ValueError(f"Invalid settings type: {settings_type}")
|
147
|
+
try:
|
148
|
+
function_gui_wrapper(function, settings, q, fig_queue, imports)
|
149
|
+
except Exception as e:
|
150
|
+
q.put(f"Error during processing: {e}")
|
151
|
+
traceback.print_exc()
|
152
|
+
finally:
|
153
|
+
stop_requested.value = 1
|
154
|
+
|
155
|
+
def start_process(q=None, fig_queue=None, settings_type='mask'):
|
51
156
|
global thread_control, vars_dict
|
52
|
-
from .settings import check_settings
|
157
|
+
from .settings import check_settings, expected_types
|
158
|
+
|
159
|
+
if q is None:
|
160
|
+
q = Queue()
|
161
|
+
if fig_queue is None:
|
162
|
+
fig_queue = Queue()
|
163
|
+
|
164
|
+
try:
|
165
|
+
settings = check_settings(vars_dict, expected_types, q)
|
166
|
+
except ValueError as e:
|
167
|
+
q.put(f"Error: {e}")
|
168
|
+
return
|
53
169
|
|
54
|
-
settings = check_settings(vars_dict)
|
55
170
|
if thread_control.get("run_thread") is not None:
|
56
171
|
initiate_abort()
|
57
|
-
|
172
|
+
|
173
|
+
stop_requested = Value('i', 0)
|
58
174
|
thread_control["stop_requested"] = stop_requested
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
thread_control["run_thread"] = Process(target=
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
thread_control["run_thread"] = Process(target=run_sequencing_gui, args=(settings, q, fig_queue, stop_requested))
|
67
|
-
elif settings_type == 'umap':
|
68
|
-
thread_control["run_thread"] = Process(target=run_umap_gui, args=(settings, q, fig_queue, stop_requested))
|
175
|
+
|
176
|
+
process_args = (settings_type, settings, q, fig_queue, stop_requested)
|
177
|
+
if settings_type in ['mask','measure','simulation','sequencing','classify','cellpose_dataset','train_cellpose','ml_analyze','cellpose_masks','cellpose_all','map_barcodes','regression','recruitment','plaques','cellpose_compare','vision_scores','vision_dataset']:
|
178
|
+
thread_control["run_thread"] = Process(target=run_function_gui, args=process_args)
|
179
|
+
else:
|
180
|
+
q.put(f"Error: Unknown settings type '{settings_type}'")
|
181
|
+
return
|
69
182
|
thread_control["run_thread"].start()
|
70
183
|
|
71
184
|
def import_settings(settings_type='mask'):
|
72
|
-
|
73
|
-
global vars_dict, scrollable_frame
|
185
|
+
global vars_dict, scrollable_frame, button_scrollable_frame
|
74
186
|
from .settings import generate_fields
|
75
187
|
|
76
188
|
def read_settings_from_csv(csv_file_path):
|
@@ -98,6 +210,7 @@ def import_settings(settings_type='mask'):
|
|
98
210
|
if not csv_file_path: # If no file is selected, return early
|
99
211
|
return
|
100
212
|
|
213
|
+
#vars_dict = hide_all_settings(vars_dict, categories=None)
|
101
214
|
csv_settings = read_settings_from_csv(csv_file_path)
|
102
215
|
if settings_type == 'mask':
|
103
216
|
settings = set_default_settings_preprocess_generate_masks(src='path', settings={})
|
@@ -115,6 +228,7 @@ def import_settings(settings_type='mask'):
|
|
115
228
|
variables = convert_settings_dict_for_gui(settings)
|
116
229
|
new_settings = update_settings_from_csv(variables, csv_settings)
|
117
230
|
vars_dict = generate_fields(new_settings, scrollable_frame)
|
231
|
+
vars_dict = hide_all_settings(vars_dict, categories=None)
|
118
232
|
|
119
233
|
def convert_settings_dict_for_gui(settings):
|
120
234
|
variables = {}
|
@@ -155,15 +269,19 @@ def convert_settings_dict_for_gui(settings):
|
|
155
269
|
variables[key] = ('entry', None, str(value))
|
156
270
|
return variables
|
157
271
|
|
158
|
-
def setup_settings_panel(vertical_container, settings_type='mask',
|
272
|
+
def setup_settings_panel(vertical_container, settings_type='mask', window_dimensions=[500, 1000]):
|
159
273
|
global vars_dict, scrollable_frame
|
160
|
-
from .settings import set_default_settings_preprocess_generate_masks, get_measure_crop_settings, set_default_train_test_model, get_analyze_reads_default_settings, set_default_umap_image_settings, generate_fields
|
274
|
+
from .settings import descriptions, get_identify_masks_finetune_default_settings, set_default_analyze_screen, set_default_settings_preprocess_generate_masks, get_measure_crop_settings, set_default_train_test_model, get_analyze_reads_default_settings, set_default_umap_image_settings, generate_fields, get_perform_regression_default_settings, get_train_cellpose_default_settings, get_map_barcodes_default_settings, get_analyze_recruitment_default_settings, get_check_cellpose_models_default_settings
|
275
|
+
|
276
|
+
width = (window_dimensions[0])//6
|
277
|
+
height = window_dimensions[1]
|
161
278
|
|
162
|
-
|
279
|
+
# Settings Frame
|
280
|
+
settings_frame = tk.Frame(vertical_container, bg='black', height=height, width=width)
|
163
281
|
vertical_container.add(settings_frame, stretch="always")
|
164
282
|
settings_label = spacrLabel(settings_frame, text="Settings", background="black", foreground="white", anchor='center', justify='center', align="center")
|
165
283
|
settings_label.grid(row=0, column=0, pady=10, padx=10)
|
166
|
-
scrollable_frame = spacrFrame(settings_frame, bg='black', width=
|
284
|
+
scrollable_frame = spacrFrame(settings_frame, bg='black', width=width)
|
167
285
|
scrollable_frame.grid(row=1, column=0, sticky="nsew")
|
168
286
|
settings_frame.grid_rowconfigure(1, weight=1)
|
169
287
|
settings_frame.grid_columnconfigure(0, weight=1)
|
@@ -178,9 +296,36 @@ def setup_settings_panel(vertical_container, settings_type='mask', frame_height=
|
|
178
296
|
settings = get_analyze_reads_default_settings(settings={})
|
179
297
|
elif settings_type == 'umap':
|
180
298
|
settings = set_default_umap_image_settings(settings={})
|
299
|
+
elif settings_type == 'train_cellpose':
|
300
|
+
settings = get_train_cellpose_default_settings(settings={})
|
301
|
+
elif settings_type == 'ml_analyze':
|
302
|
+
settings = set_default_analyze_screen(settings={})
|
303
|
+
elif settings_type == 'cellpose_masks':
|
304
|
+
settings = get_identify_masks_finetune_default_settings(settings={})
|
305
|
+
elif settings_type == 'cellpose_all':
|
306
|
+
settings = get_check_cellpose_models_default_settings(settings={})
|
307
|
+
elif settings_type == 'map_barcodes':
|
308
|
+
settings = get_map_barcodes_default_settings(settings={})
|
309
|
+
elif settings_type == 'regression':
|
310
|
+
settings = get_perform_regression_default_settings(settings={})
|
311
|
+
elif settings_type == 'recruitment':
|
312
|
+
settings = get_analyze_recruitment_default_settings(settings={})
|
313
|
+
#elif settings_type == 'simulation':
|
314
|
+
# settings = set_default_
|
315
|
+
#elif settings_type == 'cellpose_dataset':
|
316
|
+
# settings = set_default_
|
317
|
+
#elif settings_type == 'plaques':
|
318
|
+
# settings = set_default_
|
319
|
+
#elif settings_type == 'cellpose_compare':
|
320
|
+
# settings = set_default_
|
321
|
+
#elif settings_type == 'vision_scores':
|
322
|
+
# settings = set_default_
|
323
|
+
#elif settings_type == 'vision_dataset':
|
324
|
+
# settings = set_default_
|
181
325
|
else:
|
182
326
|
raise ValueError(f"Invalid settings type: {settings_type}")
|
183
327
|
|
328
|
+
|
184
329
|
variables = convert_settings_dict_for_gui(settings)
|
185
330
|
vars_dict = generate_fields(variables, scrollable_frame)
|
186
331
|
print("Settings panel setup complete")
|
@@ -314,19 +459,21 @@ def download_dataset(repo_id, subfolder, local_dir=None, retries=5, delay=5):
|
|
314
459
|
|
315
460
|
raise Exception("Failed to download files after multiple attempts.")
|
316
461
|
|
462
|
+
def setup_button_section(horizontal_container, settings_type='mask', window_dimensions=[500, 1000], run=True, abort=True, download=True, import_btn=True):
|
463
|
+
global button_frame, button_scrollable_frame, run_button, abort_button, download_dataset_button, import_button, q, fig_queue, vars_dict
|
464
|
+
from .settings import descriptions
|
317
465
|
|
318
|
-
|
319
|
-
|
466
|
+
width = (window_dimensions[0])//8
|
467
|
+
height = window_dimensions[1]
|
320
468
|
|
321
|
-
button_frame = tk.Frame(horizontal_container, bg='black')
|
469
|
+
button_frame = tk.Frame(horizontal_container, bg='black', height=height, width=width)
|
322
470
|
horizontal_container.add(button_frame, stretch="always", sticky="nsew")
|
323
471
|
button_frame.grid_rowconfigure(0, weight=0)
|
324
472
|
button_frame.grid_rowconfigure(1, weight=1)
|
325
473
|
button_frame.grid_columnconfigure(0, weight=1)
|
326
474
|
|
327
|
-
categories_label = spacrLabel(button_frame, text="Categories", background="black", foreground="white", font=('Helvetica', 12), anchor='center', justify='center', align="center")
|
475
|
+
categories_label = spacrLabel(button_frame, text="Categories", background="black", foreground="white", font=('Helvetica', 12), anchor='center', justify='center', align="center")
|
328
476
|
categories_label.grid(row=0, column=0, pady=10, padx=10)
|
329
|
-
|
330
477
|
button_scrollable_frame = spacrFrame(button_frame, bg='black')
|
331
478
|
button_scrollable_frame.grid(row=1, column=0, sticky="nsew")
|
332
479
|
|
@@ -355,62 +502,41 @@ def setup_button_section(horizontal_container, settings_type='mask', settings_ro
|
|
355
502
|
# Call toggle_settings after vars_dict is initialized
|
356
503
|
if vars_dict is not None:
|
357
504
|
toggle_settings(button_scrollable_frame)
|
358
|
-
return button_scrollable_frame
|
359
505
|
|
360
|
-
|
361
|
-
|
362
|
-
|
506
|
+
# Description frame
|
507
|
+
description_frame = tk.Frame(horizontal_container, bg='black', height=height, width=width)
|
508
|
+
horizontal_container.add(description_frame, stretch="always", sticky="nsew")
|
509
|
+
description_frame.grid_columnconfigure(0, weight=1) # Make the column stretch
|
510
|
+
description_label = tk.Label(description_frame, text="Module Description", bg='black', fg='white', anchor='nw', justify='left', wraplength=width-50)
|
511
|
+
description_label.grid(row=0, column=0, pady=50, padx=20, sticky='nsew') # Use sticky='nsew' to stretch the label
|
512
|
+
description_text = descriptions.get(settings_type, "No description available for this module.")
|
513
|
+
description_label.config(text=description_text)
|
363
514
|
|
364
|
-
|
365
|
-
raise ValueError("vars_dict is not initialized.")
|
515
|
+
return button_scrollable_frame
|
366
516
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
label.grid()
|
376
|
-
widget.grid()
|
517
|
+
def hide_all_settings(vars_dict, categories):
|
518
|
+
"""
|
519
|
+
Function to initially hide all settings in the GUI.
|
520
|
+
|
521
|
+
Parameters:
|
522
|
+
- categories: dict, The categories of settings with their corresponding settings.
|
523
|
+
- vars_dict: dict, The dictionary containing the settings and their corresponding widgets.
|
524
|
+
"""
|
377
525
|
|
378
|
-
|
379
|
-
|
380
|
-
category_idx = 0
|
526
|
+
if categories is None:
|
527
|
+
from .settings import categories
|
381
528
|
|
382
529
|
for category, settings in categories.items():
|
383
530
|
if any(setting in vars_dict for setting in settings):
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
style = ttk.Style()
|
394
|
-
font_style = tkFont.Font(family="Helvetica", size=12, weight="bold")
|
395
|
-
style.configure('Spacr.TCheckbutton', font=font_style, background='black', foreground='#ffffff', indicatoron=False, relief='flat')
|
396
|
-
style.map('Spacr.TCheckbutton', background=[('selected', 'black'), ('active', 'black')], foreground=[('selected', '#ffffff'), ('active', '#ffffff')])
|
397
|
-
toggle.configure(style='Spacr.TCheckbutton')
|
398
|
-
toggle.grid(row=row, column=col, sticky="w", pady=2, padx=2)
|
399
|
-
#row += 1
|
400
|
-
col += 1
|
401
|
-
category_idx += 1
|
402
|
-
|
403
|
-
if category_idx % 4 == 0:
|
404
|
-
row += 1
|
405
|
-
col = 2
|
406
|
-
|
407
|
-
for settings in categories.values():
|
408
|
-
for setting in settings:
|
409
|
-
if setting in vars_dict:
|
410
|
-
label, widget, _ = vars_dict[setting]
|
411
|
-
label.grid_remove()
|
412
|
-
widget.grid_remove()
|
413
|
-
|
531
|
+
vars_dict[category] = (None, None, tk.IntVar(value=0))
|
532
|
+
|
533
|
+
# Initially hide all settings
|
534
|
+
for setting in settings:
|
535
|
+
if setting in vars_dict:
|
536
|
+
label, widget, _ = vars_dict[setting]
|
537
|
+
label.grid_remove()
|
538
|
+
widget.grid_remove()
|
539
|
+
return vars_dict
|
414
540
|
|
415
541
|
def toggle_settings(button_scrollable_frame):
|
416
542
|
global vars_dict
|
@@ -449,16 +575,7 @@ def toggle_settings(button_scrollable_frame):
|
|
449
575
|
non_empty_categories = [category for category, settings in categories.items() if any(setting in vars_dict for setting in settings)]
|
450
576
|
category_dropdown = spacrDropdownMenu(button_scrollable_frame.scrollable_frame, category_var, non_empty_categories, command=on_category_select)
|
451
577
|
category_dropdown.grid(row=1, column=3, sticky="ew", pady=2, padx=2)
|
452
|
-
|
453
|
-
for category, settings in categories.items():
|
454
|
-
if any(setting in vars_dict for setting in settings):
|
455
|
-
vars_dict[category] = (None, None, tk.IntVar(value=0))
|
456
|
-
# Initially hide all settings
|
457
|
-
for setting in settings:
|
458
|
-
if setting in vars_dict:
|
459
|
-
label, widget, _ = vars_dict[setting]
|
460
|
-
label.grid_remove()
|
461
|
-
widget.grid_remove()
|
578
|
+
vars_dict = hide_all_settings(vars_dict, categories)
|
462
579
|
|
463
580
|
def process_fig_queue():
|
464
581
|
global canvas, fig_queue, canvas_widget, parent_frame
|
@@ -531,78 +648,55 @@ def setup_frame(parent_frame):
|
|
531
648
|
return parent_frame, vertical_container, horizontal_container
|
532
649
|
|
533
650
|
def initiate_root(parent, settings_type='mask'):
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
while not q.empty():
|
539
|
-
message = q.get_nowait()
|
540
|
-
clean_message = ansi_escape_pattern.sub('', message)
|
541
|
-
if clean_message.startswith("Progress"):
|
542
|
-
progress_label.config(text=clean_message)
|
543
|
-
if clean_message.startswith("\rProgress"):
|
544
|
-
progress_label.config(text=clean_message)
|
545
|
-
elif clean_message.startswith("Successfully"):
|
546
|
-
progress_label.config(text=clean_message)
|
547
|
-
elif clean_message.startswith("Processing"):
|
548
|
-
progress_label.config(text=clean_message)
|
549
|
-
elif clean_message.startswith("scale"):
|
550
|
-
pass
|
551
|
-
elif clean_message.startswith("plot_cropped_arrays"):
|
552
|
-
pass
|
553
|
-
elif clean_message == "" or clean_message == "\r" or clean_message.strip() == "":
|
554
|
-
pass
|
555
|
-
else:
|
556
|
-
print(clean_message)
|
557
|
-
except Exception as e:
|
558
|
-
print(f"Error updating GUI canvas: {e}")
|
559
|
-
finally:
|
560
|
-
root.after(100, lambda: main_thread_update_function(root, q, fig_queue, canvas_widget, progress_label))
|
561
|
-
|
562
|
-
global q, fig_queue, parent_frame, scrollable_frame, button_frame, vars_dict, canvas, canvas_widget, progress_label, button_scrollable_frame
|
651
|
+
global q, fig_queue, parent_frame, scrollable_frame, button_frame, vars_dict, canvas, canvas_widget, progress_label, progress_output, button_scrollable_frame
|
652
|
+
from .gui_utils import main_thread_update_function
|
653
|
+
from .gui import gui_app
|
654
|
+
set_start_method('spawn', force=True)
|
563
655
|
print("Initializing root with settings_type:", settings_type)
|
656
|
+
|
564
657
|
parent_frame = parent
|
658
|
+
parent_frame.update_idletasks()
|
659
|
+
frame_width = int(parent_frame.winfo_width())
|
660
|
+
frame_height = int(parent_frame.winfo_height())
|
661
|
+
print(frame_width, frame_height)
|
662
|
+
dims = [frame_width, frame_height]
|
565
663
|
|
566
664
|
if not hasattr(parent_frame, 'after_tasks'):
|
567
665
|
parent_frame.after_tasks = []
|
568
666
|
|
667
|
+
# Clear previous content instead of destroying the root
|
569
668
|
for widget in parent_frame.winfo_children():
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
print(f"Error destroying widget: {e}")
|
669
|
+
try:
|
670
|
+
widget.destroy()
|
671
|
+
except tk.TclError as e:
|
672
|
+
print(f"Error destroying widget: {e}")
|
575
673
|
|
576
674
|
q = Queue()
|
577
675
|
fig_queue = Queue()
|
578
676
|
parent_frame, vertical_container, horizontal_container = setup_frame(parent_frame)
|
579
|
-
scrollable_frame, vars_dict = setup_settings_panel(horizontal_container, settings_type) # Adjust height and width as needed
|
580
|
-
button_scrollable_frame = setup_button_section(horizontal_container, settings_type)
|
581
|
-
canvas, canvas_widget = setup_plot_section(vertical_container)
|
582
|
-
console_output = setup_console(vertical_container)
|
583
677
|
|
584
|
-
if settings_type
|
585
|
-
|
678
|
+
if settings_type == 'annotate':
|
679
|
+
from .app_annotate import initiate_annotation_app
|
680
|
+
initiate_annotation_app(horizontal_container)
|
681
|
+
elif settings_type == 'make_masks':
|
682
|
+
from .app_make_masks import initiate_make_mask_app
|
683
|
+
initiate_make_mask_app(horizontal_container)
|
586
684
|
else:
|
587
|
-
|
685
|
+
scrollable_frame, vars_dict = setup_settings_panel(horizontal_container, settings_type, window_dimensions=dims)
|
686
|
+
button_scrollable_frame = setup_button_section(horizontal_container, settings_type, window_dimensions=dims)
|
687
|
+
canvas, canvas_widget = setup_plot_section(vertical_container)
|
688
|
+
console_output = setup_console(vertical_container)
|
689
|
+
|
690
|
+
if settings_type in ['mask', 'measure', 'classify', 'sequencing']:
|
691
|
+
progress_output = setup_progress_frame(vertical_container)
|
692
|
+
else:
|
693
|
+
progress_output = None
|
694
|
+
|
695
|
+
set_globals(q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame, progress_label, fig_queue)
|
696
|
+
process_console_queue()
|
697
|
+
process_fig_queue()
|
698
|
+
after_id = parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
|
699
|
+
parent_frame.after_tasks.append(after_id)
|
588
700
|
|
589
|
-
set_globals(q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame, progress_label, fig_queue)
|
590
|
-
process_console_queue()
|
591
|
-
process_fig_queue()
|
592
|
-
after_id = parent_frame.after(100, lambda: main_thread_update_function(parent_frame, q, fig_queue, canvas_widget, progress_label))
|
593
|
-
parent_frame.after_tasks.append(after_id)
|
594
701
|
print("Root initialization complete")
|
595
702
|
return parent_frame, vars_dict
|
596
|
-
|
597
|
-
def start_gui_app(settings_type='mask'):
|
598
|
-
global q, fig_queue, parent_frame, scrollable_frame, vars_dict, canvas, canvas_widget, progress_label
|
599
|
-
root = tk.Tk()
|
600
|
-
width = root.winfo_screenwidth()
|
601
|
-
height = root.winfo_screenheight()
|
602
|
-
root.geometry(f"{width}x{height}")
|
603
|
-
root.title(f"SpaCr: {settings_type.capitalize()}")
|
604
|
-
root.content_frame = tk.Frame(root)
|
605
|
-
print("Starting GUI app with settings_type:", settings_type)
|
606
|
-
initiate_root(root.content_frame, settings_type)
|
607
|
-
create_menu_bar(root)
|
608
|
-
root.mainloop()
|