spacr 0.0.20__py3-none-any.whl → 0.0.21__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/alpha.py +291 -14
- spacr/annotate_app.py +2 -2
- spacr/core.py +1301 -426
- spacr/foldseek.py +793 -0
- spacr/get_alfafold_structures.py +72 -0
- spacr/gui_mask_app.py +30 -10
- spacr/gui_utils.py +17 -2
- spacr/io.py +260 -102
- spacr/measure.py +150 -64
- spacr/plot.py +151 -12
- spacr/sim.py +666 -119
- spacr/timelapse.py +139 -9
- spacr/train.py +18 -10
- spacr/utils.py +43 -43
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/METADATA +5 -2
- spacr-0.0.21.dist-info/RECORD +33 -0
- spacr-0.0.20.dist-info/RECORD +0 -31
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/LICENSE +0 -0
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/WHEEL +0 -0
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/entry_points.txt +0 -0
- {spacr-0.0.20.dist-info → spacr-0.0.21.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
import csv
|
2
|
+
import os
|
3
|
+
import requests
|
4
|
+
|
5
|
+
def download_alphafold_structures(tsv_location, dst, version="4"):
|
6
|
+
# Create the destination directory if it does not exist
|
7
|
+
dst_pdb = os.path.join(dst,'pdb')
|
8
|
+
dst_cif = os.path.join(dst,'cif')
|
9
|
+
dst_pae = os.path.join(dst,'pae')
|
10
|
+
|
11
|
+
if not os.path.exists(dst):
|
12
|
+
os.makedirs(dst)
|
13
|
+
if not os.path.exists(dst_pdb):
|
14
|
+
os.makedirs(dst_pdb)
|
15
|
+
if not os.path.exists(dst_cif):
|
16
|
+
os.makedirs(dst_cif)
|
17
|
+
if not os.path.exists(dst_pae):
|
18
|
+
os.makedirs(dst_pae)
|
19
|
+
|
20
|
+
failed_downloads = [] # List to keep track of failed downloads
|
21
|
+
|
22
|
+
# Open the TSV file and read entries
|
23
|
+
with open(tsv_location, 'r') as tsv_file:
|
24
|
+
reader = csv.DictReader(tsv_file, delimiter='\t')
|
25
|
+
for row in reader:
|
26
|
+
entry = row['Entry']
|
27
|
+
af_link = f"https://alphafold.ebi.ac.uk/files/AF-{entry}-F1-model_v{version}.pdb"
|
28
|
+
cif_link = f"https://alphafold.ebi.ac.uk/files/AF-{entry}-F1-model_v{version}.cif"
|
29
|
+
pae_link = f"https://alphafold.ebi.ac.uk/files/AF-{entry}-F1-predicted_aligned_error_v{version}.json"
|
30
|
+
|
31
|
+
try:
|
32
|
+
response_pdb = requests.get(af_link, stream=True)
|
33
|
+
response_cif = requests.get(cif_link, stream=True)
|
34
|
+
response_pae = requests.get(pae_link, stream=True)
|
35
|
+
if response_pdb.status_code == 200:
|
36
|
+
|
37
|
+
# Save the PDB file
|
38
|
+
with open(os.path.join(dst_pdb, f"AF-{entry}-F1-model_v{version}.pdb"), 'wb') as pdb_file:
|
39
|
+
pdb_file.write(response_pdb.content)
|
40
|
+
print(f"Downloaded: AF-{entry}-F1-model_v{version}.pdb")
|
41
|
+
|
42
|
+
# Save the CIF file
|
43
|
+
with open(os.path.join(dst_cif, f"AF-{entry}-F1-model_v{version}.cif"), 'wb') as cif_file:
|
44
|
+
cif_file.write(response_cif.content)
|
45
|
+
print(f"Downloaded: AF-{entry}-F1-model_v{version}.cif")
|
46
|
+
|
47
|
+
# Save the PAE file
|
48
|
+
with open(os.path.join(dst_pae, f"AF-{entry}-F1-predicted_aligned_error_v{version}.json"), 'wb') as pdb_file:
|
49
|
+
pdb_file.write(response_pae.content)
|
50
|
+
print(f"Downloaded: AF-{entry}-F1-predicted_aligned_error_v{version}.json")
|
51
|
+
|
52
|
+
else:
|
53
|
+
# If the file could not be downloaded, record the entry
|
54
|
+
failed_downloads.append(entry)
|
55
|
+
print(f"Failed to download structure for: {entry}")
|
56
|
+
except Exception as e:
|
57
|
+
print(f"Error downloading structure for {entry}: {e}")
|
58
|
+
failed_downloads.append(entry)
|
59
|
+
|
60
|
+
# Save the list of failed downloads to a CSV file in the destination folder
|
61
|
+
if failed_downloads:
|
62
|
+
with open(os.path.join(dst, 'failed_downloads.csv'), 'w', newline='') as failed_file:
|
63
|
+
writer = csv.writer(failed_file)
|
64
|
+
writer.writerow(['Entry'])
|
65
|
+
for entry in failed_downloads:
|
66
|
+
writer.writerow([entry])
|
67
|
+
print(f"Failed download entries saved to: {os.path.join(dst, 'failed_downloads.csv')}")
|
68
|
+
|
69
|
+
# Example usage:
|
70
|
+
tsv_location = '/home/carruthers/Downloads/GT1_proteome/GT1_proteins_uniprot.tsv' # Replace with the path to your TSV file containing a list of UniProt entries
|
71
|
+
dst_folder = '/home/carruthers/Downloads/GT1_proteome' # Replace with your destination folder
|
72
|
+
download_alphafold_structures(tsv_location, dst_folder)
|
spacr/gui_mask_app.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import sys, ctypes, matplotlib
|
2
2
|
import tkinter as tk
|
3
3
|
from tkinter import ttk, scrolledtext
|
4
4
|
from ttkthemes import ThemedTk
|
@@ -16,11 +16,19 @@ except AttributeError:
|
|
16
16
|
pass
|
17
17
|
|
18
18
|
from .logger import log_function_call
|
19
|
-
from .gui_utils import ScrollableFrame, StdoutRedirector,
|
20
|
-
from .gui_utils import mask_variables, check_mask_gui_settings, preprocess_generate_masks_wrapper, read_settings_from_csv, update_settings_from_csv
|
19
|
+
from .gui_utils import ScrollableFrame, StdoutRedirector, clear_canvas, main_thread_update_function, create_dark_mode, set_dark_style, generate_fields, process_stdout_stderr, set_default_font, style_text_boxes
|
20
|
+
from .gui_utils import mask_variables, check_mask_gui_settings, preprocess_generate_masks_wrapper, read_settings_from_csv, update_settings_from_csv#, toggle_advanced_settings
|
21
21
|
|
22
22
|
thread_control = {"run_thread": None, "stop_requested": False}
|
23
23
|
|
24
|
+
def toggle_advanced_settings():
|
25
|
+
advanced = advanced_var.get()
|
26
|
+
for widget in advanced_widgets:
|
27
|
+
if advanced:
|
28
|
+
widget.grid()
|
29
|
+
else:
|
30
|
+
widget.grid_remove()
|
31
|
+
|
24
32
|
@log_function_call
|
25
33
|
def initiate_abort():
|
26
34
|
global thread_control
|
@@ -73,7 +81,7 @@ def import_settings(scrollable_frame):
|
|
73
81
|
|
74
82
|
@log_function_call
|
75
83
|
def initiate_mask_root(width, height):
|
76
|
-
global root, vars_dict, q, canvas, fig_queue, canvas_widget, thread_control
|
84
|
+
global root, vars_dict, q, canvas, fig_queue, canvas_widget, thread_control, advanced_widgets, advanced_var
|
77
85
|
|
78
86
|
theme = 'breeze'
|
79
87
|
|
@@ -87,7 +95,8 @@ def initiate_mask_root(width, height):
|
|
87
95
|
style = ttk.Style(root)
|
88
96
|
set_dark_style(style)
|
89
97
|
|
90
|
-
|
98
|
+
style_text_boxes(style)
|
99
|
+
set_default_font(root, font_name="Arial", size=8)
|
91
100
|
#root.state('zoomed') # For Windows to maximize the window
|
92
101
|
root.attributes('-fullscreen', True)
|
93
102
|
root.geometry(f"{width}x{height}")
|
@@ -139,6 +148,10 @@ def initiate_mask_root(width, height):
|
|
139
148
|
# Setup for user input fields (variables)
|
140
149
|
variables = mask_variables()
|
141
150
|
vars_dict = generate_fields(variables, scrollable_frame)
|
151
|
+
#del vars_dict['fps']
|
152
|
+
|
153
|
+
# Debugging: print vars_dict to ensure it is populated correctly
|
154
|
+
#print("vars_dict:", vars_dict)
|
142
155
|
|
143
156
|
# Horizontal container for Matplotlib figure and the vertical pane (for settings and console)
|
144
157
|
horizontal_container = tk.PanedWindow(vertical_container, orient=tk.VERTICAL) #HORIZONTAL
|
@@ -167,21 +180,27 @@ def initiate_mask_root(width, height):
|
|
167
180
|
q = Queue()
|
168
181
|
sys.stdout = StdoutRedirector(console_output)
|
169
182
|
sys.stderr = StdoutRedirector(console_output)
|
183
|
+
|
184
|
+
advanced_var = tk.BooleanVar()
|
185
|
+
advanced_checkbox = ttk.Checkbutton(scrollable_frame.scrollable_frame, text="Advanced Settings", variable=advanced_var, command=toggle_advanced_settings)
|
186
|
+
advanced_checkbox.grid(row=46, column=1, pady=10, padx=10)
|
170
187
|
|
171
188
|
# This is your GUI setup where you create the Run button
|
172
189
|
run_button = ttk.Button(scrollable_frame.scrollable_frame, text="Run",command=lambda: start_process(q, fig_queue))
|
173
|
-
run_button.grid(row=45, column=0, pady=10)
|
190
|
+
run_button.grid(row=45, column=0, pady=10, padx=10)
|
174
191
|
|
175
192
|
abort_button = ttk.Button(scrollable_frame.scrollable_frame, text="Abort", command=initiate_abort)
|
176
|
-
abort_button.grid(row=45, column=1, pady=10)
|
193
|
+
abort_button.grid(row=45, column=1, pady=10, padx=10)
|
177
194
|
|
178
195
|
progress_label = ttk.Label(scrollable_frame.scrollable_frame, text="Processing: 0%", background="#333333", foreground="white")
|
179
|
-
progress_label.grid(row=41, column=0, columnspan=2, sticky="ew", pady=(5, 0))
|
180
|
-
|
196
|
+
progress_label.grid(row=41, column=0, columnspan=2, sticky="ew", pady=(5, 0), padx=10)
|
197
|
+
|
181
198
|
# Create the Import Settings button
|
182
199
|
import_btn = tk.Button(root, text="Import Settings", command=lambda: import_settings(scrollable_frame))
|
183
|
-
import_btn.pack(pady=20)
|
200
|
+
import_btn.pack(pady=20, padx=10)
|
201
|
+
|
184
202
|
|
203
|
+
|
185
204
|
_process_console_queue()
|
186
205
|
_process_fig_queue()
|
187
206
|
create_dark_mode(root, style, console_output)
|
@@ -193,6 +212,7 @@ def initiate_mask_root(width, height):
|
|
193
212
|
def gui_mask():
|
194
213
|
global vars_dict, root
|
195
214
|
root, vars_dict = initiate_mask_root(1000, 1500)
|
215
|
+
|
196
216
|
root.mainloop()
|
197
217
|
|
198
218
|
if __name__ == "__main__":
|
spacr/gui_utils.py
CHANGED
@@ -14,6 +14,21 @@ except AttributeError:
|
|
14
14
|
|
15
15
|
from .logger import log_function_call
|
16
16
|
|
17
|
+
def set_default_font(root, font_name="Helvetica", size=12):
|
18
|
+
default_font = (font_name, size)
|
19
|
+
root.option_add("*Font", default_font)
|
20
|
+
root.option_add("*TButton.Font", default_font)
|
21
|
+
root.option_add("*TLabel.Font", default_font)
|
22
|
+
root.option_add("*TEntry.Font", default_font)
|
23
|
+
|
24
|
+
def style_text_boxes(style):
|
25
|
+
style.configure('TEntry', padding='5 5 5 5', borderwidth=1, relief='solid', background='#333333', foreground='#ffffff')
|
26
|
+
style.configure('TButton', padding='10 10 10 10', borderwidth=1, relief='solid', background='#444444', foreground='#ffffff', font=('Helvetica', 12, 'bold'))
|
27
|
+
style.map('TButton',
|
28
|
+
background=[('active', '#555555'), ('disabled', '#222222')],
|
29
|
+
foreground=[('active', '#ffffff'), ('disabled', '#888888')])
|
30
|
+
style.configure('TLabel', padding='5 5 5 5', borderwidth=1, relief='flat', background='#2e2e2e', foreground='#ffffff')
|
31
|
+
|
17
32
|
def read_settings_from_csv(csv_file_path):
|
18
33
|
settings = {}
|
19
34
|
with open(csv_file_path, newline='') as csvfile:
|
@@ -51,7 +66,7 @@ def disable_interactivity(fig):
|
|
51
66
|
for handler_id in list(handlers.keys()):
|
52
67
|
fig.canvas.mpl_disconnect(handler_id)
|
53
68
|
|
54
|
-
def
|
69
|
+
def set_default_font_v1(app, font_name="Arial Bold", size=10):
|
55
70
|
default_font = nametofont("TkDefaultFont")
|
56
71
|
text_font = nametofont("TkTextFont")
|
57
72
|
fixed_font = nametofont("TkFixedFont")
|
@@ -580,7 +595,7 @@ def measure_crop_wrapper(settings, q, fig_queue):
|
|
580
595
|
|
581
596
|
try:
|
582
597
|
print('start')
|
583
|
-
spacr.measure.measure_crop(settings=settings
|
598
|
+
spacr.measure.measure_crop(settings=settings)
|
584
599
|
except Exception as e:
|
585
600
|
errorMessage = f"Error during processing: {e}"
|
586
601
|
q.put(errorMessage) # Send the error message to the GUI via the queue
|