spacr 0.2.61__tar.gz → 0.2.65__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.2.61/spacr.egg-info → spacr-0.2.65}/PKG-INFO +1 -1
- {spacr-0.2.61 → spacr-0.2.65}/setup.py +1 -1
- {spacr-0.2.61 → spacr-0.2.65}/spacr/__init__.py +1 -3
- {spacr-0.2.61 → spacr-0.2.65}/spacr/gui_core.py +136 -137
- {spacr-0.2.61 → spacr-0.2.65}/spacr/gui_elements.py +301 -1
- {spacr-0.2.61 → spacr-0.2.65}/spacr/gui_utils.py +39 -2
- {spacr-0.2.61 → spacr-0.2.65}/spacr/plot.py +4 -4
- {spacr-0.2.61 → spacr-0.2.65}/spacr/sequencing.py +4 -8
- {spacr-0.2.61 → spacr-0.2.65}/spacr/utils.py +1 -1
- {spacr-0.2.61 → spacr-0.2.65/spacr.egg-info}/PKG-INFO +1 -1
- {spacr-0.2.61 → spacr-0.2.65}/spacr.egg-info/SOURCES.txt +0 -1
- spacr-0.2.61/spacr/chris.py +0 -50
- {spacr-0.2.61 → spacr-0.2.65}/LICENSE +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/MANIFEST.in +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/README.rst +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/setup.cfg +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/__main__.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/app_annotate.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/app_classify.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/app_make_masks.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/app_mask.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/app_measure.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/app_sequencing.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/app_umap.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/core.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/deep_spacr.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/graph_learning.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/gui.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/io.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/logger.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/measure.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/OFL.txt +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/README.txt +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-Bold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-BoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-ExtraBold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-ExtraBoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-Italic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-Light.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-LightItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-Medium.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-MediumItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-Regular.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-SemiBold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans-SemiBoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Bold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-BoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Italic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Light.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-LightItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Medium.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-MediumItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-Regular.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Bold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Italic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Light.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Medium.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Regular.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/abort.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/annotate.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/cellpose_all.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/cellpose_masks.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/classify.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/default.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/download.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/logo.pdf +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/logo_spacr.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/logo_spacr_1.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/make_masks.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/map_barcodes.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/mask.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/measure.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/ml_analyze.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/recruitment.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/regression.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/run.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/sequencing.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/settings.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/spacr_logo_rotation.gif +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/train_cellpose.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/icons/umap.png +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/models/cp/toxo_plaque_cyto_e25000_X1120_Y1120.CP_model_settings.csv +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/resources/models/cp/toxo_pv_lumen.CP_model +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/settings.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/sim.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/sim_app.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/timelapse.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr/version.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr.egg-info/dependency_links.txt +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr.egg-info/entry_points.txt +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr.egg-info/requires.txt +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/spacr.egg-info/top_level.txt +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_annotate_app.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_core.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_gui_classify_app.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_gui_mask_app.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_gui_measure_app.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_gui_sim_app.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_gui_utils.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_io.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_mask_app.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_measure.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_plot.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_sim.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_timelapse.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_train.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_umap.py +0 -0
- {spacr-0.2.61 → spacr-0.2.65}/tests/test_utils.py +0 -0
@@ -17,7 +17,6 @@ from . import gui_utils
|
|
17
17
|
from . import gui_elements
|
18
18
|
from . import gui_core
|
19
19
|
from . import gui
|
20
|
-
from . import gui
|
21
20
|
from . import app_make_masks
|
22
21
|
from . import app_mask
|
23
22
|
from . import app_measure
|
@@ -35,7 +34,7 @@ __all__ = [
|
|
35
34
|
"plot",
|
36
35
|
"measure",
|
37
36
|
"sim",
|
38
|
-
"sequencing"
|
37
|
+
"sequencing",
|
39
38
|
"timelapse",
|
40
39
|
"deep_spacr",
|
41
40
|
"app_annotate",
|
@@ -43,7 +42,6 @@ __all__ = [
|
|
43
42
|
"gui_elements",
|
44
43
|
"gui_core",
|
45
44
|
"gui",
|
46
|
-
"gui",
|
47
45
|
"app_make_masks",
|
48
46
|
"app_mask",
|
49
47
|
"app_measure",
|
@@ -83,12 +83,22 @@ def toggle_settings(button_scrollable_frame):
|
|
83
83
|
def process_fig_queue():
|
84
84
|
global canvas, fig_queue, canvas_widget, parent_frame, uppdate_frequency, figures, figure_index
|
85
85
|
|
86
|
+
from .gui_elements import standardize_figure
|
86
87
|
try:
|
87
88
|
while not fig_queue.empty():
|
88
89
|
fig = fig_queue.get_nowait()
|
90
|
+
|
91
|
+
if fig is None:
|
92
|
+
print("Warning: Retrieved a None figure from fig_queue.")
|
93
|
+
continue # Skip processing if the figure is None
|
94
|
+
|
95
|
+
# Standardize the figure appearance before adding it to the list
|
96
|
+
standardize_figure(fig)
|
97
|
+
|
89
98
|
figures.append(fig)
|
90
|
-
figure_index
|
91
|
-
|
99
|
+
if figure_index == len(figures) - 2:
|
100
|
+
figure_index += 1
|
101
|
+
display_figure(fig)
|
92
102
|
except Exception as e:
|
93
103
|
traceback.print_exc()
|
94
104
|
finally:
|
@@ -98,8 +108,23 @@ def process_fig_queue():
|
|
98
108
|
def display_figure(fig):
|
99
109
|
global canvas, canvas_widget
|
100
110
|
|
111
|
+
from .gui_elements import modify_figure_properties, save_figure_as_format, modify_figure
|
112
|
+
|
113
|
+
# Apply the dark style to the context menu
|
114
|
+
style_out = set_dark_style(ttk.Style())
|
115
|
+
bg_color = style_out['bg_color']
|
116
|
+
fg_color = style_out['fg_color']
|
117
|
+
|
118
|
+
# Initialize the scale factor for zooming
|
119
|
+
scale_factor = 1.0
|
120
|
+
|
121
|
+
# Save the original x and y limits of the first axis (assuming all axes have the same limits)
|
122
|
+
original_xlim = [ax.get_xlim() for ax in fig.get_axes()]
|
123
|
+
original_ylim = [ax.get_ylim() for ax in fig.get_axes()]
|
124
|
+
|
101
125
|
# Clear previous canvas content
|
102
|
-
canvas
|
126
|
+
if canvas:
|
127
|
+
canvas.get_tk_widget().destroy()
|
103
128
|
|
104
129
|
# Create a new canvas for the figure
|
105
130
|
new_canvas = FigureCanvasTkAgg(fig, master=canvas_widget.master)
|
@@ -109,154 +134,141 @@ def display_figure(fig):
|
|
109
134
|
# Update the global canvas and canvas_widget references
|
110
135
|
canvas = new_canvas
|
111
136
|
canvas_widget = new_canvas.get_tk_widget()
|
112
|
-
|
113
|
-
# Apply the dark style to the context menu
|
114
|
-
style_out = set_dark_style(ttk.Style())
|
115
|
-
bg_color = style_out['bg_color']
|
116
|
-
fg_color = style_out['fg_color']
|
117
|
-
|
118
|
-
# Define the save functions for the context menu
|
119
|
-
def save_figure_as_format(format):
|
120
|
-
file_path = filedialog.asksaveasfilename(defaultextension=f".{format}", filetypes=[(f"{format.upper()} files", f"*.{format}"), ("All files", "*.*")])
|
121
|
-
if file_path:
|
122
|
-
fig.savefig(file_path, format=format)
|
123
|
-
|
124
|
-
def modify_figure():
|
125
|
-
def apply_modifications():
|
126
|
-
try:
|
127
|
-
x_width = float(x_width_var.get())
|
128
|
-
y_height = float(y_height_var.get())
|
129
|
-
line_width = float(line_width_var.get())
|
130
|
-
font_size = int(font_size_var.get())
|
131
|
-
modify_figure_properties(fig, x_width=x_width, y_height=y_height, line_width=line_width)
|
132
|
-
for ax in fig.get_axes():
|
133
|
-
for label in ax.get_xticklabels() + ax.get_yticklabels():
|
134
|
-
label.set_fontsize(font_size)
|
135
|
-
ax.title.set_fontsize(font_size)
|
136
|
-
ax.xaxis.label.set_fontsize(font_size)
|
137
|
-
ax.yaxis.label.set_fontsize(font_size)
|
138
|
-
canvas.draw_idle() # Redraw the canvas after modifications
|
139
|
-
except ValueError:
|
140
|
-
print("Invalid input; please enter numeric values.")
|
141
|
-
|
142
|
-
# Create a new window for user input
|
143
|
-
modify_window = tk.Toplevel()
|
144
|
-
modify_window.title("Modify Figure Properties")
|
145
|
-
|
146
|
-
# Apply dark style to the popup window
|
147
|
-
modify_window.configure(bg=bg_color)
|
148
|
-
|
149
|
-
# Create and style the input fields
|
150
|
-
tk.Label(modify_window, text="X Axis Width:", bg=bg_color, fg=fg_color).grid(row=0, column=0, padx=10, pady=5)
|
151
|
-
x_width_var = tk.StringVar()
|
152
|
-
tk.Entry(modify_window, textvariable=x_width_var, bg=bg_color, fg=fg_color).grid(row=0, column=1, padx=10, pady=5)
|
153
|
-
|
154
|
-
tk.Label(modify_window, text="Y Axis Height:", bg=bg_color, fg=fg_color).grid(row=1, column=0, padx=10, pady=5)
|
155
|
-
y_height_var = tk.StringVar()
|
156
|
-
tk.Entry(modify_window, textvariable=y_height_var, bg=bg_color, fg=fg_color).grid(row=1, column=1, padx=10, pady=5)
|
157
|
-
|
158
|
-
tk.Label(modify_window, text="Line Width:", bg=bg_color, fg=fg_color).grid(row=2, column=0, padx=10, pady=5)
|
159
|
-
line_width_var = tk.StringVar()
|
160
|
-
tk.Entry(modify_window, textvariable=line_width_var, bg=bg_color, fg=fg_color).grid(row=2, column=1, padx=10, pady=5)
|
161
|
-
|
162
|
-
tk.Label(modify_window, text="Font Size:", bg=bg_color, fg=fg_color).grid(row=3, column=0, padx=10, pady=5)
|
163
|
-
font_size_var = tk.StringVar()
|
164
|
-
tk.Entry(modify_window, textvariable=font_size_var, bg=bg_color, fg=fg_color).grid(row=3, column=1, padx=10, pady=5)
|
165
|
-
|
166
|
-
# Apply button
|
167
|
-
apply_button = tk.Button(modify_window, text="Apply", command=apply_modifications, bg=bg_color, fg=fg_color)
|
168
|
-
apply_button.grid(row=4, column=0, columnspan=2, pady=10)
|
137
|
+
canvas_widget.configure(bg=bg_color)
|
169
138
|
|
170
139
|
# Create the context menu
|
171
140
|
context_menu = tk.Menu(canvas_widget, tearoff=0, bg=bg_color, fg=fg_color)
|
172
|
-
context_menu.add_command(label="Save Figure as PDF", command=lambda: save_figure_as_format('pdf'))
|
173
|
-
context_menu.add_command(label="Save Figure as PNG", command=lambda: save_figure_as_format('png'))
|
174
|
-
context_menu.add_command(label="Modify Figure", command=modify_figure)
|
141
|
+
context_menu.add_command(label="Save Figure as PDF", command=lambda: save_figure_as_format(fig, 'pdf'))
|
142
|
+
context_menu.add_command(label="Save Figure as PNG", command=lambda: save_figure_as_format(fig, 'png'))
|
143
|
+
context_menu.add_command(label="Modify Figure", command=lambda: modify_figure(fig))
|
144
|
+
context_menu.add_command(label="Reset Zoom", command=lambda: reset_zoom(fig)) # Add Reset Zoom option
|
145
|
+
|
146
|
+
def reset_zoom(fig):
|
147
|
+
global scale_factor
|
148
|
+
scale_factor = 1.0 # Reset the scale factor
|
149
|
+
|
150
|
+
for i, ax in enumerate(fig.get_axes()):
|
151
|
+
ax.set_xlim(original_xlim[i])
|
152
|
+
ax.set_ylim(original_ylim[i])
|
153
|
+
fig.canvas.draw_idle()
|
175
154
|
|
176
155
|
def on_right_click(event):
|
177
156
|
context_menu.post(event.x_root, event.y_root)
|
178
157
|
|
179
|
-
|
158
|
+
def on_hover(event):
|
159
|
+
widget_width = event.widget.winfo_width()
|
160
|
+
x_position = event.x
|
161
|
+
|
162
|
+
if x_position < widget_width / 2:
|
163
|
+
canvas_widget.config(cursor="hand2")
|
164
|
+
else:
|
165
|
+
canvas_widget.config(cursor="hand2")
|
166
|
+
|
167
|
+
def on_leave(event):
|
168
|
+
canvas_widget.config(cursor="arrow")
|
169
|
+
|
170
|
+
def flash_feedback(side):
|
171
|
+
flash = tk.Toplevel(canvas_widget.master)
|
172
|
+
flash.overrideredirect(True)
|
173
|
+
flash_width = int(canvas_widget.winfo_width() / 2)
|
174
|
+
flash_height = canvas_widget.winfo_height()
|
175
|
+
flash.configure(bg='white')
|
176
|
+
flash.attributes('-alpha', 0.9)
|
177
|
+
|
178
|
+
if side == "left":
|
179
|
+
flash.geometry(f"{flash_width}x{flash_height}+{canvas_widget.winfo_rootx()}+{canvas_widget.winfo_rooty()}")
|
180
|
+
else:
|
181
|
+
flash.geometry(f"{flash_width}x{flash_height}+{canvas_widget.winfo_rootx() + flash_width}+{canvas_widget.winfo_rooty()}")
|
182
|
+
|
183
|
+
flash.lift()
|
184
|
+
|
185
|
+
# Ensure the flash covers the correct area only
|
186
|
+
flash.update_idletasks()
|
187
|
+
flash.after(100, flash.destroy)
|
188
|
+
|
189
|
+
def on_click(event):
|
190
|
+
widget_width = event.widget.winfo_width()
|
191
|
+
x_position = event.x
|
192
|
+
|
193
|
+
if x_position < widget_width / 2:
|
194
|
+
#flash_feedback("left")
|
195
|
+
show_previous_figure()
|
196
|
+
else:
|
197
|
+
#flash_feedback("right")
|
198
|
+
show_next_figure()
|
199
|
+
|
200
|
+
def zoom(event):
|
201
|
+
nonlocal scale_factor
|
202
|
+
|
203
|
+
zoom_speed = 0.1 # Adjust the zoom speed for smoother experience
|
204
|
+
|
205
|
+
# Adjust zoom factor based on the operating system and mouse event
|
206
|
+
if event.num == 4 or event.delta > 0: # Scroll up
|
207
|
+
scale_factor *= (1 + zoom_speed)
|
208
|
+
elif event.num == 5 or event.delta < 0: # Scroll down
|
209
|
+
scale_factor /= (1 + zoom_speed)
|
210
|
+
|
211
|
+
# Get mouse position relative to the figure
|
212
|
+
x_mouse, y_mouse = event.x, event.y
|
213
|
+
x_ratio = x_mouse / canvas_widget.winfo_width()
|
214
|
+
y_ratio = y_mouse / canvas_widget.winfo_height()
|
215
|
+
|
216
|
+
for ax in fig.get_axes():
|
217
|
+
xlim = ax.get_xlim()
|
218
|
+
ylim = ax.get_ylim()
|
219
|
+
|
220
|
+
# Calculate the new limits
|
221
|
+
x_center = xlim[0] + x_ratio * (xlim[1] - xlim[0])
|
222
|
+
y_center = ylim[0] + (1 - y_ratio) * (ylim[1] - ylim[0])
|
223
|
+
|
224
|
+
x_range = (xlim[1] - xlim[0]) * scale_factor
|
225
|
+
y_range = (ylim[1] - ylim[0]) * scale_factor
|
226
|
+
|
227
|
+
ax.set_xlim([x_center - x_range * x_ratio, x_center + x_range * (1 - x_ratio)])
|
228
|
+
ax.set_ylim([y_center - y_range * (1 - y_ratio), y_center + y_range * y_ratio])
|
229
|
+
|
230
|
+
# Redraw the figure
|
231
|
+
fig.canvas.draw_idle()
|
232
|
+
|
233
|
+
# Bind events for hover, click interactions, and zoom
|
234
|
+
canvas_widget.bind("<Motion>", on_hover)
|
235
|
+
canvas_widget.bind("<Leave>", on_leave)
|
236
|
+
canvas_widget.bind("<Button-1>", on_click)
|
237
|
+
canvas_widget.bind("<Button-3>", on_right_click)
|
238
|
+
|
239
|
+
# Bind mouse wheel for zooming (cross-platform)
|
240
|
+
canvas_widget.bind("<MouseWheel>", zoom) # Windows
|
241
|
+
canvas_widget.bind("<Button-4>", zoom) # Linux/macOS Scroll Up
|
242
|
+
canvas_widget.bind("<Button-5>", zoom) # Linux/macOS Scroll Down
|
180
243
|
|
181
244
|
def clear_unused_figures():
|
182
245
|
global figures, figure_index
|
183
246
|
|
184
247
|
lower_bound = max(0, figure_index - 20)
|
185
248
|
upper_bound = min(len(figures), figure_index + 20)
|
186
|
-
|
187
249
|
# Clear figures outside of the +/- 20 range
|
188
250
|
figures = deque([fig for i, fig in enumerate(figures) if lower_bound <= i <= upper_bound])
|
189
|
-
|
190
251
|
# Update the figure index after clearing
|
191
252
|
figure_index = min(max(figure_index, 0), len(figures) - 1)
|
192
253
|
|
193
254
|
def show_previous_figure():
|
194
|
-
global figure_index, figures
|
255
|
+
global figure_index, figures, fig_queue
|
195
256
|
if figure_index is not None and figure_index > 0:
|
196
257
|
figure_index -= 1
|
197
258
|
display_figure(figures[figure_index])
|
198
259
|
clear_unused_figures()
|
199
260
|
|
200
261
|
def show_next_figure():
|
201
|
-
global figure_index, figures
|
262
|
+
global figure_index, figures, fig_queue
|
202
263
|
if figure_index is not None and figure_index < len(figures) - 1:
|
203
264
|
figure_index += 1
|
204
265
|
display_figure(figures[figure_index])
|
205
266
|
clear_unused_figures()
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
fig.savefig(file_path, format=file_format)
|
212
|
-
print(f"Figure saved as {file_format.upper()} at {file_path}")
|
213
|
-
except Exception as e:
|
214
|
-
print(f"Error saving figure: {e}")
|
215
|
-
|
216
|
-
def modify_figure_properties(fig, x_width=None, y_height=None, line_width=None):
|
217
|
-
"""
|
218
|
-
Modifies the properties of the figure, including axis dimensions and line widths.
|
219
|
-
|
220
|
-
Parameters:
|
221
|
-
- fig: The matplotlib figure object to modify.
|
222
|
-
- x_width: Desired width for the x-axis (optional).
|
223
|
-
- y_height: Desired height for the y-axis (optional).
|
224
|
-
- line_width: Desired line width for all lines (optional).
|
225
|
-
"""
|
226
|
-
for ax in fig.get_axes():
|
227
|
-
# Scaling the figure
|
228
|
-
if x_width is not None or y_height is not None:
|
229
|
-
# Get the current axis limits
|
230
|
-
current_xlim = ax.get_xlim()
|
231
|
-
current_ylim = ax.get_ylim()
|
232
|
-
|
233
|
-
# Set new limits
|
234
|
-
if x_width is not None:
|
235
|
-
scale_factor_x = x_width / (current_xlim[1] - current_xlim[0])
|
236
|
-
else:
|
237
|
-
scale_factor_x = 1
|
238
|
-
|
239
|
-
if y_height is not None:
|
240
|
-
scale_factor_y = y_height / (current_ylim[1] - current_ylim[0])
|
241
|
-
else:
|
242
|
-
scale_factor_y = 1
|
243
|
-
|
244
|
-
# Adjust the figure size and elements proportionally
|
245
|
-
fig.set_size_inches(fig.get_size_inches() * scale_factor_x * scale_factor_y, forward=True)
|
246
|
-
ax.set_xlim(left=current_xlim[0] * scale_factor_x, right=current_xlim[1] * scale_factor_x)
|
247
|
-
ax.set_ylim(bottom=current_ylim[0] * scale_factor_y, top=current_ylim[1] * scale_factor_y)
|
248
|
-
|
249
|
-
# Adjust line width and other elements if specified
|
250
|
-
if line_width is not None:
|
251
|
-
for line in ax.get_lines():
|
252
|
-
line.set_linewidth(line_width)
|
253
|
-
for spine in ax.spines.values(): # Modify width of spines (e.g., scale bars)
|
254
|
-
spine.set_linewidth(line_width)
|
255
|
-
ax.tick_params(width=line_width) # Modify width of ticks
|
256
|
-
for text in ax.get_xticklabels() + ax.get_yticklabels():
|
257
|
-
text.set_fontsize(ax.get_xticklabels()[0].get_fontsize())
|
258
|
-
|
259
|
-
fig.canvas.draw_idle()
|
267
|
+
elif figure_index == len(figures) - 1 and not fig_queue.empty():
|
268
|
+
fig = fig_queue.get_nowait()
|
269
|
+
figures.append(fig)
|
270
|
+
figure_index += 1
|
271
|
+
display_figure(fig)
|
260
272
|
|
261
273
|
def set_globals(thread_control_var, q_var, console_output_var, parent_frame_var, vars_dict_var, canvas_var, canvas_widget_var, scrollable_frame_var, fig_queue_var, figures_var, figure_index_var, progress_bar_var, usage_bars_var, fig_memory_limit_var, figure_current_memory_usage_var):
|
262
274
|
global thread_control, q, console_output, parent_frame, vars_dict, canvas, canvas_widget, scrollable_frame, fig_queue, figures, figure_index, progress_bar, usage_bars, fig_memory_limit, figure_current_memory_usage
|
@@ -416,7 +428,7 @@ def setup_plot_section(vertical_container):
|
|
416
428
|
plot_frame.grid_columnconfigure(0, weight=1)
|
417
429
|
|
418
430
|
canvas.draw()
|
419
|
-
canvas.figure = figure
|
431
|
+
canvas.figure = figure # Ensure that the figure is linked to the canvas
|
420
432
|
style_out = set_dark_style(ttk.Style())
|
421
433
|
|
422
434
|
figure.patch.set_facecolor(style_out['bg_color'])
|
@@ -425,19 +437,6 @@ def setup_plot_section(vertical_container):
|
|
425
437
|
widgets = [canvas_widget]
|
426
438
|
style = ttk.Style(vertical_container)
|
427
439
|
_ = set_dark_style(style, containers=containers, widgets=widgets)
|
428
|
-
|
429
|
-
# Add navigation buttons using spacrButton
|
430
|
-
button_frame = tk.Frame(plot_frame, bg=style_out['bg_color'])
|
431
|
-
button_frame.grid(row=1, column=0, sticky='ew', pady=5)
|
432
|
-
|
433
|
-
size_dict = set_element_size()
|
434
|
-
|
435
|
-
btn_size = int(size_dict['btn_size']*0.75)
|
436
|
-
prev_button = spacrButton(button_frame, text="Previous", command=show_previous_figure, bg=style_out['bg_color'], show_text=False, size=btn_size, animation=False)
|
437
|
-
prev_button.pack(side='left', padx=5)
|
438
|
-
|
439
|
-
next_button = spacrButton(button_frame, text="Next", command=show_next_figure, bg=style_out['bg_color'], show_text=False, size=btn_size, animation=False)
|
440
|
-
next_button.pack(side='right', padx=5)
|
441
440
|
|
442
441
|
return canvas, canvas_widget
|
443
442
|
|
@@ -842,7 +841,7 @@ def initiate_root(parent, settings_type='mask'):
|
|
842
841
|
from .gui_utils import setup_frame
|
843
842
|
from .settings import descriptions
|
844
843
|
|
845
|
-
uppdate_frequency =
|
844
|
+
uppdate_frequency = 100
|
846
845
|
|
847
846
|
# Start tracemalloc and initialize global variables
|
848
847
|
tracemalloc.start()
|