spacr 0.1.85__tar.gz → 0.2.1__tar.gz
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-0.1.85/spacr.egg-info → spacr-0.2.1}/PKG-INFO +1 -1
- {spacr-0.1.85 → spacr-0.2.1}/setup.py +2 -2
- {spacr-0.1.85 → spacr-0.2.1}/spacr/__init__.py +6 -2
- {spacr-0.1.85 → spacr-0.2.1}/spacr/app_annotate.py +6 -5
- {spacr-0.1.85 → spacr-0.2.1}/spacr/app_make_masks.py +8 -15
- {spacr-0.1.85 → spacr-0.2.1}/spacr/core.py +1 -1
- spacr-0.2.1/spacr/gui.py +157 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/gui_core.py +43 -16
- {spacr-0.1.85 → spacr-0.2.1}/spacr/gui_elements.py +116 -25
- {spacr-0.1.85 → spacr-0.2.1}/spacr/gui_utils.py +3 -3
- spacr-0.2.1/spacr/resources/icons/abort.png +0 -0
- spacr-0.2.1/spacr/resources/icons/annotate.png +0 -0
- spacr-0.2.1/spacr/resources/icons/cellpose_masks.png +0 -0
- spacr-0.2.1/spacr/resources/icons/classify.png +0 -0
- spacr-0.2.1/spacr/resources/icons/default.png +0 -0
- spacr-0.2.1/spacr/resources/icons/download.png +0 -0
- spacr-0.2.1/spacr/resources/icons/logo_spacr.png +0 -0
- spacr-0.2.1/spacr/resources/icons/make_masks.png +0 -0
- spacr-0.2.1/spacr/resources/icons/map_barcodes.png +0 -0
- spacr-0.2.1/spacr/resources/icons/mask.png +0 -0
- spacr-0.2.1/spacr/resources/icons/measure.png +0 -0
- spacr-0.2.1/spacr/resources/icons/regression.png +0 -0
- spacr-0.2.1/spacr/resources/icons/run.png +0 -0
- spacr-0.2.1/spacr/resources/icons/sequencing.png +0 -0
- spacr-0.2.1/spacr/resources/icons/settings.png +0 -0
- spacr-0.2.1/spacr/resources/icons/train_cellpose.png +0 -0
- spacr-0.2.1/spacr/resources/icons/umap.png +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/settings.py +12 -12
- {spacr-0.1.85 → spacr-0.2.1/spacr.egg-info}/PKG-INFO +1 -1
- {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/SOURCES.txt +20 -3
- spacr-0.1.85/spacr/gui.py +0 -195
- {spacr-0.1.85 → spacr-0.2.1}/LICENSE +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/MANIFEST.in +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/README.rst +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/setup.cfg +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/__main__.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/app_classify.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/app_mask.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/app_measure.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/app_sequencing.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/app_umap.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/chris.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/deep_spacr.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/graph_learning.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/io.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/logger.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/measure.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/plot.py +0 -0
- {spacr-0.1.85/spacr → spacr-0.2.1/spacr/resources}/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model +0 -0
- {spacr-0.1.85/spacr → spacr-0.2.1/spacr/resources}/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model_settings.csv +0 -0
- {spacr-0.1.85/spacr → spacr-0.2.1/spacr/resources}/models/cp/toxo_pv_lumen.CP_model +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/sequencing.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/sim.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/sim_app.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/timelapse.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/utils.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr/version.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/dependency_links.txt +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/entry_points.txt +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/requires.txt +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/spacr.egg-info/top_level.txt +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_annotate_app.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_core.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_classify_app.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_mask_app.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_measure_app.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_sim_app.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_gui_utils.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_io.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_mask_app.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_measure.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_plot.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_sim.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_timelapse.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_train.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_umap.py +0 -0
- {spacr-0.1.85 → spacr-0.2.1}/tests/test_utils.py +0 -0
@@ -50,7 +50,7 @@ dependencies = [
|
|
50
50
|
|
51
51
|
setup(
|
52
52
|
name="spacr",
|
53
|
-
version="0.1
|
53
|
+
version="0.2.1",
|
54
54
|
author="Einar Birnir Olafsson",
|
55
55
|
author_email="olafsson@med.umich.com",
|
56
56
|
description="Spatial phenotype analysis of crisp screens (SpaCr)",
|
@@ -58,7 +58,7 @@ setup(
|
|
58
58
|
url="https://github.com/EinarOlafsson/spacr",
|
59
59
|
packages=find_packages(exclude=["tests.*", "tests"]),
|
60
60
|
include_package_data=True,
|
61
|
-
package_data={'spacr': ['models/cp/*'],},
|
61
|
+
package_data={'spacr': ['resources/models/cp/*', 'resources/icons/*'],},
|
62
62
|
install_requires=dependencies,
|
63
63
|
entry_points={
|
64
64
|
'console_scripts': [
|
@@ -16,8 +16,8 @@ from . import app_annotate
|
|
16
16
|
from . import gui_utils
|
17
17
|
from . import gui_elements
|
18
18
|
from . import gui_core
|
19
|
-
from . import
|
20
|
-
from . import
|
19
|
+
from . import gui
|
20
|
+
from . import gui
|
21
21
|
from . import app_make_masks
|
22
22
|
from . import app_mask
|
23
23
|
from . import app_measure
|
@@ -40,6 +40,10 @@ __all__ = [
|
|
40
40
|
"deep_spacr",
|
41
41
|
"app_annotate",
|
42
42
|
"gui_utils",
|
43
|
+
"gui_elements",
|
44
|
+
"gui_core",
|
45
|
+
"gui",
|
46
|
+
"gui",
|
43
47
|
"app_make_masks",
|
44
48
|
"app_mask",
|
45
49
|
"app_measure",
|
@@ -1,15 +1,16 @@
|
|
1
1
|
import tkinter as tk
|
2
|
+
from tkinter import ttk
|
2
3
|
from .gui import MainApp
|
4
|
+
from .gui_elements import set_dark_style
|
3
5
|
|
4
6
|
def initiate_annotation_app(parent_frame):
|
5
7
|
from .gui_utils import generate_annotate_fields, annotate_app
|
6
8
|
# Set up the settings window
|
7
9
|
settings_window = tk.Toplevel(parent_frame)
|
8
10
|
settings_window.title("Annotation Settings")
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
settings_frame = tk.Frame(settings_window, bg='black') # Set the background color to black
|
11
|
+
style_out = set_dark_style(ttk.Style())
|
12
|
+
settings_window.configure(bg=style_out['bg_color'])
|
13
|
+
settings_frame = tk.Frame(settings_window, bg=style_out['bg_color'])
|
13
14
|
settings_frame.pack(fill=tk.BOTH, expand=True)
|
14
15
|
vars_dict = generate_annotate_fields(settings_frame)
|
15
16
|
|
@@ -41,7 +42,7 @@ def initiate_annotation_app(parent_frame):
|
|
41
42
|
settings_window.destroy()
|
42
43
|
annotate_app(parent_frame, settings)
|
43
44
|
|
44
|
-
start_button = tk.Button(settings_window, text="Start Annotation", command=start_annotation_app, bg='
|
45
|
+
start_button = tk.Button(settings_window, text="Start Annotation", command=start_annotation_app, bg=style_out['bg_color'], fg=style_out['bg_color'])
|
45
46
|
start_button.pack(pady=10)
|
46
47
|
|
47
48
|
def start_annotate_app():
|
@@ -3,26 +3,22 @@ from tkinter import ttk
|
|
3
3
|
from .gui import MainApp
|
4
4
|
|
5
5
|
def initiate_make_mask_app(parent_frame):
|
6
|
-
from .gui_elements import
|
7
|
-
# Set up the settings window
|
6
|
+
from .gui_elements import ModifyMaskApp, set_dark_style
|
8
7
|
settings_window = tk.Toplevel(parent_frame)
|
9
8
|
settings_window.title("Make Masks Settings")
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
settings_frame = tk.Frame(settings_window, bg='black') # Set the background color to black
|
9
|
+
style_out = set_dark_style(ttk.Style())
|
10
|
+
settings_window.configure(bg=style_out['bg_color'])
|
11
|
+
settings_frame = tk.Frame(settings_window, bg=style_out['bg_color'])
|
14
12
|
settings_frame.pack(fill=tk.BOTH, expand=True)
|
15
13
|
|
16
14
|
vars_dict = {
|
17
15
|
'folder_path': ttk.Entry(settings_frame),
|
18
16
|
'scale_factor': ttk.Entry(settings_frame)
|
19
17
|
}
|
20
|
-
|
21
|
-
# Arrange input fields and labels
|
22
18
|
row = 0
|
23
19
|
for name, entry in vars_dict.items():
|
24
20
|
ttk.Label(settings_frame, text=f"{name.replace('_', ' ').capitalize()}:",
|
25
|
-
background=
|
21
|
+
background=style_out['bg_color'], foreground=style_out['fg_color']).grid(row=row, column=0)
|
26
22
|
entry.grid(row=row, column=1)
|
27
23
|
row += 1
|
28
24
|
|
@@ -32,15 +28,12 @@ def initiate_make_mask_app(parent_frame):
|
|
32
28
|
try:
|
33
29
|
scale_factor = float(vars_dict['scale_factor'].get())
|
34
30
|
except ValueError:
|
35
|
-
scale_factor = None
|
36
|
-
|
37
|
-
# Convert empty strings to None
|
31
|
+
scale_factor = None
|
38
32
|
folder_path = folder_path if folder_path != '' else None
|
39
|
-
|
40
33
|
settings_window.destroy()
|
41
|
-
|
34
|
+
ModifyMaskApp(parent_frame, folder_path, scale_factor)
|
42
35
|
|
43
|
-
run_button = tk.Button(settings_window, text="Start Make Masks", command=start_make_mask_app, bg='
|
36
|
+
run_button = tk.Button(settings_window, text="Start Make Masks", command=start_make_mask_app, bg=style_out['bg_color'], fg=style_out['fg_color'])
|
44
37
|
run_button.pack(pady=10)
|
45
38
|
|
46
39
|
def start_make_mask_app():
|
@@ -1738,7 +1738,7 @@ def preprocess_generate_masks(src, settings={}):
|
|
1738
1738
|
if os.path.exists(os.path.join(src,'measurements')):
|
1739
1739
|
_pivot_counts_table(db_path=os.path.join(src,'measurements', 'measurements.db'))
|
1740
1740
|
|
1741
|
-
#
|
1741
|
+
#Concatenate stack with masks
|
1742
1742
|
_load_and_concatenate_arrays(src, settings['channels'], settings['cell_channel'], settings['nucleus_channel'], settings['pathogen_channel'])
|
1743
1743
|
|
1744
1744
|
if settings['plot']:
|
spacr-0.2.1/spacr/gui.py
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
import tkinter as tk
|
2
|
+
from tkinter import ttk
|
3
|
+
from PIL import Image, ImageTk, ImageDraw
|
4
|
+
import os
|
5
|
+
from multiprocessing import set_start_method
|
6
|
+
from .gui_elements import spacrButton, create_menu_bar, set_dark_style
|
7
|
+
from .gui_core import initiate_root
|
8
|
+
|
9
|
+
class MainApp(tk.Tk):
|
10
|
+
def __init__(self, default_app=None):
|
11
|
+
super().__init__()
|
12
|
+
width = self.winfo_screenwidth()
|
13
|
+
height = self.winfo_screenheight()
|
14
|
+
self.geometry(f"{width}x{height}")
|
15
|
+
self.title("SpaCr GUI Collection")
|
16
|
+
self.configure(bg='#333333') # Set window background to dark gray
|
17
|
+
|
18
|
+
# Initialize style and apply dark style to the main window
|
19
|
+
style = ttk.Style()
|
20
|
+
self.color_settings = set_dark_style(style, parent_frame=self)
|
21
|
+
self.main_buttons = {} # Initialize main_buttons dictionary here
|
22
|
+
self.additional_buttons = {} # Initialize additional_buttons dictionary here
|
23
|
+
|
24
|
+
self.main_gui_apps = {
|
25
|
+
"Mask": (lambda frame: initiate_root(frame, 'mask'), "Generate cellpose masks for cells, nuclei and pathogen images."),
|
26
|
+
"Measure": (lambda frame: initiate_root(frame, 'measure'), "Measure single object intensity and morphological feature. Crop and save single object image"),
|
27
|
+
"Annotate": (lambda frame: initiate_root(frame, 'annotate'), "Annotation single object images on a grid. Annotations are saved to database."),
|
28
|
+
"Make Masks": (lambda frame: initiate_root(frame, 'make_masks'), "Adjust pre-existing Cellpose models to your specific dataset for improved performance"),
|
29
|
+
"Classify": (lambda frame: initiate_root(frame, 'classify'), "Train Torch Convolutional Neural Networks (CNNs) or Transformers to classify single object images."),
|
30
|
+
}
|
31
|
+
|
32
|
+
self.additional_gui_apps = {
|
33
|
+
"Sequencing": (lambda frame: initiate_root(frame, 'sequencing'), "Analyze sequencing data."),
|
34
|
+
"Umap": (lambda frame: initiate_root(frame, 'umap'), "Generate UMAP embeddings with datapoints represented as images."),
|
35
|
+
"Train Cellpose": (lambda frame: initiate_root(frame, 'train_cellpose'), "Train custom Cellpose models."),
|
36
|
+
"ML Analyze": (lambda frame: initiate_root(frame, 'ml_analyze'), "Machine learning analysis of data."),
|
37
|
+
"Cellpose Masks": (lambda frame: initiate_root(frame, 'cellpose_masks'), "Generate Cellpose masks."),
|
38
|
+
"Cellpose All": (lambda frame: initiate_root(frame, 'cellpose_all'), "Run Cellpose on all images."),
|
39
|
+
"Map Barcodes": (lambda frame: initiate_root(frame, 'map_barcodes'), "Map barcodes to data."),
|
40
|
+
"Regression": (lambda frame: initiate_root(frame, 'regression'), "Perform regression analysis."),
|
41
|
+
"Recruitment": (lambda frame: initiate_root(frame, 'recruitment'), "Analyze recruitment data.")
|
42
|
+
}
|
43
|
+
|
44
|
+
self.selected_app = tk.StringVar()
|
45
|
+
self.create_widgets()
|
46
|
+
|
47
|
+
if default_app in self.main_gui_apps:
|
48
|
+
self.load_app(default_app, self.main_gui_apps[default_app][0])
|
49
|
+
elif default_app in self.additional_gui_apps:
|
50
|
+
self.load_app(default_app, self.additional_gui_apps[default_app][0])
|
51
|
+
|
52
|
+
def create_widgets(self):
|
53
|
+
# Create the menu bar
|
54
|
+
create_menu_bar(self)
|
55
|
+
|
56
|
+
# Create a canvas to hold the selected app and other elements
|
57
|
+
self.canvas = tk.Canvas(self, highlightthickness=0)
|
58
|
+
self.canvas.grid(row=0, column=0, sticky="nsew")
|
59
|
+
self.grid_rowconfigure(0, weight=1)
|
60
|
+
self.grid_columnconfigure(0, weight=1)
|
61
|
+
|
62
|
+
# Create a frame inside the canvas to hold the main content
|
63
|
+
self.content_frame = tk.Frame(self.canvas)
|
64
|
+
self.content_frame.grid(row=0, column=0, sticky="nsew")
|
65
|
+
|
66
|
+
# Center the content frame within the canvas
|
67
|
+
self.canvas.create_window((self.winfo_screenwidth() // 2, self.winfo_screenheight() // 2), window=self.content_frame, anchor="center")
|
68
|
+
|
69
|
+
# Apply dark style to canvas and content_frame
|
70
|
+
set_dark_style(ttk.Style(), containers=[self.canvas, self.content_frame])
|
71
|
+
|
72
|
+
# Create startup screen with buttons for each main GUI app and drop-down for additional apps
|
73
|
+
self.create_startup_screen()
|
74
|
+
|
75
|
+
def create_startup_screen(self):
|
76
|
+
self.clear_frame(self.content_frame)
|
77
|
+
|
78
|
+
# Create frames for the grids
|
79
|
+
main_buttons_frame = tk.Frame(self.content_frame)
|
80
|
+
main_buttons_frame.pack(pady=10)
|
81
|
+
set_dark_style(ttk.Style(), containers=[main_buttons_frame])
|
82
|
+
|
83
|
+
additional_buttons_frame = tk.Frame(self.content_frame)
|
84
|
+
additional_buttons_frame.pack(pady=10)
|
85
|
+
set_dark_style(ttk.Style(), containers=[additional_buttons_frame])
|
86
|
+
|
87
|
+
# Create a frame for the description below the icon grids
|
88
|
+
description_frame = tk.Frame(self.content_frame, height=70)
|
89
|
+
description_frame.pack(fill=tk.X, pady=10)
|
90
|
+
description_frame.pack_propagate(False) # Prevent the frame from resizing based on its content
|
91
|
+
set_dark_style(ttk.Style(), containers=[description_frame])
|
92
|
+
|
93
|
+
# Use a Label widget to display descriptions
|
94
|
+
self.description_label = tk.Label(description_frame, text="", wraplength=800, justify="center", font=('Helvetica', 12), fg=self.color_settings['fg_color'], bg=self.color_settings['bg_color'])
|
95
|
+
self.description_label.pack(fill=tk.BOTH, pady=10)
|
96
|
+
|
97
|
+
# Load the logo image and place it in the main apps row
|
98
|
+
logo_button = spacrButton(main_buttons_frame, text="SpaCr", command=lambda: self.load_app("logo_spacr", initiate_root), icon_name="logo_spacr", size=100, show_text=False)
|
99
|
+
logo_button.grid(row=0, column=0, padx=5, pady=5)
|
100
|
+
self.main_buttons[logo_button] = "SpaCr: An advanced application suite for cellpose masks, measurements, annotations, and more."
|
101
|
+
|
102
|
+
# Create icon buttons for the main apps
|
103
|
+
for i, (app_name, app_data) in enumerate(self.main_gui_apps.items()):
|
104
|
+
app_func, app_desc = app_data
|
105
|
+
button = spacrButton(main_buttons_frame, text=app_name, command=lambda app_name=app_name, app_func=app_func: self.load_app(app_name, app_func), icon_name=app_name.lower(), size=100, show_text=False)
|
106
|
+
button.grid(row=0, column=i + 1, padx=5, pady=5)
|
107
|
+
self.main_buttons[button] = app_desc
|
108
|
+
|
109
|
+
# Create icon buttons for the additional apps
|
110
|
+
for i, (app_name, app_data) in enumerate(self.additional_gui_apps.items()):
|
111
|
+
app_func, app_desc = app_data
|
112
|
+
button = spacrButton(additional_buttons_frame, text=app_name, command=lambda app_name=app_name, app_func=app_func: self.load_app(app_name, app_func), icon_name=app_name.lower(), size=75, show_text=False)
|
113
|
+
button.grid(row=0, column=i, padx=5, pady=5)
|
114
|
+
self.additional_buttons[button] = app_desc
|
115
|
+
|
116
|
+
# Update description initially
|
117
|
+
self.update_description()
|
118
|
+
|
119
|
+
def update_description(self):
|
120
|
+
# Check all buttons and update description if any has the active color
|
121
|
+
for button, desc in {**self.main_buttons, **self.additional_buttons}.items():
|
122
|
+
if button.canvas.itemcget(button.button_bg, "fill") == self.color_settings['active_color']:
|
123
|
+
self.show_description(desc)
|
124
|
+
return
|
125
|
+
self.clear_description()
|
126
|
+
|
127
|
+
def show_description(self, description):
|
128
|
+
if self.description_label.winfo_exists():
|
129
|
+
self.description_label.config(text=description)
|
130
|
+
self.description_label.update_idletasks() # Ensure the label updates immediately
|
131
|
+
|
132
|
+
def clear_description(self):
|
133
|
+
if self.description_label.winfo_exists():
|
134
|
+
self.description_label.config(text="")
|
135
|
+
self.description_label.update_idletasks() # Ensure the label updates immediately
|
136
|
+
|
137
|
+
def load_app(self, app_name, app_func):
|
138
|
+
# Clear the current content frame
|
139
|
+
self.clear_frame(self.canvas)
|
140
|
+
|
141
|
+
# Initialize the selected app
|
142
|
+
app_frame = tk.Frame(self.canvas)
|
143
|
+
app_frame.pack(fill=tk.BOTH, expand=True)
|
144
|
+
set_dark_style(ttk.Style(), containers=[app_frame])
|
145
|
+
app_func(app_frame)
|
146
|
+
|
147
|
+
def clear_frame(self, frame):
|
148
|
+
for widget in frame.winfo_children():
|
149
|
+
widget.destroy()
|
150
|
+
|
151
|
+
def gui_app():
|
152
|
+
app = MainApp()
|
153
|
+
app.mainloop()
|
154
|
+
|
155
|
+
if __name__ == "__main__":
|
156
|
+
set_start_method('spawn', force=True)
|
157
|
+
gui_app()
|
@@ -231,25 +231,43 @@ def import_settings(settings_type='mask'):
|
|
231
231
|
vars_dict = hide_all_settings(vars_dict, categories=None)
|
232
232
|
|
233
233
|
def convert_settings_dict_for_gui(settings):
|
234
|
+
from torchvision import models as torch_models
|
235
|
+
torchvision_models = [name for name, obj in torch_models.__dict__.items() if callable(obj)]
|
236
|
+
chans = ['0', '1', '2', '3', '4', '5', '6', '7', '8', None]
|
237
|
+
chans_v2 = [0, 1, 2, 3, None]
|
234
238
|
variables = {}
|
235
239
|
special_cases = {
|
236
240
|
'metadata_type': ('combo', ['cellvoyager', 'cq1', 'nikon', 'zeis', 'custom'], 'cellvoyager'),
|
237
241
|
'channels': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
|
238
|
-
'
|
239
|
-
'
|
240
|
-
'
|
241
|
-
|
242
|
+
'channel_dims': ('combo', ['[0,1,2,3]', '[0,1,2]', '[0,1]', '[0]'], '[0,1,2,3]'),
|
243
|
+
'cell_mask_dim': ('combo', chans, None),
|
244
|
+
'cell_chann_dim': ('combo', chans, None),
|
245
|
+
'nucleus_mask_dim': ('combo', chans, None),
|
246
|
+
'nucleus_chann_dim': ('combo', chans, None),
|
247
|
+
'pathogen_mask_dim': ('combo', chans, None),
|
248
|
+
'pathogen_chann_dim': ('combo', chans, None),
|
249
|
+
'crop_mode': ('combo', ['cell', 'nucleus', 'pathogen', '[cell, nucleus, pathogen]', '[cell,nucleus, pathogen]'], ['cell']),
|
242
250
|
'magnification': ('combo', [20, 40, 60], 20),
|
243
|
-
'nucleus_channel': ('combo',
|
244
|
-
'cell_channel': ('combo',
|
245
|
-
'
|
251
|
+
'nucleus_channel': ('combo', chans_v2, None),
|
252
|
+
'cell_channel': ('combo', chans_v2, None),
|
253
|
+
'channel_of_interest': ('combo', chans_v2, None),
|
254
|
+
'pathogen_channel': ('combo', chans_v2, None),
|
246
255
|
'timelapse_mode': ('combo', ['trackpy', 'btrack'], 'trackpy'),
|
256
|
+
'train_mode': ('combo', ['erm', 'irm'], 'erm'),
|
257
|
+
'clustering': ('combo', ['dbscan', 'kmean'], 'dbscan'),
|
258
|
+
'reduction_method': ('combo', ['umap', 'tsne'], 'umap'),
|
259
|
+
'model_name': ('combo', ['cyto', 'cyto_2', 'cyto_3', 'nuclei'], 'cyto'),
|
260
|
+
'regression_type': ('combo', ['ols','gls','wls','rlm','glm','mixed','quantile','logit','probit','poisson','lasso','ridge'], 'ols'),
|
247
261
|
'timelapse_objects': ('combo', ['cell', 'nucleus', 'pathogen', 'cytoplasm', None], None),
|
248
|
-
'model_type': ('combo',
|
262
|
+
'model_type': ('combo', torchvision_models, 'resnet50'),
|
249
263
|
'optimizer_type': ('combo', ['adamw', 'adam'], 'adamw'),
|
250
264
|
'schedule': ('combo', ['reduce_lr_on_plateau', 'step_lr'], 'reduce_lr_on_plateau'),
|
251
265
|
'loss_type': ('combo', ['focal_loss', 'binary_cross_entropy_with_logits'], 'focal_loss'),
|
252
266
|
'normalize_by': ('combo', ['fov', 'png'], 'png'),
|
267
|
+
'agg_type': ('combo', ['mean', 'median'], 'mean'),
|
268
|
+
'grouping': ('combo', ['mean', 'median'], 'mean'),
|
269
|
+
'min_max': ('combo', ['allq', 'all'], 'allq'),
|
270
|
+
'transform': ('combo', ['log', 'sqrt', 'square', None], None)
|
253
271
|
}
|
254
272
|
|
255
273
|
for key, value in settings.items():
|
@@ -338,9 +356,10 @@ def setup_plot_section(vertical_container):
|
|
338
356
|
plot_frame.add(canvas_widget, stretch="always")
|
339
357
|
canvas.draw()
|
340
358
|
canvas.figure = figure
|
341
|
-
|
342
|
-
|
343
|
-
|
359
|
+
style_out = set_dark_style(ttk.Style())
|
360
|
+
|
361
|
+
figure.patch.set_facecolor(style_out['bg_color'])
|
362
|
+
plot.set_facecolor(style_out['bg_color'])
|
344
363
|
containers = [plot_frame]
|
345
364
|
widgets = [canvas_widget]
|
346
365
|
style = ttk.Style(vertical_container)
|
@@ -488,25 +507,25 @@ def setup_button_section(horizontal_container, settings_type='mask', window_dime
|
|
488
507
|
btn_row = 1
|
489
508
|
|
490
509
|
if run:
|
491
|
-
run_button = spacrButton(button_scrollable_frame.scrollable_frame, text="
|
510
|
+
run_button = spacrButton(button_scrollable_frame.scrollable_frame, text="run", command=lambda: start_process(q, fig_queue, settings_type))
|
492
511
|
run_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
|
493
512
|
widgets.append(run_button)
|
494
513
|
btn_row += 1
|
495
514
|
|
496
515
|
if abort and settings_type in ['mask', 'measure', 'classify', 'sequencing', 'umap']:
|
497
|
-
abort_button = spacrButton(button_scrollable_frame.scrollable_frame, text="
|
516
|
+
abort_button = spacrButton(button_scrollable_frame.scrollable_frame, text="abort", command=initiate_abort)
|
498
517
|
abort_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
|
499
518
|
widgets.append(abort_button)
|
500
519
|
btn_row += 1
|
501
520
|
|
502
521
|
if download and settings_type in ['mask']:
|
503
|
-
download_dataset_button = spacrButton(button_scrollable_frame.scrollable_frame, text="
|
522
|
+
download_dataset_button = spacrButton(button_scrollable_frame.scrollable_frame, text="download", command=download_hug_dataset)
|
504
523
|
download_dataset_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
|
505
524
|
widgets.append(download_dataset_button)
|
506
525
|
btn_row += 1
|
507
526
|
|
508
527
|
if import_btn:
|
509
|
-
import_button = spacrButton(button_scrollable_frame.scrollable_frame, text="
|
528
|
+
import_button = spacrButton(button_scrollable_frame.scrollable_frame, text="settings", command=lambda: import_settings(settings_type))
|
510
529
|
import_button.grid(row=btn_row, column=btn_col, pady=5, padx=5, sticky='ew')
|
511
530
|
widgets.append(import_button)
|
512
531
|
|
@@ -516,11 +535,19 @@ def setup_button_section(horizontal_container, settings_type='mask', window_dime
|
|
516
535
|
description_frame = tk.Frame(horizontal_container)
|
517
536
|
horizontal_container.add(description_frame, stretch="always", sticky="nsew")
|
518
537
|
description_frame.grid_columnconfigure(0, weight=1)
|
538
|
+
description_frame.grid_rowconfigure(0, weight=1) # Add this line to make the row expandable
|
539
|
+
|
519
540
|
description_label = tk.Label(description_frame, text="Module Description", anchor='nw', justify='left', wraplength=width - 50)
|
520
541
|
description_label.grid(row=0, column=0, pady=50, padx=20, sticky='nsew')
|
521
542
|
description_text = descriptions.get(settings_type, "No description available for this module.")
|
522
543
|
description_label.config(text=description_text)
|
523
544
|
|
545
|
+
def update_wraplength(event):
|
546
|
+
new_width = event.width - 40 # Adjust as needed
|
547
|
+
description_label.config(wraplength=new_width)
|
548
|
+
|
549
|
+
description_label.bind('<Configure>', update_wraplength)
|
550
|
+
|
524
551
|
containers = [button_frame, description_frame]
|
525
552
|
widgets.extend([description_label])
|
526
553
|
|
@@ -588,7 +615,7 @@ def toggle_settings(button_scrollable_frame):
|
|
588
615
|
category_var = tk.StringVar()
|
589
616
|
non_empty_categories = [category for category, settings in categories.items() if any(setting in vars_dict for setting in settings)]
|
590
617
|
category_dropdown = spacrDropdownMenu(button_scrollable_frame.scrollable_frame, category_var, non_empty_categories, command=on_category_select)
|
591
|
-
category_dropdown.grid(row=
|
618
|
+
category_dropdown.grid(row=5, column=0, sticky="ew", pady=2, padx=2)
|
592
619
|
vars_dict = hide_all_settings(vars_dict, categories)
|
593
620
|
|
594
621
|
def process_fig_queue():
|