diff --git a/devices/undulator.py b/devices/undulator.py index 227cdc4..7d0c12b 100644 --- a/devices/undulator.py +++ b/devices/undulator.py @@ -1,6 +1,6 @@ from time import sleep import numpy as np -from scipy.interpolate import Akima1DInterpolator as Akima +#from scipy.interpolate import Akima1DInterpolator as Akima from epics import PV from slic.core.adjustable import Adjustable @@ -18,31 +18,31 @@ und_names = [f"SATUN{n:02}-UIND030" for n in n_unds] und_name_cal = "SATUN12-UIND030" -energies = [ - 0.5457977557372193, - 0.5429495415906611, - 0.5401552739843691, - 0.537355500731781, - 0.534605067464375, - 0.5318574959825555, - 0.5291128804749312, - 0.5264167029579244, - 0.5237231992520139, - 0.5210645197823921, -] +#energies = [ +# 0.5457977557372193, +# 0.5429495415906611, +# 0.5401552739843691, +# 0.537355500731781, +# 0.534605067464375, +# 0.5318574959825555, +# 0.5291128804749312, +# 0.5264167029579244, +# 0.5237231992520139, +# 0.5210645197823921, +#] -k_values = [ - 2.673, - 2.681888888888889, - 2.690777777777778, - 2.699666666666667, - 2.708555555555556, - 2.7174444444444443, - 2.7263333333333333, - 2.735222222222222, - 2.744111111111111, - 2.753, -] +#k_values = [ +# 2.673, +# 2.681888888888889, +# 2.690777777777778, +# 2.699666666666667, +# 2.708555555555556, +# 2.7174444444444443, +# 2.7263333333333333, +# 2.735222222222222, +# 2.744111111111111, +# 2.753, +#] #energies = [ @@ -116,16 +116,14 @@ k_values = [ class Undulators(Adjustable): - def __init__(self, energies=energies, k_values=k_values): - super().__init__(name="Athos Undulators") + def __init__(self): + super().__init__(name="Athos Undulators", units="eV") self.adjs = {name: Undulator(name) for name in und_names} - self.eV_to_K = make_calib(energies, k_values) - self.K_to_eV = make_calib(k_values, energies) + self.convert = ConverterEK() def set_target_value(self, value, hold=False): - value /= 1000 # eV -> keV - k = self.eV_to_K(value) + k = self.convert.K(value) if np.isnan(k): print("K is nan for", value) return @@ -146,7 +144,7 @@ class Undulators(Adjustable): def get_current_value(self): a = self.adjs[und_name_cal] k = a.get_current_value() - energy = self.K_to_eV(k) + energy = self.convert.E(k) all_ks = [a.get_current_value() for a in self.adjs.values()] checks = np.isclose(all_ks, k, rtol=0, atol=0.001) @@ -156,7 +154,7 @@ class Undulators(Adjustable): if not chk: print(name, k) - return float(energy) * 1000 # keV -> eV + return energy def is_moving(self): @@ -174,41 +172,73 @@ class Undulator(PVAdjustable): -def make_calib(x, y): - x, y = list(zip(*sorted(zip(x, y)))) - return Akima(x, y) +#def make_calib(x, y): +# x, y = list(zip(*sorted(zip(x, y)))) +# return Akima(x, y) -def get_map(k_min=min(k_values), k_max=max(k_values)): - und = Undulator(und_name_cal) - start_k_value = und.get_current_value() +#def get_map(k_min=min(k_values), k_max=max(k_values)): +# und = Undulator(und_name_cal) +# start_k_value = und.get_current_value() - k_values = np.linspace(k_min, k_max, 10) - energies = [] - print() - print("mapping = {") - for k in k_values: - und.set_target_value(k).wait() - energy = und.energy.get_current_value() - print(f" {energy}: {k},") - energies.append(energy) - print("}") - energies = np.array(energies) +# k_values = np.linspace(k_min, k_max, 10) +# energies = [] +# print() +# print("mapping = {") +# for k in k_values: +# und.set_target_value(k).wait() +# energy = und.energy.get_current_value() +# print(f" {energy}: {k},") +# energies.append(energy) +# print("}") +# energies = np.array(energies) - print() - print("energies = [") - for energy in energies: - print(f" {energy},") - print("]") +# print() +# print("energies = [") +# for energy in energies: +# print(f" {energy},") +# print("]") - print() - print("k_values = [") - for k in k_values: - print(f" {k},") - print("]") +# print() +# print("k_values = [") +# for k in k_values: +# print(f" {k},") +# print("]") - und.set_target_value(start_k_value).wait() - return energies, k_values +# und.set_target_value(start_k_value).wait() +# return energies, k_values + + + +class ConverterEK: + + h = 4.135667696e-15 # eV * s + c = 299792458 # m / s + lambda_u = 38e-3 # m + const = 2 * h * c / lambda_u # eV + + electron_rest_energy = 0.51099895 # MeV + + def __init__(self, pvname_electron_energy="SATCL01-MBND100:P-READ"): + self.pv_electron_energy = PV(pvname_electron_energy) + + def K(self, energy): + f = self.get_factor() + v = f / energy - 1 + return np.sqrt(2 * v) + + def E(self, k_value): + f = self.get_factor() + v = 1 + k_value**2 / 2 + return f / v + + def get_factor(self): + return self.const * self.get_gamma_squared() + + def get_gamma_squared(self): + electron_energy = self.pv_electron_energy.get() + gamma = electron_energy / self.electron_rest_energy + return gamma**2