spacr 0.1.77__py3-none-any.whl → 0.1.85__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.py +67 -20
- spacr/gui_core.py +206 -82
- spacr/gui_elements.py +144 -79
- spacr/io.py +1 -1
- spacr/measure.py +14 -14
- spacr/settings.py +258 -97
- spacr/test_gui.py +0 -0
- {spacr-0.1.77.dist-info → spacr-0.1.85.dist-info}/METADATA +1 -1
- {spacr-0.1.77.dist-info → spacr-0.1.85.dist-info}/RECORD +13 -12
- {spacr-0.1.77.dist-info → spacr-0.1.85.dist-info}/LICENSE +0 -0
- {spacr-0.1.77.dist-info → spacr-0.1.85.dist-info}/WHEEL +0 -0
- {spacr-0.1.77.dist-info → spacr-0.1.85.dist-info}/entry_points.txt +0 -0
- {spacr-0.1.77.dist-info → spacr-0.1.85.dist-info}/top_level.txt +0 -0
spacr/gui.py
CHANGED
@@ -11,72 +11,112 @@ class MainApp(tk.Tk):
|
|
11
11
|
super().__init__()
|
12
12
|
width = self.winfo_screenwidth()
|
13
13
|
height = self.winfo_screenheight()
|
14
|
-
self.geometry(f"{width}x{height}")
|
14
|
+
self.geometry(f"{width}x{height}")
|
15
15
|
self.title("SpaCr GUI Collection")
|
16
|
-
|
16
|
+
|
17
|
+
# Initialize style and apply dark style to the main window
|
17
18
|
style = ttk.Style()
|
18
|
-
set_dark_style(style)
|
19
|
+
self.color_settings = set_dark_style(style, parent_frame=self)
|
19
20
|
|
20
|
-
self.
|
21
|
+
self.main_gui_apps = {
|
21
22
|
"Mask": (lambda frame: initiate_root(frame, 'mask'), "Generate cellpose masks for cells, nuclei and pathogen images."),
|
22
23
|
"Measure": (lambda frame: initiate_root(frame, 'measure'), "Measure single object intensity and morphological feature. Crop and save single object image"),
|
23
24
|
"Annotate": (lambda frame: initiate_root(frame, 'annotate'), "Annotation single object images on a grid. Annotations are saved to database."),
|
24
|
-
"Make Masks": (lambda frame: initiate_root(frame, 'make_masks'),"Adjust pre-existing Cellpose models to your specific dataset for improved performance"),
|
25
|
+
"Make Masks": (lambda frame: initiate_root(frame, 'make_masks'), "Adjust pre-existing Cellpose models to your specific dataset for improved performance"),
|
25
26
|
"Classify": (lambda frame: initiate_root(frame, 'classify'), "Train Torch Convolutional Neural Networks (CNNs) or Transformers to classify single object images."),
|
26
|
-
|
27
|
-
|
27
|
+
}
|
28
|
+
|
29
|
+
self.additional_gui_apps = {
|
30
|
+
"Sequencing": (lambda frame: initiate_root(frame, 'sequencing'), "Analyze sequencing data."),
|
31
|
+
"Umap": (lambda frame: initiate_root(frame, 'umap'), "Generate UMAP embeddings with datapoints represented as images."),
|
32
|
+
"Train Cellpose": (lambda frame: initiate_root(frame, 'train_cellpose'), "Train custom Cellpose models."),
|
33
|
+
"ML Analyze": (lambda frame: initiate_root(frame, 'ml_analyze'), "Machine learning analysis of data."),
|
34
|
+
"Cellpose Masks": (lambda frame: initiate_root(frame, 'cellpose_masks'), "Generate Cellpose masks."),
|
35
|
+
"Cellpose All": (lambda frame: initiate_root(frame, 'cellpose_all'), "Run Cellpose on all images."),
|
36
|
+
"Map Barcodes": (lambda frame: initiate_root(frame, 'map_barcodes'), "Map barcodes to data."),
|
37
|
+
"Regression": (lambda frame: initiate_root(frame, 'regression'), "Perform regression analysis."),
|
38
|
+
"Recruitment": (lambda frame: initiate_root(frame, 'recruitment'), "Analyze recruitment data.")
|
28
39
|
}
|
29
40
|
|
30
41
|
self.selected_app = tk.StringVar()
|
31
42
|
self.create_widgets()
|
32
43
|
|
33
|
-
if default_app in self.
|
34
|
-
self.load_app(default_app, self.
|
44
|
+
if default_app in self.main_gui_apps:
|
45
|
+
self.load_app(default_app, self.main_gui_apps[default_app][0])
|
46
|
+
elif default_app in self.additional_gui_apps:
|
47
|
+
self.load_app(default_app, self.additional_gui_apps[default_app][0])
|
35
48
|
|
36
49
|
def create_widgets(self):
|
37
50
|
# Create the menu bar
|
38
51
|
create_menu_bar(self)
|
39
52
|
|
40
53
|
# Create a canvas to hold the selected app and other elements
|
41
|
-
self.canvas = tk.Canvas(self,
|
54
|
+
self.canvas = tk.Canvas(self, highlightthickness=0)
|
42
55
|
self.canvas.grid(row=0, column=0, sticky="nsew")
|
43
56
|
self.grid_rowconfigure(0, weight=1)
|
44
57
|
self.grid_columnconfigure(0, weight=1)
|
45
58
|
|
46
59
|
# Create a frame inside the canvas to hold the main content
|
47
|
-
self.content_frame = tk.Frame(self.canvas
|
60
|
+
self.content_frame = tk.Frame(self.canvas)
|
48
61
|
self.content_frame.pack(fill=tk.BOTH, expand=True)
|
49
62
|
|
50
|
-
#
|
63
|
+
# Apply dark style to canvas and content_frame
|
64
|
+
set_dark_style(ttk.Style(), containers=[self.canvas, self.content_frame])
|
65
|
+
|
66
|
+
# Create startup screen with buttons for each main GUI app and drop-down for additional apps
|
51
67
|
self.create_startup_screen()
|
52
68
|
|
53
69
|
def create_startup_screen(self):
|
54
70
|
self.clear_frame(self.content_frame)
|
55
71
|
|
56
72
|
# Create a frame for the logo and description
|
57
|
-
logo_frame = tk.Frame(self.content_frame
|
73
|
+
logo_frame = tk.Frame(self.content_frame)
|
58
74
|
logo_frame.pack(pady=20, expand=True)
|
75
|
+
set_dark_style(ttk.Style(), containers=[logo_frame])
|
59
76
|
|
60
77
|
# Load the logo image
|
61
78
|
if not self.load_logo(logo_frame):
|
62
|
-
tk.Label(logo_frame, text="Logo not found",
|
79
|
+
logo_not_found = tk.Label(logo_frame, text="Logo not found", font=('Helvetica', 24))
|
80
|
+
logo_not_found.pack(padx=10, pady=10)
|
81
|
+
set_dark_style(ttk.Style(), widgets=[logo_not_found])
|
63
82
|
|
64
83
|
# Add SpaCr text below the logo with padding for sharper text
|
65
|
-
tk.Label(logo_frame, text="SpaCr",
|
84
|
+
spacr_label = tk.Label(logo_frame, text="SpaCr", fg=self.color_settings['active_color'], font=('Helvetica', 24))
|
85
|
+
spacr_label.pack(padx=10, pady=10)
|
86
|
+
set_dark_style(ttk.Style(), widgets=[spacr_label])
|
66
87
|
|
67
88
|
# Create a frame for the buttons and descriptions
|
68
|
-
buttons_frame = tk.Frame(self.content_frame
|
89
|
+
buttons_frame = tk.Frame(self.content_frame)
|
69
90
|
buttons_frame.pack(pady=10, expand=True, padx=10)
|
91
|
+
set_dark_style(ttk.Style(), containers=[buttons_frame])
|
70
92
|
|
71
|
-
for i, (app_name, app_data) in enumerate(self.
|
93
|
+
for i, (app_name, app_data) in enumerate(self.main_gui_apps.items()):
|
72
94
|
app_func, app_desc = app_data
|
73
95
|
|
74
96
|
# Create custom button with text
|
75
97
|
button = spacrButton(buttons_frame, text=app_name, command=lambda app_name=app_name, app_func=app_func: self.load_app(app_name, app_func), font=('Helvetica', 12))
|
76
98
|
button.grid(row=i, column=0, pady=10, padx=10, sticky="w")
|
77
99
|
|
78
|
-
description_label = tk.Label(buttons_frame, text=app_desc,
|
100
|
+
description_label = tk.Label(buttons_frame, text=app_desc, wraplength=800, justify="left", font=('Helvetica', 12))
|
79
101
|
description_label.grid(row=i, column=1, pady=10, padx=10, sticky="w")
|
102
|
+
set_dark_style(ttk.Style(), widgets=[description_label])
|
103
|
+
|
104
|
+
# Add drop-down menu for additional apps
|
105
|
+
dropdown_frame = tk.Frame(buttons_frame)
|
106
|
+
dropdown_frame.grid(row=len(self.main_gui_apps), column=0, columnspan=2, pady=20)
|
107
|
+
set_dark_style(ttk.Style(), containers=[dropdown_frame])
|
108
|
+
|
109
|
+
additional_apps_label = tk.Label(dropdown_frame, text="Additional Apps", font=('Helvetica', 12))
|
110
|
+
additional_apps_label.pack(side=tk.LEFT, padx=5)
|
111
|
+
set_dark_style(ttk.Style(), widgets=[additional_apps_label])
|
112
|
+
|
113
|
+
self.additional_apps_var = tk.StringVar(value="Select an app")
|
114
|
+
dropdown = ttk.Combobox(dropdown_frame, textvariable=self.additional_apps_var, values=list(self.additional_gui_apps.keys()))
|
115
|
+
dropdown.pack(side=tk.LEFT, padx=5)
|
116
|
+
set_dark_style(ttk.Style(), widgets=[dropdown])
|
117
|
+
|
118
|
+
load_button = spacrButton(dropdown_frame, text="Load", command=self.load_additional_app, font=('Helvetica', 12))
|
119
|
+
load_button.pack(side=tk.LEFT, padx=5)
|
80
120
|
|
81
121
|
# Ensure buttons have a fixed width
|
82
122
|
buttons_frame.grid_columnconfigure(0, minsize=150)
|
@@ -118,9 +158,10 @@ class MainApp(tk.Tk):
|
|
118
158
|
new_height = int(screen_height // 4)
|
119
159
|
logo_image = logo_image.resize((new_height, new_height), Image.Resampling.LANCZOS)
|
120
160
|
logo_photo = ImageTk.PhotoImage(logo_image)
|
121
|
-
logo_label = tk.Label(frame, image=logo_photo
|
161
|
+
logo_label = tk.Label(frame, image=logo_photo)
|
122
162
|
logo_label.image = logo_photo # Keep a reference to avoid garbage collection
|
123
163
|
logo_label.pack()
|
164
|
+
set_dark_style(ttk.Style(), widgets=[logo_label])
|
124
165
|
return True
|
125
166
|
except Exception as e:
|
126
167
|
print(f"An error occurred while processing the logo image: {e}")
|
@@ -131,10 +172,16 @@ class MainApp(tk.Tk):
|
|
131
172
|
self.clear_frame(self.content_frame)
|
132
173
|
|
133
174
|
# Initialize the selected app
|
134
|
-
app_frame = tk.Frame(self.content_frame
|
175
|
+
app_frame = tk.Frame(self.content_frame)
|
135
176
|
app_frame.pack(fill=tk.BOTH, expand=True)
|
177
|
+
set_dark_style(ttk.Style(), containers=[app_frame])
|
136
178
|
app_func(app_frame)
|
137
179
|
|
180
|
+
def load_additional_app(self):
|
181
|
+
selected_app = self.additional_apps_var.get()
|
182
|
+
if selected_app in self.additional_gui_apps:
|
183
|
+
self.load_app(selected_app, self.additional_gui_apps[selected_app][0])
|
184
|
+
|
138
185
|
def clear_frame(self, frame):
|
139
186
|
for widget in frame.winfo_children():
|
140
187
|
widget.destroy()
|
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
6
|
from tkinter import filedialog
|
6
|
-
from multiprocessing import Process, Value, Queue
|
7
|
+
from multiprocessing import Process, Value, Queue, set_start_method
|
7
8
|
from multiprocessing.sharedctypes import Synchronized
|
8
|
-
from multiprocessing import set_start_method
|
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, 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 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
|
@@ -44,26 +41,116 @@ def initiate_abort():
|
|
44
41
|
thread_control["run_thread"].join()
|
45
42
|
thread_control["run_thread"] = None
|
46
43
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
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)
|
50
54
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
+
|
56
94
|
if settings_type == 'mask':
|
57
|
-
|
95
|
+
function = preprocess_generate_masks
|
96
|
+
imports = 2
|
58
97
|
elif settings_type == 'measure':
|
59
|
-
|
60
|
-
|
61
|
-
|
98
|
+
function = measure_crop
|
99
|
+
imports = 1
|
100
|
+
elif settings_type == 'simulation':
|
101
|
+
function = run_multiple_simulations
|
102
|
+
imports = 1
|
62
103
|
elif settings_type == 'sequencing':
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
67
154
|
|
68
155
|
def start_process(q=None, fig_queue=None, settings_type='mask'):
|
69
156
|
global thread_control, vars_dict
|
@@ -83,25 +170,15 @@ def start_process(q=None, fig_queue=None, settings_type='mask'):
|
|
83
170
|
if thread_control.get("run_thread") is not None:
|
84
171
|
initiate_abort()
|
85
172
|
|
86
|
-
stop_requested = Value('i', 0)
|
173
|
+
stop_requested = Value('i', 0)
|
87
174
|
thread_control["stop_requested"] = stop_requested
|
88
175
|
|
89
|
-
process_args = (settings, q, fig_queue, stop_requested)
|
90
|
-
|
91
|
-
|
92
|
-
thread_control["run_thread"] = Process(target=run_mask_gui, args=process_args)
|
93
|
-
elif settings_type == 'measure':
|
94
|
-
thread_control["run_thread"] = Process(target=run_measure_gui, args=process_args)
|
95
|
-
elif settings_type == 'classify':
|
96
|
-
thread_control["run_thread"] = Process(target=run_classify_gui, args=process_args)
|
97
|
-
elif settings_type == 'sequencing':
|
98
|
-
thread_control["run_thread"] = Process(target=run_sequencing_gui, args=process_args)
|
99
|
-
elif settings_type == 'umap':
|
100
|
-
thread_control["run_thread"] = Process(target=run_umap_gui, args=process_args)
|
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)
|
101
179
|
else:
|
102
180
|
q.put(f"Error: Unknown settings type '{settings_type}'")
|
103
181
|
return
|
104
|
-
|
105
182
|
thread_control["run_thread"].start()
|
106
183
|
|
107
184
|
def import_settings(settings_type='mask'):
|
@@ -194,17 +271,16 @@ def convert_settings_dict_for_gui(settings):
|
|
194
271
|
|
195
272
|
def setup_settings_panel(vertical_container, settings_type='mask', window_dimensions=[500, 1000]):
|
196
273
|
global vars_dict, scrollable_frame
|
197
|
-
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 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
|
198
275
|
|
199
|
-
width = (window_dimensions[0])//6
|
276
|
+
width = (window_dimensions[0]) // 6
|
200
277
|
height = window_dimensions[1]
|
201
278
|
|
202
|
-
|
203
|
-
settings_frame = tk.Frame(vertical_container, bg='black', height=height, width=width)
|
279
|
+
settings_frame = tk.Frame(vertical_container)
|
204
280
|
vertical_container.add(settings_frame, stretch="always")
|
205
|
-
settings_label = spacrLabel(settings_frame, text="Settings",
|
281
|
+
settings_label = spacrLabel(settings_frame, text="Settings", anchor='center', justify='center', align="center")
|
206
282
|
settings_label.grid(row=0, column=0, pady=10, padx=10)
|
207
|
-
scrollable_frame = spacrFrame(settings_frame
|
283
|
+
scrollable_frame = spacrFrame(settings_frame)
|
208
284
|
scrollable_frame.grid(row=1, column=0, sticky="nsew")
|
209
285
|
settings_frame.grid_rowconfigure(1, weight=1)
|
210
286
|
settings_frame.grid_columnconfigure(0, weight=1)
|
@@ -219,11 +295,32 @@ def setup_settings_panel(vertical_container, settings_type='mask', window_dimens
|
|
219
295
|
settings = get_analyze_reads_default_settings(settings={})
|
220
296
|
elif settings_type == 'umap':
|
221
297
|
settings = set_default_umap_image_settings(settings={})
|
298
|
+
elif settings_type == 'train_cellpose':
|
299
|
+
settings = get_train_cellpose_default_settings(settings={})
|
300
|
+
elif settings_type == 'ml_analyze':
|
301
|
+
settings = set_default_analyze_screen(settings={})
|
302
|
+
elif settings_type == 'cellpose_masks':
|
303
|
+
settings = get_identify_masks_finetune_default_settings(settings={})
|
304
|
+
elif settings_type == 'cellpose_all':
|
305
|
+
settings = get_check_cellpose_models_default_settings(settings={})
|
306
|
+
elif settings_type == 'map_barcodes':
|
307
|
+
settings = get_map_barcodes_default_settings(settings={})
|
308
|
+
elif settings_type == 'regression':
|
309
|
+
settings = get_perform_regression_default_settings(settings={})
|
310
|
+
elif settings_type == 'recruitment':
|
311
|
+
settings = get_analyze_recruitment_default_settings(settings={})
|
222
312
|
else:
|
223
313
|
raise ValueError(f"Invalid settings type: {settings_type}")
|
224
314
|
|
225
315
|
variables = convert_settings_dict_for_gui(settings)
|
226
316
|
vars_dict = generate_fields(variables, scrollable_frame)
|
317
|
+
|
318
|
+
containers = [settings_frame]
|
319
|
+
widgets = [settings_label, scrollable_frame]
|
320
|
+
|
321
|
+
style = ttk.Style(vertical_container)
|
322
|
+
_ = set_dark_style(style, containers=containers, widgets=widgets)
|
323
|
+
|
227
324
|
print("Settings panel setup complete")
|
228
325
|
return scrollable_frame, vars_dict
|
229
326
|
|
@@ -231,45 +328,57 @@ def setup_plot_section(vertical_container):
|
|
231
328
|
global canvas, canvas_widget
|
232
329
|
plot_frame = tk.PanedWindow(vertical_container, orient=tk.VERTICAL)
|
233
330
|
vertical_container.add(plot_frame, stretch="always")
|
234
|
-
figure = Figure(figsize=(30, 4), dpi=100
|
331
|
+
figure = Figure(figsize=(30, 4), dpi=100)
|
235
332
|
plot = figure.add_subplot(111)
|
236
333
|
plot.plot([], []) # This creates an empty plot.
|
237
334
|
plot.axis('off')
|
238
335
|
canvas = FigureCanvasTkAgg(figure, master=plot_frame)
|
239
|
-
canvas.get_tk_widget().configure(cursor='arrow',
|
336
|
+
canvas.get_tk_widget().configure(cursor='arrow', highlightthickness=0)
|
240
337
|
canvas_widget = canvas.get_tk_widget()
|
241
338
|
plot_frame.add(canvas_widget, stretch="always")
|
242
339
|
canvas.draw()
|
243
340
|
canvas.figure = figure
|
341
|
+
# Set the figure and axes background to black
|
342
|
+
figure.patch.set_facecolor('black')
|
343
|
+
plot.set_facecolor('black')
|
344
|
+
containers = [plot_frame]
|
345
|
+
widgets = [canvas_widget]
|
346
|
+
style = ttk.Style(vertical_container)
|
347
|
+
_ = set_dark_style(style, containers=containers, widgets=widgets)
|
244
348
|
return canvas, canvas_widget
|
245
349
|
|
246
350
|
def setup_console(vertical_container):
|
247
351
|
global console_output
|
248
|
-
|
249
|
-
console_frame = tk.Frame(vertical_container, bg='black')
|
352
|
+
console_frame = tk.Frame(vertical_container)
|
250
353
|
vertical_container.add(console_frame, stretch="always")
|
251
|
-
console_label = spacrLabel(console_frame, text="Console",
|
354
|
+
console_label = spacrLabel(console_frame, text="Console", anchor='center', justify='center', align="center")
|
252
355
|
console_label.grid(row=0, column=0, pady=10, padx=10)
|
253
|
-
console_output = scrolledtext.ScrolledText(console_frame, height=10
|
356
|
+
console_output = scrolledtext.ScrolledText(console_frame, height=10)
|
254
357
|
console_output.grid(row=1, column=0, sticky="nsew")
|
255
358
|
console_frame.grid_rowconfigure(1, weight=1)
|
256
359
|
console_frame.grid_columnconfigure(0, weight=1)
|
257
|
-
|
360
|
+
containers = [console_frame]
|
361
|
+
widgets = [console_label, console_output]
|
362
|
+
style = ttk.Style(vertical_container)
|
363
|
+
_ = set_dark_style(style, containers=containers, widgets=widgets)
|
258
364
|
return console_output
|
259
365
|
|
260
366
|
def setup_progress_frame(vertical_container):
|
261
367
|
global progress_output
|
262
|
-
progress_frame = tk.Frame(vertical_container
|
368
|
+
progress_frame = tk.Frame(vertical_container)
|
263
369
|
vertical_container.add(progress_frame, stretch="always")
|
264
|
-
label_frame = tk.Frame(progress_frame
|
370
|
+
label_frame = tk.Frame(progress_frame)
|
265
371
|
label_frame.grid(row=0, column=0, sticky="ew", pady=(5, 0), padx=10)
|
266
|
-
progress_label = spacrLabel(label_frame, text="Processing: 0%",
|
372
|
+
progress_label = spacrLabel(label_frame, text="Processing: 0%", font=('Helvetica', 12), anchor='w', justify='left', align="left")
|
267
373
|
progress_label.grid(row=0, column=0, sticky="w")
|
268
|
-
progress_output = scrolledtext.ScrolledText(progress_frame, height=10
|
374
|
+
progress_output = scrolledtext.ScrolledText(progress_frame, height=10)
|
269
375
|
progress_output.grid(row=1, column=0, sticky="nsew")
|
270
376
|
progress_frame.grid_rowconfigure(1, weight=1)
|
271
377
|
progress_frame.grid_columnconfigure(0, weight=1)
|
272
|
-
|
378
|
+
containers = [progress_frame, label_frame]
|
379
|
+
widgets = [progress_label, progress_output]
|
380
|
+
style = ttk.Style(vertical_container)
|
381
|
+
_ = set_dark_style(style, containers=containers, widgets=widgets)
|
273
382
|
return progress_output
|
274
383
|
|
275
384
|
def download_hug_dataset():
|
@@ -355,59 +464,70 @@ def download_dataset(repo_id, subfolder, local_dir=None, retries=5, delay=5):
|
|
355
464
|
|
356
465
|
raise Exception("Failed to download files after multiple attempts.")
|
357
466
|
|
358
|
-
def setup_button_section(horizontal_container, settings_type='mask',
|
467
|
+
def setup_button_section(horizontal_container, settings_type='mask', window_dimensions=[500, 1000], run=True, abort=True, download=True, import_btn=True):
|
359
468
|
global button_frame, button_scrollable_frame, run_button, abort_button, download_dataset_button, import_button, q, fig_queue, vars_dict
|
360
469
|
from .settings import descriptions
|
361
470
|
|
362
|
-
width = (window_dimensions[0])//8
|
471
|
+
width = (window_dimensions[0]) // 8
|
363
472
|
height = window_dimensions[1]
|
364
473
|
|
365
|
-
button_frame = tk.Frame(horizontal_container
|
474
|
+
button_frame = tk.Frame(horizontal_container)
|
366
475
|
horizontal_container.add(button_frame, stretch="always", sticky="nsew")
|
367
476
|
button_frame.grid_rowconfigure(0, weight=0)
|
368
477
|
button_frame.grid_rowconfigure(1, weight=1)
|
369
478
|
button_frame.grid_columnconfigure(0, weight=1)
|
370
479
|
|
371
|
-
categories_label = spacrLabel(button_frame, text="Categories",
|
480
|
+
categories_label = spacrLabel(button_frame, text="Categories", anchor='center', justify='center', align="center")
|
372
481
|
categories_label.grid(row=0, column=0, pady=10, padx=10)
|
373
|
-
button_scrollable_frame = spacrFrame(button_frame
|
482
|
+
button_scrollable_frame = spacrFrame(button_frame)
|
374
483
|
button_scrollable_frame.grid(row=1, column=0, sticky="nsew")
|
375
484
|
|
485
|
+
widgets = [categories_label, button_scrollable_frame.scrollable_frame]
|
486
|
+
|
376
487
|
btn_col = 0
|
377
488
|
btn_row = 1
|
378
|
-
|
489
|
+
|
379
490
|
if run:
|
380
|
-
run_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue, settings_type)
|
491
|
+
run_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Run", command=lambda: start_process(q, fig_queue, settings_type))
|
381
492
|
run_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
|
493
|
+
widgets.append(run_button)
|
382
494
|
btn_row += 1
|
383
495
|
|
384
496
|
if abort and settings_type in ['mask', 'measure', 'classify', 'sequencing', 'umap']:
|
385
|
-
abort_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort
|
497
|
+
abort_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
|
386
498
|
abort_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
|
499
|
+
widgets.append(abort_button)
|
387
500
|
btn_row += 1
|
388
501
|
|
389
502
|
if download and settings_type in ['mask']:
|
390
|
-
download_dataset_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Download", command=download_hug_dataset
|
503
|
+
download_dataset_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Download", command=download_hug_dataset)
|
391
504
|
download_dataset_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
|
505
|
+
widgets.append(download_dataset_button)
|
392
506
|
btn_row += 1
|
393
507
|
|
394
508
|
if import_btn:
|
395
|
-
import_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(settings_type)
|
509
|
+
import_button = spacrButton(button_scrollable_frame.scrollable_frame, text="Import", command=lambda: import_settings(settings_type))
|
396
510
|
import_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
|
511
|
+
widgets.append(import_button)
|
397
512
|
|
398
|
-
# Call toggle_settings after vars_dict is initialized
|
399
513
|
if vars_dict is not None:
|
400
514
|
toggle_settings(button_scrollable_frame)
|
401
515
|
|
402
|
-
|
403
|
-
description_frame = tk.Frame(horizontal_container, bg='black', height=height, width=width)
|
516
|
+
description_frame = tk.Frame(horizontal_container)
|
404
517
|
horizontal_container.add(description_frame, stretch="always", sticky="nsew")
|
405
|
-
|
406
|
-
description_label.
|
518
|
+
description_frame.grid_columnconfigure(0, weight=1)
|
519
|
+
description_label = tk.Label(description_frame, text="Module Description", anchor='nw', justify='left', wraplength=width - 50)
|
520
|
+
description_label.grid(row=0, column=0, pady=50, padx=20, sticky='nsew')
|
407
521
|
description_text = descriptions.get(settings_type, "No description available for this module.")
|
408
522
|
description_label.config(text=description_text)
|
409
523
|
|
410
|
-
|
524
|
+
containers = [button_frame, description_frame]
|
525
|
+
widgets.extend([description_label])
|
526
|
+
|
527
|
+
style = ttk.Style(horizontal_container)
|
528
|
+
_ = set_dark_style(style, containers=containers, widgets=widgets)
|
529
|
+
|
530
|
+
return button_frame, button_scrollable_frame, description_frame, description_label
|
411
531
|
|
412
532
|
def hide_all_settings(vars_dict, categories):
|
413
533
|
"""
|
@@ -456,7 +576,6 @@ def toggle_settings(button_scrollable_frame):
|
|
456
576
|
def on_category_select(selected_category):
|
457
577
|
if selected_category == "Select Category":
|
458
578
|
return
|
459
|
-
#print(f"Selected category: {selected_category}")
|
460
579
|
if selected_category in categories:
|
461
580
|
toggle_category(categories[selected_category])
|
462
581
|
if selected_category in active_categories:
|
@@ -464,7 +583,7 @@ def toggle_settings(button_scrollable_frame):
|
|
464
583
|
else:
|
465
584
|
active_categories.add(selected_category)
|
466
585
|
category_dropdown.update_styles(active_categories)
|
467
|
-
category_var.set("Select Category")
|
586
|
+
category_var.set("Select Category")
|
468
587
|
|
469
588
|
category_var = tk.StringVar()
|
470
589
|
non_empty_categories = [category for category, settings in categories.items() if any(setting in vars_dict for setting in settings)]
|
@@ -522,24 +641,29 @@ def set_globals(q_var, console_output_var, parent_frame_var, vars_dict_var, canv
|
|
522
641
|
progress_label = progress_label_var
|
523
642
|
fig_queue = fig_queue_var
|
524
643
|
|
644
|
+
def create_containers(parent_frame):
|
645
|
+
vertical_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL)
|
646
|
+
horizontal_container = tk.PanedWindow(vertical_container, orient=tk.HORIZONTAL)
|
647
|
+
settings_frame = tk.Frame(horizontal_container)
|
648
|
+
return vertical_container, horizontal_container, settings_frame
|
649
|
+
|
525
650
|
def setup_frame(parent_frame):
|
526
651
|
style = ttk.Style(parent_frame)
|
527
|
-
|
652
|
+
vertical_container, horizontal_container, settings_frame = create_containers(parent_frame)
|
653
|
+
containers = [vertical_container, horizontal_container, settings_frame]
|
654
|
+
|
655
|
+
set_dark_style(style, parent_frame, containers)
|
528
656
|
set_default_font(parent_frame, font_name="Helvetica", size=8)
|
529
|
-
|
530
|
-
parent_frame.grid_rowconfigure(0, weight=1)
|
531
|
-
parent_frame.grid_columnconfigure(0, weight=1)
|
532
|
-
vertical_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL, bg='black')
|
657
|
+
|
533
658
|
vertical_container.grid(row=0, column=0, sticky=tk.NSEW)
|
534
|
-
horizontal_container = tk.PanedWindow(vertical_container, orient=tk.HORIZONTAL, bg='black')
|
535
659
|
vertical_container.add(horizontal_container, stretch="always")
|
536
660
|
horizontal_container.grid_columnconfigure(0, weight=1)
|
537
661
|
horizontal_container.grid_columnconfigure(1, weight=1)
|
538
|
-
settings_frame = tk.Frame(horizontal_container, bg='black')
|
539
662
|
settings_frame.grid_rowconfigure(0, weight=0)
|
540
663
|
settings_frame.grid_rowconfigure(1, weight=1)
|
541
664
|
settings_frame.grid_columnconfigure(0, weight=1)
|
542
665
|
horizontal_container.add(settings_frame, stretch="always", sticky="nsew")
|
666
|
+
|
543
667
|
return parent_frame, vertical_container, horizontal_container
|
544
668
|
|
545
669
|
def initiate_root(parent, settings_type='mask'):
|