305 lines
10 KiB
Python
305 lines
10 KiB
Python
import os
|
||
import json
|
||
#
|
||
#RED = "\033[91m"
|
||
#RESET = "\033[0m"
|
||
|
||
|
||
# see also Python Projekte/Strings in Datei speichern
|
||
|
||
BEAMLINE_PARAMETERS_FILE = "/home/gac-x11ma/pshell/home/script/beamline_alignment/bml_align_params.json"
|
||
|
||
def save_parameters():
|
||
msg = "Save as ..."
|
||
# User inputs the file path
|
||
path = get_string(msg, default = "/home/gac-x11ma/pshell/home/script/beamline_alignment/0012.json", alternatives = None, password = False)
|
||
|
||
# 1 Check if the user cancelled
|
||
if path is None:
|
||
print("Aborted by user.")
|
||
return # ✅ exit the function immediately
|
||
|
||
# 2 Get the parent folder of the file
|
||
folder = os.path.dirname(path)
|
||
# print(folder)
|
||
|
||
# 3 ️⃣Check if the folder existst
|
||
if not os.path.isdir(folder):
|
||
print ("Aborted. Folder: " + folder + " does not exist.")
|
||
return # ✅ exit the function cleanly
|
||
|
||
# 4 Mapping from component + parameter to individual read string (Dictionary) Each component contains its parameters, with the corresponding read string and optional tolerance
|
||
|
||
with open(BEAMLINE_PARAMETERS_FILE, "r") as f:
|
||
machine_parameters = json.load(f)
|
||
|
||
parameters = {}
|
||
nan_occurred = False
|
||
|
||
# 5️⃣ Read each parameter from the machine
|
||
for comp, param_dict in machine_parameters.items():
|
||
print("\nComponent: " + comp)
|
||
parameters[comp] = {}
|
||
for p, info in param_dict.items():
|
||
cmd = info["read_cmd"]
|
||
#print(cmd)
|
||
tol = info["tolerance"]
|
||
#print(tol)
|
||
try:
|
||
value = caget(cmd)
|
||
if isinstance(value, str):
|
||
display_value = value
|
||
else:
|
||
#value = string(value) c ensure float
|
||
display_value = str(value)
|
||
print(comp + "_" + p + " = " + display_value)
|
||
# print(value)
|
||
except:
|
||
# print("Problem")
|
||
# value = float('nan')
|
||
nan_occurred = True
|
||
print(comp + p + " = NaN")
|
||
parameters[comp][p] = {"value": value, "tolerance": tol}
|
||
|
||
# # 6 Save parameters to JSON file
|
||
try:
|
||
with open(path, "w") as f:
|
||
json.dump(parameters, f, indent=4, allow_nan=True)
|
||
print("Parameters successfully saved in: " + path)
|
||
except:
|
||
print("Error while saving file.")
|
||
|
||
# Warn if NaN occurred
|
||
if nan_occurred:
|
||
print("There were NaN-Values")
|
||
|
||
def select_components(selected_components=None):
|
||
|
||
#Allows the user (or another function) to select one
|
||
#or more components either interactively or
|
||
#by providing a list. It validates the selection against
|
||
#the available components in the JSON file.
|
||
|
||
|
||
msg = "Select components: "
|
||
|
||
# Load machine parameters
|
||
try:
|
||
with open(BEAMLINE_PARAMETERS_FILE, "r") as f:
|
||
machine_parameters = json.load(f)
|
||
except:
|
||
print("Error loading machine_parameters.json")
|
||
return None
|
||
|
||
# Extract component names
|
||
all_components = list(machine_parameters.keys())
|
||
# print("Available components:")
|
||
# for comp in all_components:
|
||
# print("- " + comp)
|
||
|
||
# --- determine components to display ---
|
||
if selected_components is None:
|
||
|
||
# user didn't specify -> use all from JSON
|
||
presented_to_select = all_components[:]
|
||
presented_to_select.append("all")
|
||
|
||
selected = get_string(msg, default = None, alternatives = presented_to_select, password = False)
|
||
#print(selected)
|
||
if selected is None:
|
||
print("Selection aborted by user.")
|
||
return None
|
||
elif selected == "all":
|
||
# Display components
|
||
print("Selected components:")
|
||
for comp in all_components:
|
||
print("- " + comp)
|
||
return all_components
|
||
|
||
else:
|
||
selected_components = [selected] if not isinstance(selected, list) else selected
|
||
print("Selected components:")
|
||
for comp in selected_components:
|
||
print("- " + comp)
|
||
return selected_components
|
||
|
||
|
||
elif selected_components == "all":
|
||
|
||
# Display components
|
||
print("Selected components:")
|
||
for comp in all_components:
|
||
print("- " + comp)
|
||
return all_components
|
||
|
||
else:
|
||
# ensure it is a list
|
||
if not isinstance(selected_components, list):
|
||
print("Error: selected_components must be a list of the form \"[\"Diag\", \"CMU\", ...]\" or \"all\".")
|
||
return
|
||
# validate each component
|
||
invalid = [c for c in selected_components if c not in all_components]
|
||
if invalid:
|
||
print("Error: Invalid component(s):")
|
||
for comp in invalid:
|
||
print("- " + comp)
|
||
|
||
print("Valid components are:")
|
||
for comp in all_components:
|
||
print("- " + comp)
|
||
|
||
return None
|
||
else:
|
||
print("Selected components:")
|
||
for comp in selected_components:
|
||
print("- " + comp)
|
||
return selected_components
|
||
|
||
|
||
def display_parameters(selected_components=None):
|
||
|
||
|
||
# Displays parameters for selected components.
|
||
# - Uses select_components() to choose components.
|
||
# - Prints each parameter with its value.
|
||
# - If a parameter value is missing or cannot be read, prints NaN.
|
||
|
||
|
||
# 1️⃣ Get the selected components (interactive or via argument)
|
||
selection = select_components(selected_components)
|
||
if selection is None:
|
||
return # user cancelled or invalid input
|
||
|
||
# 2️⃣ Load the machine parameters JSON
|
||
try:
|
||
with open(BEAMLINE_PARAMETERS_FILE, "r") as f:
|
||
machine_parameters = json.load(f)
|
||
except:
|
||
print("Error loading machine_parameters.json")
|
||
return
|
||
|
||
# 3️⃣ Loop through components and display their parameters
|
||
for comp in selection:
|
||
print("\nComponent: " + comp)
|
||
params = machine_parameters.get(comp, {})
|
||
if not params:
|
||
print(" No parameters found.")
|
||
continue
|
||
|
||
for key, param_info in params.items():
|
||
|
||
# param_info enthält z.B. den read_cmd
|
||
read_cmd = param_info.get("read_cmd") # JSON muss für jeden Parameter den entsprechenden Befehl enthalten
|
||
|
||
try:
|
||
display_value = caget(read_cmd)
|
||
print(read_cmd + " = " + str(display_value))
|
||
except:
|
||
display_value = "NaN"
|
||
# print(" " + key + ": " + display_value)
|
||
|
||
def restore_parameters(selected_components=None):
|
||
# """
|
||
# Restore parameter values from a previously saved JSON file.
|
||
# The user selects which components to restore, and only parameters
|
||
# marked as "restorable": true in machine_parameters.json will be written back.
|
||
# """
|
||
|
||
msg = "Open *.json configuration file ..."
|
||
|
||
# User inputs the file path
|
||
|
||
# --- Step 1: Select file ---
|
||
restore_file = get_string(msg, default = "/home/gac-x11ma/pshell/home/script/beamline_alignment/0012.json", alternatives = None, password = False)
|
||
if restore_file is None:
|
||
print("Restore aborted: no file specified.")
|
||
return
|
||
|
||
try:
|
||
with open(restore_file, "r") as f:
|
||
saved_data = json.load(f)
|
||
except:
|
||
print("Error loading restore file:", restore_file)
|
||
return
|
||
|
||
# --- Step 2: Load machine parameters ---
|
||
try:
|
||
with open(BEAMLINE_PARAMETERS_FILE, "r") as f:
|
||
machine_parameters = json.load(f)
|
||
except:
|
||
print("Error loading machine_parameters.json")
|
||
return
|
||
|
||
# --- Step 3: Select components ---
|
||
selection = select_components(selected_components)
|
||
|
||
if selection is None:
|
||
return # user cancelled or invalid input
|
||
|
||
# --- Step 4:️⃣ Load the machine parameters JSON
|
||
try:
|
||
with open(BEAMLINE_PARAMETERS_FILE, "r") as f:
|
||
machine_parameters = json.load(f)
|
||
except:
|
||
print("Error loading machine_parameters.json")
|
||
return
|
||
|
||
# --- Step 5: Restore loop ---
|
||
|
||
for comp in selection:
|
||
print("\nComponent: " + comp)
|
||
params = machine_parameters.get(comp, {})
|
||
if not params:
|
||
print(" No parameters found.")
|
||
continue
|
||
|
||
saved_params = saved_data.get(comp, {})
|
||
if not saved_params:
|
||
print(" No saved values for this component.")
|
||
continue
|
||
|
||
for key, param_info in params.items():
|
||
|
||
if not param_info.get("restorable", False):
|
||
continue
|
||
|
||
# --- get saved value ---
|
||
saved_entry = saved_params.get(key, None)
|
||
if saved_entry is not None and 'value' in saved_entry:
|
||
saved_value = saved_entry['value']
|
||
else:
|
||
saved_value = "NaN"
|
||
|
||
# param_info enthält z.B. den read_cmd
|
||
read_cmd = param_info.get("read_cmd") # JSON muss für jeden Parameter den entsprechenden Befehl enthalten
|
||
write_cmd = param_info.get("write_cmd") # JSON muss für jeden Parameter den entsprechenden Befehl enthalten
|
||
tolerance = param_info.get("tolerance")
|
||
|
||
try:
|
||
display_value = caget(read_cmd)
|
||
# print(read_cmd + " = " + str(display_value) + ", saved value = " + str(saved_value))
|
||
# difference = float(display_value) - float(saved_value)
|
||
# --- compute difference if possible ---
|
||
if saved_value != "NaN" and display_value != "NaN":
|
||
try:
|
||
difference = abs(float(display_value) - float(saved_value))
|
||
except:
|
||
difference = "NaN"
|
||
else:
|
||
difference = "NaN"
|
||
print(read_cmd + " = " + str(display_value) + ", diff = " + str(round(difference, 5)) + ", tolerance = " + str(round(tolerance, 5)))
|
||
if float(difference) > float(tolerance):
|
||
print("Set " + read_cmd + " to " + str(round(saved_value, 5)))
|
||
write_cmd_new = "\"" + write_cmd + "\""
|
||
#print(write_cmd_new)
|
||
caput(write_cmd, float(saved_value))
|
||
else:
|
||
print("OK.")
|
||
except:
|
||
display_value = "NaN"
|
||
# print(" " + key + ": " + display_value)
|
||
|
||
|
||
|
||
# print("Component:", comp)
|
||
# run('beamline_init/with_x-rays/functions/SlitCalib.py') |