spacr 0.2.46__py3-none-any.whl → 0.2.53__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/core.py +24 -11
- spacr/gui.py +0 -2
- spacr/gui_core.py +70 -55
- spacr/gui_elements.py +367 -152
- spacr/gui_utils.py +59 -68
- spacr/io.py +2 -3
- spacr/measure.py +196 -145
- spacr/plot.py +2 -42
- 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/sequencing.py +107 -13
- spacr/settings.py +27 -84
- spacr/utils.py +9 -9
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/METADATA +6 -4
- spacr-0.2.53.dist-info/RECORD +100 -0
- spacr-0.2.46.dist-info/RECORD +0 -60
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/LICENSE +0 -0
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/WHEEL +0 -0
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/entry_points.txt +0 -0
- {spacr-0.2.46.dist-info → spacr-0.2.53.dist-info}/top_level.txt +0 -0
spacr/gui_utils.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import os, io, sys, ast, ctypes, ast, sqlite3, requests, time, traceback
|
2
|
-
import traceback
|
3
2
|
import tkinter as tk
|
4
3
|
from tkinter import ttk
|
5
4
|
import matplotlib
|
@@ -7,8 +6,7 @@ import matplotlib.pyplot as plt
|
|
7
6
|
matplotlib.use('Agg')
|
8
7
|
from huggingface_hub import list_repo_files
|
9
8
|
|
10
|
-
from .
|
11
|
-
from .gui_elements import AnnotateApp, spacrEntry, spacrCheck, spacrCombo, set_default_font
|
9
|
+
from .gui_elements import AnnotateApp, spacrEntry, spacrCheck, spacrCombo
|
12
10
|
|
13
11
|
try:
|
14
12
|
ctypes.windll.shcore.SetProcessDpiAwareness(True)
|
@@ -28,6 +26,10 @@ def proceed_with_app(root, app_name, app_func):
|
|
28
26
|
app_func(root.content_frame)
|
29
27
|
|
30
28
|
def load_app(root, app_name, app_func):
|
29
|
+
# Clear the canvas if it exists
|
30
|
+
if root.canvas is not None:
|
31
|
+
root.clear_frame(root.canvas)
|
32
|
+
|
31
33
|
# Cancel all scheduled after tasks
|
32
34
|
if hasattr(root, 'after_tasks'):
|
33
35
|
for task in root.after_tasks:
|
@@ -37,20 +39,10 @@ def load_app(root, app_name, app_func):
|
|
37
39
|
# Exit functionality only for the annotation and make_masks apps
|
38
40
|
if app_name not in ["Annotate", "make_masks"] and hasattr(root, 'current_app_exit_func'):
|
39
41
|
root.next_app_func = proceed_with_app
|
40
|
-
root.next_app_args = (app_name, app_func)
|
42
|
+
root.next_app_args = (app_name, app_func)
|
41
43
|
root.current_app_exit_func()
|
42
44
|
else:
|
43
45
|
proceed_with_app(root, app_name, app_func)
|
44
|
-
|
45
|
-
def parse_list_v1(value):
|
46
|
-
try:
|
47
|
-
parsed_value = ast.literal_eval(value)
|
48
|
-
if isinstance(parsed_value, list):
|
49
|
-
return parsed_value
|
50
|
-
else:
|
51
|
-
raise ValueError
|
52
|
-
except (ValueError, SyntaxError):
|
53
|
-
raise ValueError("Invalid format for list")
|
54
46
|
|
55
47
|
def parse_list(value):
|
56
48
|
try:
|
@@ -64,43 +56,57 @@ def parse_list(value):
|
|
64
56
|
|
65
57
|
# Usage example in your create_input_field function
|
66
58
|
def create_input_field(frame, label_text, row, var_type='entry', options=None, default_value=None):
|
67
|
-
from .gui_elements import set_dark_style
|
59
|
+
from .gui_elements import set_dark_style, set_element_size
|
68
60
|
label_column = 0
|
69
|
-
widget_column =
|
61
|
+
widget_column = 0 # Both label and widget will be in the same column
|
70
62
|
|
71
63
|
style_out = set_dark_style(ttk.Style())
|
64
|
+
font_loader = style_out['font_loader']
|
65
|
+
font_size = style_out['font_size']
|
66
|
+
size_dict = set_element_size()
|
67
|
+
size_dict['settings_width'] = size_dict['settings_width'] - int(size_dict['settings_width']*0.1)
|
72
68
|
|
73
69
|
# Replace underscores with spaces and capitalize the first letter
|
74
70
|
label_text = label_text.replace('_', ' ').capitalize()
|
75
71
|
|
76
72
|
# Configure the column widths
|
77
|
-
frame.grid_columnconfigure(label_column, weight=
|
78
|
-
|
73
|
+
frame.grid_columnconfigure(label_column, weight=1) # Allow the column to expand
|
74
|
+
|
75
|
+
# Create a custom frame with a translucent background and rounded edges
|
76
|
+
custom_frame = tk.Frame(frame, bg=style_out['bg_color'], bd=2, relief='solid', width=size_dict['settings_width'])
|
77
|
+
custom_frame.grid(column=label_column, row=row, sticky=tk.EW, padx=(5, 5), pady=5)
|
78
|
+
|
79
|
+
# Apply styles to custom frame
|
80
|
+
custom_frame.update_idletasks()
|
81
|
+
custom_frame.config(highlightbackground=style_out['bg_color'], highlightthickness=1, bd=2)
|
79
82
|
|
80
83
|
# Create and configure the label
|
81
|
-
|
82
|
-
|
84
|
+
if font_loader:
|
85
|
+
label = ttk.Label(custom_frame, text=label_text, background=style_out['bg_color'], foreground=style_out['fg_color'], font=font_loader.get_font(size=font_size), anchor='e', justify='right')
|
86
|
+
label = ttk.Label(custom_frame, text=label_text, background=style_out['bg_color'], foreground=style_out['fg_color'], font=(style_out['font_family'], style_out['font_size']), anchor='e', justify='right')
|
87
|
+
label.grid(column=label_column, row=0, sticky=tk.W, padx=(5, 2), pady=5) # Place the label in the first row
|
83
88
|
|
89
|
+
# Create and configure the input widget based on var_type
|
84
90
|
if var_type == 'entry':
|
85
91
|
var = tk.StringVar(value=default_value)
|
86
|
-
entry = spacrEntry(
|
87
|
-
entry.grid(column=widget_column, row=
|
88
|
-
return (label, entry, var) # Return both the label and the entry, and the variable
|
92
|
+
entry = spacrEntry(custom_frame, textvariable=var, outline=False, width=size_dict['settings_width'])
|
93
|
+
entry.grid(column=widget_column, row=1, sticky=tk.W, padx=(2, 5), pady=5) # Place the entry in the second row
|
94
|
+
return (label, entry, var, custom_frame) # Return both the label and the entry, and the variable
|
89
95
|
elif var_type == 'check':
|
90
96
|
var = tk.BooleanVar(value=default_value) # Set default value (True/False)
|
91
|
-
check = spacrCheck(
|
92
|
-
check.grid(column=widget_column, row=
|
93
|
-
return (label, check, var) # Return both the label and the checkbutton, and the variable
|
97
|
+
check = spacrCheck(custom_frame, text="", variable=var)
|
98
|
+
check.grid(column=widget_column, row=1, sticky=tk.W, padx=(2, 5), pady=5) # Place the checkbutton in the second row
|
99
|
+
return (label, check, var, custom_frame) # Return both the label and the checkbutton, and the variable
|
94
100
|
elif var_type == 'combo':
|
95
101
|
var = tk.StringVar(value=default_value) # Set default value
|
96
|
-
combo = spacrCombo(
|
97
|
-
combo.grid(column=widget_column, row=
|
102
|
+
combo = spacrCombo(custom_frame, textvariable=var, values=options, width=size_dict['settings_width']) # Apply TCombobox style
|
103
|
+
combo.grid(column=widget_column, row=1, sticky=tk.W, padx=(2, 5), pady=5) # Place the combobox in the second row
|
98
104
|
if default_value:
|
99
105
|
combo.set(default_value)
|
100
|
-
return (label, combo, var) # Return both the label and the combobox, and the variable
|
106
|
+
return (label, combo, var, custom_frame) # Return both the label and the combobox, and the variable
|
101
107
|
else:
|
102
108
|
var = None # Placeholder in case of an undefined var_type
|
103
|
-
return (label, None, var)
|
109
|
+
return (label, None, var, custom_frame)
|
104
110
|
|
105
111
|
def process_stdout_stderr(q):
|
106
112
|
"""
|
@@ -116,10 +122,9 @@ class WriteToQueue(io.TextIOBase):
|
|
116
122
|
"""
|
117
123
|
def __init__(self, q):
|
118
124
|
self.q = q
|
119
|
-
|
120
125
|
def write(self, msg):
|
121
|
-
|
122
|
-
|
126
|
+
if msg.strip(): # Avoid empty messages
|
127
|
+
self.q.put(msg)
|
123
128
|
def flush(self):
|
124
129
|
pass
|
125
130
|
|
@@ -309,23 +314,6 @@ def annotate_with_image_refs(settings, root, shutdown_callback):
|
|
309
314
|
# Call load_images after setting up the root window
|
310
315
|
app.load_images()
|
311
316
|
|
312
|
-
def set_element_size(widget):
|
313
|
-
screen_width = widget.winfo_screenwidth()
|
314
|
-
screen_height = widget.winfo_screenheight()
|
315
|
-
btn_size = screen_width // 40
|
316
|
-
bar_size = screen_width // 50
|
317
|
-
settings_width = screen_width // 5
|
318
|
-
panel_height = screen_height // 12
|
319
|
-
panel_width = settings_width
|
320
|
-
size_dict = {
|
321
|
-
'btn_size': btn_size,
|
322
|
-
'bar_size': bar_size,
|
323
|
-
'settings_width': settings_width,
|
324
|
-
'panel_width': panel_width,
|
325
|
-
'panel_height': panel_height
|
326
|
-
}
|
327
|
-
return size_dict
|
328
|
-
|
329
317
|
def convert_settings_dict_for_gui(settings):
|
330
318
|
from torchvision import models as torch_models
|
331
319
|
torchvision_models = [name for name, obj in torch_models.__dict__.items() if callable(obj)]
|
@@ -383,6 +371,7 @@ def convert_settings_dict_for_gui(settings):
|
|
383
371
|
variables[key] = ('entry', None, str(value))
|
384
372
|
return variables
|
385
373
|
|
374
|
+
|
386
375
|
def spacrFigShow(fig_queue=None):
|
387
376
|
"""
|
388
377
|
Replacement for plt.show() that queues figures instead of displaying them.
|
@@ -464,7 +453,7 @@ def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
|
|
464
453
|
imports = 1
|
465
454
|
elif settings_type == 'map_barcodes':
|
466
455
|
function = map_barcodes_folder
|
467
|
-
imports =
|
456
|
+
imports = 1
|
468
457
|
elif settings_type == 'regression':
|
469
458
|
function = perform_regression
|
470
459
|
imports = 2
|
@@ -481,6 +470,7 @@ def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
|
|
481
470
|
finally:
|
482
471
|
stop_requested.value = 1
|
483
472
|
|
473
|
+
|
484
474
|
def hide_all_settings(vars_dict, categories):
|
485
475
|
"""
|
486
476
|
Function to initially hide all settings in the GUI.
|
@@ -495,26 +485,27 @@ def hide_all_settings(vars_dict, categories):
|
|
495
485
|
|
496
486
|
for category, settings in categories.items():
|
497
487
|
if any(setting in vars_dict for setting in settings):
|
498
|
-
vars_dict[category] = (None, None, tk.IntVar(value=0))
|
488
|
+
vars_dict[category] = (None, None, tk.IntVar(value=0), None)
|
499
489
|
|
500
490
|
# Initially hide all settings
|
501
491
|
for setting in settings:
|
502
492
|
if setting in vars_dict:
|
503
|
-
label, widget, _ = vars_dict[setting]
|
493
|
+
label, widget, _, frame = vars_dict[setting]
|
504
494
|
label.grid_remove()
|
505
495
|
widget.grid_remove()
|
496
|
+
frame.grid_remove()
|
506
497
|
return vars_dict
|
507
498
|
|
508
499
|
def setup_frame(parent_frame):
|
509
|
-
from .gui_elements import set_dark_style,
|
500
|
+
from .gui_elements import set_dark_style, set_element_size
|
510
501
|
|
511
502
|
style = ttk.Style(parent_frame)
|
512
|
-
size_dict = set_element_size(
|
503
|
+
size_dict = set_element_size()
|
513
504
|
style_out = set_dark_style(style)
|
514
505
|
|
515
506
|
settings_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL, width=size_dict['settings_width'], bg=style_out['bg_color'])
|
516
|
-
vertical_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL, bg=style_out['bg_color'])
|
517
|
-
horizontal_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL, height=size_dict['panel_height'], bg=style_out['bg_color'])
|
507
|
+
vertical_container = tk.PanedWindow(parent_frame, orient=tk.VERTICAL, width=size_dict['panel_width'], bg=style_out['bg_color'])
|
508
|
+
horizontal_container = tk.PanedWindow(parent_frame, orient=tk.HORIZONTAL, height=size_dict['panel_height'], width=size_dict['panel_width'], bg=style_out['bg_color'])
|
518
509
|
|
519
510
|
parent_frame.grid_rowconfigure(0, weight=1)
|
520
511
|
parent_frame.grid_rowconfigure(1, weight=0)
|
@@ -523,22 +514,18 @@ def setup_frame(parent_frame):
|
|
523
514
|
|
524
515
|
settings_container.grid(row=0, column=0, rowspan=2, sticky="nsew")
|
525
516
|
vertical_container.grid(row=0, column=1, sticky="nsew")
|
526
|
-
horizontal_container.grid(row=1, column=1, sticky="
|
517
|
+
horizontal_container.grid(row=1, column=1, sticky="ew")
|
527
518
|
|
528
|
-
#
|
529
|
-
|
530
|
-
|
531
|
-
parent_frame.grid_columnconfigure(1, weight=0)
|
532
|
-
horizontal_container.config(width=fixed_width)
|
519
|
+
# Ensure settings_container maintains its width
|
520
|
+
settings_container.grid_propagate(False)
|
521
|
+
settings_container.update_idletasks()
|
533
522
|
|
534
|
-
tk.Label(settings_container, text="Settings Container", bg=style_out['bg_color']).
|
535
|
-
tk.Label(vertical_container, text="Vertical Container", bg=style_out['bg_color']).pack(fill=tk.BOTH, expand=True)
|
523
|
+
tk.Label(settings_container, text="Settings Container", bg=style_out['bg_color']).grid(row=0, column=0, sticky="ew")
|
536
524
|
|
537
525
|
set_dark_style(style, parent_frame, [settings_container, vertical_container, horizontal_container])
|
538
526
|
|
539
|
-
size = style_out['font_size'] - 2
|
540
|
-
|
541
|
-
set_default_font(parent_frame, font_name=style_out['font_family'], size=size)
|
527
|
+
#size = style_out['font_size'] - 2
|
528
|
+
#set_default_font(parent_frame, font_name=style_out['font_family'], size=size)
|
542
529
|
|
543
530
|
return parent_frame, vertical_container, horizontal_container, settings_container
|
544
531
|
|
@@ -622,3 +609,7 @@ def download_dataset(q, repo_id, subfolder, local_dir=None, retries=5, delay=5):
|
|
622
609
|
time.sleep(delay)
|
623
610
|
|
624
611
|
raise Exception("Failed to download files after multiple attempts.")
|
612
|
+
|
613
|
+
def ensure_after_tasks(frame):
|
614
|
+
if not hasattr(frame, 'after_tasks'):
|
615
|
+
frame.after_tasks = []
|
spacr/io.py
CHANGED
@@ -597,7 +597,6 @@ def _rename_and_organize_image_files(src, regex, batch_size=100, pick_slice=Fals
|
|
597
597
|
for idx in range(0, len(all_filenames), batch_size):
|
598
598
|
start = time.time()
|
599
599
|
batch_filenames = all_filenames[idx:idx+batch_size]
|
600
|
-
files_processed = 0
|
601
600
|
for filename in batch_filenames:
|
602
601
|
images_by_key = _extract_filename_metadata(batch_filenames, src, images_by_key, regular_expression, metadata_type, pick_slice, skip_mode)
|
603
602
|
|
@@ -974,7 +973,7 @@ def _concatenate_channel(src, channels, randomize=True, timelapse=False, batch_s
|
|
974
973
|
time_ls.append(duration)
|
975
974
|
files_processed = i+1
|
976
975
|
files_to_process = time_stack_path_lists
|
977
|
-
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=
|
976
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type="Concatinating")
|
978
977
|
stack = np.stack(stack_region)
|
979
978
|
save_loc = os.path.join(channel_stack_loc, f'{name}.npz')
|
980
979
|
np.savez(save_loc, data=stack, filenames=filenames_region)
|
@@ -1005,7 +1004,7 @@ def _concatenate_channel(src, channels, randomize=True, timelapse=False, batch_s
|
|
1005
1004
|
time_ls.append(duration)
|
1006
1005
|
files_processed = i+1
|
1007
1006
|
files_to_process = nr_files
|
1008
|
-
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=
|
1007
|
+
print_progress(files_processed, files_to_process, n_jobs=1, time_ls=time_ls, batch_size=batch_size, operation_type="Concatinating")
|
1009
1008
|
if (i+1) % batch_size == 0 or i+1 == nr_files:
|
1010
1009
|
unique_shapes = {arr.shape[:-1] for arr in stack_ls}
|
1011
1010
|
if len(unique_shapes) > 1:
|