Skip to content

Commit 49b04c2

Browse files
sleeping now
1 parent 548cb48 commit 49b04c2

15 files changed

Lines changed: 273 additions & 129 deletions

Keithley_2400/Backends/IV_K2400_Loop_Backend_v10.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import numpy as np
2323
import matplotlib.pyplot as plt
2424
from time import sleep
25-
import pyvisa
2625
from pymeasure.instruments.keithley import Keithley2400
2726
import pandas as pd
2827

@@ -90,8 +89,4 @@ def IV_Measure(cur):
9089
plt.title('I-V Curve')
9190
plt.legend()
9291
plt.grid(True)
93-
plt.show()
94-
95-
96-
if __name__ == "__main__":
97-
main()
92+
plt.show()

Keithley_6517B/High_Resistance/Backends/IV_K6517B_Simple_Backend_v10.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ def get_sweep_parameters():
5454
filename += '.csv'
5555
return start_v, stop_v, steps, delay, filename
5656

57-
5857
def plot_results(data):
5958
"""Plots the I-V curve from the collected data."""
6059
if not data:

Keithley_6517B/High_Resistance/IV_K6517B_GUI_v11.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ def setup_styles(self):
314314
focuscolor='none')
315315
style.map(
316316
'TButton',
317-
background=[('active', self.CLR_ACCENT_GOLD), ('hover', self.CLR_ACCENT_GOLD)],
318-
foreground=[('active', self.CLR_TEXT_DARK), ('hover', self.CLR_TEXT_DARK)]
317+
background=[('active', self.CLR_ACCENT_GOLD),
318+
('hover', self.CLR_ACCENT_GOLD)],
319+
foreground=[('active', self.CLR_TEXT_DARK),
320+
('hover', self.CLR_TEXT_DARK)]
319321
)
320322
style.configure(
321323
'Start.TButton',

Keithley_6517B/Pyroelectricity/Pyroelectric_K6517B_L350_GUI_v4.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -849,9 +849,9 @@ def _process_data_queue(self):
849849
elif state == 'ramping':
850850
elapsed_time = time.time() - self.start_time
851851
log_msg = (
852-
f"Ramping... Time: {elapsed_time:7.1f}s | "
853-
f"Temp: {current_temp:8.4f}K | "
854-
f"Current: {current_val:.3e} A"
852+
f"Time: {elapsed_time:.1f}s | "
853+
f"Temp: {current_temp:.2f}K | "
854+
f"Current: {current_val:.2e}A"
855855
)
856856
self.log(log_msg)
857857

PICA_v6.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,6 @@ def _configure_scrollable_frame(event):
504504
5, 10), pady=(
505505
0, 15))
506506

507-
508507
# --- Left Column Suites ---
509508
self._create_suite_frame(left_col,
510509
'Low Resistance (10 nΩ to 100 MΩ)',

Utilities/LivePlotter_v10.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def animate(i):
6969
axs[2].set_ylabel('Voltage (V)', fontsize=13)
7070
axs[2].legend(loc='upper left')
7171

72-
ani = FuncAnimation(plt.gcf(), animate, interval=1000, cache_frame_data=False)
72+
ani = FuncAnimation(plt.gcf(), animate, interval=1000, cache_frame_data=False) # noqa: F841
7373

7474
plt.tight_layout()
7575
plt.show()

Utilities/PlotterUtil_GUI_v3.py

Lines changed: 199 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -954,96 +954,207 @@ def _finalize_plot(self, x_col, y_col, selected_filepaths):
954954
else:
955955
legend_title = "Multiple Files"
956956

957-
leg = self.ax_main.legend(title=legend_title, labelcolor=self.CLR_CONSOLE_BG)
958-
if leg:
959-
leg.get_title().set_color(self.CLR_CONSOLE_BG)
960-
961-
self.ax_main.set_xscale(
962-
'log' if self.x_log_var.get() else 'linear') # type: ignore
963-
self.ax_main.set_yscale(
964-
'log' if self.y_log_var.get() else 'linear')
965-
self.ax_main.set_xlabel(x_col)
966-
self.ax_main.set_ylabel(y_col)
967-
968-
if len(selected_filepaths) == 1:
969-
self.ax_main.set_title(
970-
os.path.basename(
971-
selected_filepaths[0]),
972-
fontweight='bold')
973-
else:
974-
self.ax_main.set_title(
975-
f"{y_col} vs. {x_col}",
976-
fontweight='bold')
977-
self.figure.tight_layout()
978-
979-
def _handle_load_error(self, filepath, e):
980-
"""Handles errors during file loading."""
981-
if filepath in self.file_data_cache:
982-
self.file_data_cache[filepath] = {
983-
"path": filepath, "headers": [], "data": {}}
984-
self.column_source_var.set("Columns from: (no file selected)")
985-
self.active_filepath = None
986-
self.plot_data()
987-
self.x_col_cb.set('')
988-
self.y_col_cb.set('')
989-
self.x_col_cb['values'] = []
990-
self.y_col_cb['values'] = []
991-
self.live_update_var.set(False)
992-
self.toggle_live_update()
993-
self.log(f"Error loading file: {traceback.format_exc()}")
994-
messagebox.showerror(
995-
"File Load Error",
996-
f"Could not read the data file. It may be empty, malformed, or in use.\n\nDetails: {e}")
997-
998-
def toggle_live_update(self):
999-
if self.live_update_var.get():
1000-
self.start_file_watcher()
1001-
else:
1002-
self.stop_file_watcher()
1003-
1004-
def start_file_watcher(self):
1005-
self.stop_file_watcher() # Ensure no multiple watchers are running
1006-
if self.live_update_var.get() and self.active_filepath:
1007-
self.log("Live update enabled. Watching for file changes...")
1008-
self.file_watcher_job = self.root.after(
1009-
1000, self.check_for_updates)
1010-
1011-
def stop_file_watcher(self):
1012-
if self.file_watcher_job:
1013-
self.root.after_cancel(self.file_watcher_job)
1014-
self.file_watcher_job = None
1015-
self.log("Live update disabled.")
1016-
1017-
def check_for_updates(self):
1018-
if not self.active_filepath or not self.live_update_var.get(
1019-
) or not os.path.exists(self.active_filepath):
1020-
self.file_watcher_job = None # Stop watching if file is gone or disabled
1021-
return
1022-
1023-
try:
1024-
file_info = self.file_data_cache[self.active_filepath]
1025-
mod_time = os.path.getmtime(self.active_filepath)
1026-
current_size = os.path.getsize(self.active_filepath)
1027-
1028-
if mod_time != file_info.get('mod_time'):
1029-
if current_size > file_info.get('size', 0):
1030-
# File has grown, append new data
1031-
self.append_file_data()
957+
leg = self.ax_main.legend(title=legend_title,
958+
959+
labelcolor=self.CLR_CONSOLE_BG)
960+
961+
if leg:
962+
963+
leg.get_title().set_color(self.CLR_CONSOLE_BG)
964+
965+
966+
967+
self.ax_main.set_xscale(
968+
969+
'log' if self.x_log_var.get() else 'linear') # type: ignore
970+
971+
self.ax_main.set_yscale(
972+
973+
'log' if self.y_log_var.get() else 'linear')
974+
975+
self.ax_main.set_xlabel(x_col)
976+
977+
self.ax_main.set_ylabel(y_col)
978+
979+
980+
981+
if len(selected_filepaths) == 1:
982+
983+
self.ax_main.set_title(
984+
985+
os.path.basename(
986+
987+
selected_filepaths[0]),
988+
989+
fontweight='bold')
990+
991+
else:
992+
993+
self.ax_main.set_title(
994+
995+
f"{y_col} vs. {x_col}",
996+
997+
fontweight='bold')
998+
999+
self.figure.tight_layout()
1000+
1001+
1002+
1003+
def _handle_load_error(self, filepath, e):
1004+
1005+
"""Handles errors during file loading."""
1006+
1007+
if filepath in self.file_data_cache:
1008+
1009+
self.file_data_cache[filepath] = {
1010+
1011+
"path": filepath, "headers": [], "data": {}}
1012+
1013+
self.column_source_var.set("Columns from: (no file selected)")
1014+
1015+
self.active_filepath = None
1016+
1017+
self.plot_data()
1018+
1019+
self.x_col_cb.set('')
1020+
1021+
self.y_col_cb.set('')
1022+
1023+
self.x_col_cb['values'] = []
1024+
1025+
self.y_col_cb['values'] = []
1026+
1027+
self.live_update_var.set(False)
1028+
1029+
self.toggle_live_update()
1030+
1031+
self.log(f"Error loading file: {traceback.format_exc()}")
1032+
1033+
messagebox.showerror(
1034+
1035+
"File Load Error",
1036+
1037+
f"Could not read the data file. It may be empty, malformed, or in use.\n\nDetails: {e}")
1038+
1039+
1040+
1041+
def toggle_live_update(self):
1042+
1043+
if self.live_update_var.get():
1044+
1045+
self.start_file_watcher()
1046+
10321047
else:
1033-
# File was overwritten or shrunk, do a full reload
1048+
1049+
self.stop_file_watcher()
1050+
1051+
1052+
1053+
def start_file_watcher(self):
1054+
1055+
self.stop_file_watcher() # Ensure no multiple watchers are running
1056+
1057+
if self.live_update_var.get() and self.active_filepath:
1058+
1059+
self.log("Live update enabled. Watching for file changes...")
1060+
1061+
self.file_watcher_job = self.root.after(
1062+
1063+
1000, self.check_for_updates)
1064+
1065+
1066+
1067+
def stop_file_watcher(self):
1068+
1069+
if self.file_watcher_job:
1070+
1071+
self.root.after_cancel(self.file_watcher_job)
1072+
1073+
self.file_watcher_job = None
1074+
1075+
self.log("Live update disabled.")
1076+
1077+
1078+
1079+
def check_for_updates(self):
1080+
1081+
if not self.active_filepath or not self.live_update_var.get(
1082+
1083+
) or not os.path.exists(self.active_filepath):
1084+
1085+
self.file_watcher_job = None # Stop watching if file is gone or disabled
1086+
1087+
return
1088+
1089+
1090+
1091+
try:
1092+
1093+
file_info = self.file_data_cache[self.active_filepath]
1094+
1095+
mod_time = os.path.getmtime(self.active_filepath)
1096+
1097+
current_size = os.path.getsize(self.active_filepath)
1098+
1099+
1100+
1101+
if mod_time != file_info.get('mod_time'):
1102+
1103+
if current_size > file_info.get('size', 0):
1104+
1105+
# File has grown, append new data
1106+
1107+
self.append_file_data()
1108+
1109+
else:
1110+
1111+
# File was overwritten or shrunk, do a full reload
1112+
1113+
self.log(
1114+
1115+
"File has been overwritten. Performing full reload...")
1116+
1117+
self.load_file_data(self.active_filepath)
1118+
1119+
else:
1120+
1121+
# If no changes, schedule the next check
1122+
1123+
self.file_watcher_job = self.root.after(
1124+
1125+
1000, self.check_for_updates)
1126+
1127+
1128+
1129+
except OSError:
1130+
1131+
# File might have been deleted or is temporarily inaccessible
1132+
10341133
self.log(
1035-
"File has been overwritten. Performing full reload...")
1036-
self.load_file_data(self.active_filepath)
1037-
else:
1038-
# If no changes, schedule the next check
1039-
self.file_watcher_job = self.root.after(
1040-
1000, self.check_for_updates)
1041-
1042-
except OSError:
1043-
# File might have been deleted or is temporarily inaccessible
1044-
self.log(
1045-
"File watcher stopped: file is inaccessible or has been deleted.")
1046-
self.stop_file_watcher()
1134+
1135+
"File watcher stopped: file is inaccessible or has been deleted.")
1136+
1137+
self.stop_file_watcher()
1138+
1139+
1140+
1141+
1142+
1143+
if __name__ == '__main__':
1144+
1145+
# This is ESSENTIAL for multiprocessing to work in a bundled executable
1146+
1147+
# and to prevent pickling errors with 'spawn' start method on Windows.
1148+
1149+
multiprocessing.freeze_support()
1150+
1151+
1152+
1153+
root = tk.Tk()
1154+
1155+
app = PlotterApp(root)
1156+
1157+
root.mainloop()
10471158

10481159

10491160
if __name__ == '__main__':

deployment/Picachu.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,12 @@ class PICALauncherApp:
133133
SCRIPT_PATHS = {
134134
"Sweep Mode I-V": os.path.join(SUB_PROGRAMS_DIR, "IV_K6221_DC_Sweep_GUI_V10.exe"),
135135
"Delta Mode R-T": os.path.join(SUB_PROGRAMS_DIR, "Delta_RT_K6221_K2182_L350_T_Control_GUI_v5.exe"),
136-
"Delta Mode R-T (T_Sensing)": os.path.join(SUB_PROGRAMS_DIR, "Delta_RT_K6221_K2182_L350_Sensing_GUI_v5.exe"),
136+
"Delta Mode R-T (T_Sensing)": os.path.join(
137+
SUB_PROGRAMS_DIR, "Delta_RT_K6221_K2182_L350_Sensing_GUI_v5.exe"),
137138
"K2400 I-V": os.path.join(SUB_PROGRAMS_DIR, "IV_K2400_GUI_v5.exe"),
138139
"K2400 R-T": os.path.join(SUB_PROGRAMS_DIR, "RT_K2400_L350_T_Control_GUI_v3.exe"),
139-
"K2400 R-T (T_Sensing)": os.path.join(SUB_PROGRAMS_DIR, "RT_K2400_L350_T_Sensing_GUI_v4.exe"),
140+
"K2400 R-T (T_Sensing)": os.path.join(
141+
SUB_PROGRAMS_DIR, "RT_K2400_L350_T_Sensing_GUI_v4.exe"),
140142
"K2400_2182 I-V": os.path.join(SUB_PROGRAMS_DIR, "IV_K2400_K2182_GUI_v3.exe"),
141143
"K2400_2182 R-T": os.path.join(SUB_PROGRAMS_DIR, "RT_K2400_K2182_T_Control_GUI_v3.exe"),
142144
"K2400_2182 R-T (T_Sensing)": os.path.join(SUB_PROGRAMS_DIR, "RT_K2400_2182_L350_T_Sensing_GUI_v2.exe"),
@@ -1151,6 +1153,6 @@ def main():
11511153
# and ensures a consistent, stable process creation method across platforms.
11521154
# 'spawn' is the most robust method for GUI apps, though it is the default
11531155
# on Windows and macOS.
1154-
multiprocessing.set_start_method('spawn', force=True)
1155-
multiprocessing.freeze_support()
1156-
main()
1156+
multiprocessing.set_start_method('spawn', force=True)
1157+
multiprocessing.freeze_support()
1158+
main()

0 commit comments

Comments
 (0)