spacr 0.2.4__py3-none-any.whl → 0.2.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 +1 -11
- spacr/core.py +277 -349
- spacr/deep_spacr.py +248 -269
- spacr/gui.py +58 -54
- spacr/gui_core.py +689 -535
- spacr/gui_elements.py +1002 -153
- spacr/gui_utils.py +452 -107
- spacr/io.py +158 -91
- spacr/measure.py +199 -151
- spacr/plot.py +159 -47
- spacr/resources/font/open_sans/OFL.txt +93 -0
- spacr/resources/font/open_sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
- spacr/resources/font/open_sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
- spacr/resources/font/open_sans/README.txt +100 -0
- spacr/resources/font/open_sans/static/OpenSans-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-SemiBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
- spacr/resources/icons/logo.pdf +2786 -6
- spacr/resources/icons/logo_spacr.png +0 -0
- spacr/resources/icons/logo_spacr_1.png +0 -0
- spacr/sequencing.py +477 -587
- spacr/settings.py +217 -144
- spacr/utils.py +46 -46
- {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/METADATA +46 -35
- spacr-0.2.8.dist-info/RECORD +100 -0
- {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/WHEEL +1 -1
- spacr-0.2.4.dist-info/RECORD +0 -58
- {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/LICENSE +0 -0
- {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/entry_points.txt +0 -0
- {spacr-0.2.4.dist-info → spacr-0.2.8.dist-info}/top_level.txt +0 -0
spacr/gui.py
CHANGED
@@ -1,44 +1,61 @@
|
|
1
1
|
import tkinter as tk
|
2
2
|
from tkinter import ttk
|
3
|
-
from PIL import Image, ImageTk, ImageDraw
|
4
|
-
import os
|
5
3
|
from multiprocessing import set_start_method
|
6
4
|
from .gui_elements import spacrButton, create_menu_bar, set_dark_style
|
7
5
|
from .gui_core import initiate_root
|
6
|
+
from screeninfo import get_monitors
|
8
7
|
|
9
8
|
class MainApp(tk.Tk):
|
10
9
|
def __init__(self, default_app=None):
|
11
10
|
super().__init__()
|
12
|
-
|
13
|
-
|
11
|
+
|
12
|
+
# Initialize the window
|
13
|
+
self.geometry("100x100")
|
14
|
+
self.update_idletasks()
|
15
|
+
|
16
|
+
# Get the current window position
|
17
|
+
self.update_idletasks()
|
18
|
+
x = self.winfo_x()
|
19
|
+
y = self.winfo_y()
|
20
|
+
|
21
|
+
# Find the monitor where the window is located
|
22
|
+
for monitor in get_monitors():
|
23
|
+
if monitor.x <= x < monitor.x + monitor.width and monitor.y <= y < monitor.y + monitor.height:
|
24
|
+
width = monitor.width
|
25
|
+
height = monitor.height
|
26
|
+
break
|
27
|
+
else:
|
28
|
+
monitor = get_monitors()[0]
|
29
|
+
width = monitor.width
|
30
|
+
height = monitor.height
|
31
|
+
|
32
|
+
# Set the window size to the dimensions of the monitor where it is located
|
14
33
|
self.geometry(f"{width}x{height}")
|
15
34
|
self.title("SpaCr GUI Collection")
|
16
35
|
self.configure(bg='#333333') # Set window background to dark gray
|
17
36
|
|
18
|
-
# Initialize style and apply dark style to the main window
|
19
37
|
style = ttk.Style()
|
20
38
|
self.color_settings = set_dark_style(style, parent_frame=self)
|
21
|
-
self.main_buttons = {}
|
22
|
-
self.additional_buttons = {}
|
39
|
+
self.main_buttons = {}
|
40
|
+
self.additional_buttons = {}
|
23
41
|
|
24
42
|
self.main_gui_apps = {
|
25
|
-
"Mask": (lambda frame: initiate_root(
|
26
|
-
"Measure": (lambda frame: initiate_root(
|
27
|
-
"Annotate": (lambda frame: initiate_root(
|
28
|
-
"Make Masks": (lambda frame: initiate_root(
|
29
|
-
"Classify": (lambda frame: initiate_root(
|
43
|
+
"Mask": (lambda frame: initiate_root(self, 'mask'), "Generate cellpose masks for cells, nuclei and pathogen images."),
|
44
|
+
"Measure": (lambda frame: initiate_root(self, 'measure'), "Measure single object intensity and morphological feature. Crop and save single object image"),
|
45
|
+
"Annotate": (lambda frame: initiate_root(self, 'annotate'), "Annotation single object images on a grid. Annotations are saved to database."),
|
46
|
+
"Make Masks": (lambda frame: initiate_root(self, 'make_masks'), "Adjust pre-existing Cellpose models to your specific dataset for improved performance"),
|
47
|
+
"Classify": (lambda frame: initiate_root(self, 'classify'), "Train Torch Convolutional Neural Networks (CNNs) or Transformers to classify single object images."),
|
30
48
|
}
|
31
49
|
|
32
50
|
self.additional_gui_apps = {
|
33
|
-
"
|
34
|
-
"
|
35
|
-
"
|
36
|
-
"
|
37
|
-
"Cellpose
|
38
|
-
"
|
39
|
-
"
|
40
|
-
"
|
41
|
-
"Recruitment": (lambda frame: initiate_root(frame, 'recruitment'), "Analyze recruitment data.")
|
51
|
+
"Umap": (lambda frame: initiate_root(self, 'umap'), "Generate UMAP embeddings with datapoints represented as images."),
|
52
|
+
"Train Cellpose": (lambda frame: initiate_root(self, 'train_cellpose'), "Train custom Cellpose models."),
|
53
|
+
"ML Analyze": (lambda frame: initiate_root(self, 'ml_analyze'), "Machine learning analysis of data."),
|
54
|
+
"Cellpose Masks": (lambda frame: initiate_root(self, 'cellpose_masks'), "Generate Cellpose masks."),
|
55
|
+
"Cellpose All": (lambda frame: initiate_root(self, 'cellpose_all'), "Run Cellpose on all images."),
|
56
|
+
"Map Barcodes": (lambda frame: initiate_root(self, 'map_barcodes'), "Map barcodes to data."),
|
57
|
+
"Regression": (lambda frame: initiate_root(self, 'regression'), "Perform regression analysis."),
|
58
|
+
"Recruitment": (lambda frame: initiate_root(self, 'recruitment'), "Analyze recruitment data.")
|
42
59
|
}
|
43
60
|
|
44
61
|
self.selected_app = tk.StringVar()
|
@@ -50,75 +67,64 @@ class MainApp(tk.Tk):
|
|
50
67
|
self.load_app(default_app, self.additional_gui_apps[default_app][0])
|
51
68
|
|
52
69
|
def create_widgets(self):
|
53
|
-
# Create the menu bar
|
54
70
|
create_menu_bar(self)
|
55
71
|
|
56
|
-
#
|
57
|
-
self.canvas = tk.Canvas(self, highlightthickness=0)
|
58
|
-
self.canvas.grid(row=0, column=0, sticky="nsew")
|
72
|
+
# Use a grid layout for centering
|
59
73
|
self.grid_rowconfigure(0, weight=1)
|
60
74
|
self.grid_columnconfigure(0, weight=1)
|
61
75
|
|
62
|
-
|
63
|
-
self.content_frame = tk.Frame(self.canvas)
|
76
|
+
self.content_frame = tk.Frame(self)
|
64
77
|
self.content_frame.grid(row=0, column=0, sticky="nsew")
|
78
|
+
|
79
|
+
# Center the content frame within the window
|
80
|
+
self.content_frame.grid_rowconfigure(0, weight=1)
|
81
|
+
self.content_frame.grid_columnconfigure(0, weight=1)
|
65
82
|
|
66
|
-
|
67
|
-
self.
|
68
|
-
|
69
|
-
|
70
|
-
set_dark_style(ttk.Style(), containers=[self.canvas, self.content_frame])
|
83
|
+
self.inner_frame = tk.Frame(self.content_frame)
|
84
|
+
self.inner_frame.grid(row=0, column=0)
|
85
|
+
|
86
|
+
set_dark_style(ttk.Style(), containers=[self.content_frame, self.inner_frame])
|
71
87
|
|
72
|
-
# Create startup screen with buttons for each main GUI app and drop-down for additional apps
|
73
88
|
self.create_startup_screen()
|
74
89
|
|
75
90
|
def create_startup_screen(self):
|
76
|
-
self.clear_frame(self.
|
91
|
+
self.clear_frame(self.inner_frame)
|
77
92
|
|
78
|
-
|
79
|
-
main_buttons_frame = tk.Frame(self.content_frame)
|
93
|
+
main_buttons_frame = tk.Frame(self.inner_frame)
|
80
94
|
main_buttons_frame.pack(pady=10)
|
81
95
|
set_dark_style(ttk.Style(), containers=[main_buttons_frame])
|
82
96
|
|
83
|
-
additional_buttons_frame = tk.Frame(self.
|
97
|
+
additional_buttons_frame = tk.Frame(self.inner_frame)
|
84
98
|
additional_buttons_frame.pack(pady=10)
|
85
99
|
set_dark_style(ttk.Style(), containers=[additional_buttons_frame])
|
86
100
|
|
87
|
-
|
88
|
-
description_frame = tk.Frame(self.content_frame, height=70)
|
101
|
+
description_frame = tk.Frame(self.inner_frame, height=70)
|
89
102
|
description_frame.pack(fill=tk.X, pady=10)
|
90
|
-
description_frame.pack_propagate(False)
|
103
|
+
description_frame.pack_propagate(False)
|
91
104
|
set_dark_style(ttk.Style(), containers=[description_frame])
|
92
105
|
|
93
|
-
# Use a Label widget to display descriptions
|
94
106
|
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
107
|
self.description_label.pack(fill=tk.BOTH, pady=10)
|
96
108
|
|
97
|
-
# Load the logo image and place it in the main apps row
|
98
109
|
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
110
|
logo_button.grid(row=0, column=0, padx=5, pady=5)
|
100
|
-
self.main_buttons[logo_button] = "SpaCr provides a flexible toolset to extract single-cell images and measurements from high-content cell painting experiments, train deep-learning models to classify cellular/subcellular phenotypes, simulate, and analyze pooled CRISPR-Cas9 imaging screens
|
111
|
+
self.main_buttons[logo_button] = "SpaCr provides a flexible toolset to extract single-cell images and measurements from high-content cell painting experiments, train deep-learning models to classify cellular/subcellular phenotypes, simulate, and analyze pooled CRISPR-Cas9 imaging screens."
|
101
112
|
|
102
|
-
# Create icon buttons for the main apps
|
103
113
|
for i, (app_name, app_data) in enumerate(self.main_gui_apps.items()):
|
104
114
|
app_func, app_desc = app_data
|
105
115
|
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
116
|
button.grid(row=0, column=i + 1, padx=5, pady=5)
|
107
117
|
self.main_buttons[button] = app_desc
|
108
118
|
|
109
|
-
# Create icon buttons for the additional apps
|
110
119
|
for i, (app_name, app_data) in enumerate(self.additional_gui_apps.items()):
|
111
120
|
app_func, app_desc = app_data
|
112
121
|
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
122
|
button.grid(row=0, column=i, padx=5, pady=5)
|
114
123
|
self.additional_buttons[button] = app_desc
|
115
124
|
|
116
|
-
# Update description initially
|
117
125
|
self.update_description()
|
118
|
-
#
|
119
126
|
|
120
127
|
def update_description(self):
|
121
|
-
# Check all buttons and update description if any has the active color
|
122
128
|
for button, desc in {**self.main_buttons, **self.additional_buttons}.items():
|
123
129
|
if button.canvas.itemcget(button.button_bg, "fill") == self.color_settings['active_color']:
|
124
130
|
self.show_description(desc)
|
@@ -128,19 +134,17 @@ class MainApp(tk.Tk):
|
|
128
134
|
def show_description(self, description):
|
129
135
|
if self.description_label.winfo_exists():
|
130
136
|
self.description_label.config(text=description)
|
131
|
-
self.description_label.update_idletasks()
|
137
|
+
self.description_label.update_idletasks()
|
132
138
|
|
133
139
|
def clear_description(self):
|
134
140
|
if self.description_label.winfo_exists():
|
135
141
|
self.description_label.config(text="")
|
136
|
-
self.description_label.update_idletasks()
|
142
|
+
self.description_label.update_idletasks()
|
137
143
|
|
138
144
|
def load_app(self, app_name, app_func):
|
139
|
-
|
140
|
-
self.clear_frame(self.canvas)
|
145
|
+
self.clear_frame(self.inner_frame)
|
141
146
|
|
142
|
-
|
143
|
-
app_frame = tk.Frame(self.canvas)
|
147
|
+
app_frame = tk.Frame(self.inner_frame)
|
144
148
|
app_frame.pack(fill=tk.BOTH, expand=True)
|
145
149
|
set_dark_style(ttk.Style(), containers=[app_frame])
|
146
150
|
app_func(app_frame)
|