fixes with system upgrades and file permissions

This commit is contained in:
2024-04-19 13:54:29 +02:00
parent 1ef4b53e9f
commit 24a89f7aa2
11 changed files with 669 additions and 311 deletions
+7 -7
View File
@@ -226,24 +226,24 @@ class Daq(Assembly):
def get_next_run_number(self, pgroup=None):
if pgroup is None:
pgroup = self.pgroup
res = requests.get(
f"{self.broker_address}/get_next_run_number",
res = requests.post(
f"{self.broker_address}/advance_run_number",
json={"pgroup": pgroup},
timeout=self.timeout,
)
assert res.ok, f"Getting last run number failed {res.raise_for_status()}"
return int(res.json()["message"])
return int(res.json()["run_number"])
def get_last_run_number(self, pgroup=None):
if pgroup is None:
pgroup = self.pgroup
res = requests.get(
f"{self.broker_address}/get_last_run_number",
f"{self.broker_address}/get_current_run_number",
json={"pgroup": pgroup},
timeout=self.timeout,
)
assert res.ok, f"Getting last run number failed {res.raise_for_status()}"
return int(res.json()["message"])
return int(res.json()["run_number"])
def get_detector_frequency(self):
return self._event_master.event_codes[
@@ -251,12 +251,12 @@ class Daq(Assembly):
].frequency.get_current_value()
def get_JFs_available(self):
return requests.get(f"{self.broker_address}/get_allowed_detectors_list").json()[
return requests.get(f"{self.broker_address}/get_allowed_detectors").json()[
"detectors"
]
def get_JFs_running(self):
return requests.get(f"{self.broker_address}/get_running_detectors_list").json()[
return requests.get(f"{self.broker_address}/get_running_detectors").json()[
"detectors"
]
+29 -20
View File
@@ -9,23 +9,29 @@ from time import sleep
from pathlib import Path
from .utilities import Acquisition
import time
from ..elements.adjustable import AdjustableFS
class EpicsDaq:
def __init__(
self,
default_file_path="%s",
elog=None,
name=None,
channel_list=None,
):
self.name = name
self._default_file_path = default_file_path
self.default_file_path = AdjustableFS(f'/sf/bernina/config/eco/reference_values/{name}_default_file_path.json', default_value="~/data/", name="default_file_path")
self._elog = elog
self.channels = {}
self.pulse_id = PV("SLAAR11-LTIM01-EVR0:RX-PULSEID")
self.channel_list = channel_list
self.update_channels()
@property
def _default_file_path(self):
return self.default_file_path()
@_default_file_path.setter
def _default_file_path(self, val):
self.default_file_path(val)
def update_channels(self):
channels = self.channel_list.get_current_value()
for channel in channels:
@@ -33,7 +39,10 @@ class EpicsDaq:
self.channels[channel] = PV(channel, auto_monitor=True)
def h5(self, fina=None, channel_list=None, N_pulses=None, queue_size=100):
channel_list = self.channel_list
if channel_list is None:
channel_list = self.channel_list
if not channel_list.get_current_value() == list(self.channels.keys()):
self.update_channels()
if os.path.isfile(fina):
print("!!! File %s already exists, would you like to delete it?" % fina)
@@ -43,10 +52,10 @@ class EpicsDaq:
else:
return
data = []
counters = []
data = {}
counters = {}
channels = self.channels
for channel in channels:
for k, channel in channels.items():
channelval = channel.value
if type(channelval) == np.ndarray:
shape = (N_pulses,) + channelval.shape
@@ -54,26 +63,26 @@ class EpicsDaq:
else:
shape = (N_pulses,)
dtype = type(channelval)
data.append(np.ndarray(shape, dtype=dtype))
counters.append(0)
data[k]=np.ndarray(shape, dtype=dtype)
counters[k]=0
def cb_getdata(ch=None, m=0, *args, **kwargs):
data[m][counters[m]] = kwargs["value"]
counters[m] = counters[m] + 1
if counters[m] == N_pulses:
def cb_getdata(ch=None, k="", *args, **kwargs):
data[k][counters[k]] = kwargs["value"]
counters[k] = counters[k] + 1
if counters[k] == N_pulses:
ch.clear_callbacks()
for (m, channel) in enumerate(channels):
channel.add_callback(callback=cb_getdata, ch=channel, m=m)
for k, channel in channels.items():
channel.add_callback(callback=cb_getdata, ch=channel, k=k)
while True:
sleep(0.005)
if np.mean(counters) == N_pulses:
if np.mean(list(counters.values())) == N_pulses:
break
f = h5py.File(name=fina, mode="w")
for (n, channel) in enumerate(channel_list):
dat = f.create_group(name=channel)
dat.create_dataset(name="data", data=data[n])
for k in channels.keys():
dat = f.create_group(name=k)
dat.create_dataset(name="data", data=data[k])
dat.create_dataset(
name="pulse_id", data=np.arange(N_pulses) + round(time.time() * 100)
)
+93 -69
View File
@@ -341,7 +341,7 @@ namespace.append_obj(
# },
name="mon_mono",
module_name="eco.xdiagnostics.intensity_monitors",
# pipeline_computation="SAROP21-PBPS103_proc",
pipeline_computation="SAROP21-PBPS103_proc",
lazy=True,
)
@@ -648,6 +648,7 @@ namespace.append_obj(
"right": "SARES21-PBPS141:Lnk9Ch0-PP_VAL_PD3",
},
module_name="eco.xdiagnostics.intensity_monitors",
pipeline_computation="SARES21-PBPS141_proc",
name="mon_kb",
lazy=True,
)
@@ -1160,14 +1161,13 @@ namespace.append_obj(
# )
### draft new epics daq ###
# namespace.append_obj(
# "EpicsDaq",
# default_file_path=f"/sf/bernina/data/{config_berninamesp['pgroup']}/res/epics_daq/",
# channels_list=channels_CA_epicsdaq,
# name="daq_epics_local",
# module_name="eco.acquisition.epics_data",
# lazy=True,
# )
namespace.append_obj(
"EpicsDaq",
channel_list=channels_CA_epicsdaq,
name="daq_epics_local",
module_name="eco.acquisition.epics_data",
lazy=True,
)
### old epics daq ###
# namespace.append_obj(
# "ChannelList",
@@ -1184,17 +1184,18 @@ namespace.append_obj(
# module_name="eco.acquisition.epics_data",
# )
# namespace.append_obj(
# "Scans",
# name="scans_epics",
# module_name="eco.acquisition.scan",
# data_base_dir="scan_data",
# scan_info_dir=f"/sf/bernina/data/{config_berninamesp['pgroup']}/res/scan_info",
# default_counters=[epics_daq],
# checker=checker_epics,
# scan_directories=True,
# run_table=run_table,
# )
namespace.append_obj(
"Scans",
name="scans_epics",
module_name="eco.acquisition.scan",
data_base_dir=f"{config_bernina.pgroup()}/scan_data",
scan_info_dir=f"{daq_epics_local.default_file_path()}/{config_bernina.pgroup()}/scan_info",
default_counters=[daq_epics_local],
checker=None,
scan_directories=True,
run_table=None,
lazy=True,
)
#
#
##### standard DAQ #######
@@ -1861,17 +1862,17 @@ namespace.append_obj(
"CameraBasler",
"SARES20-CAMS142-M2",
lazy=True,
name="samplecam_sideview_45",
module_name="eco.devices_general.cameras_swissfel",
)
namespace.append_obj(
"CameraBasler",
"SARES20-CAMS142-C1",
lazy=True,
name="samplecam_sideview",
module_name="eco.devices_general.cameras_swissfel",
)
#namespace.append_obj(
# "CameraBasler",
# "SARES20-CAMS142-C2",
# lazy=True,
# name="samplecam_inline",
# module_name="eco.devices_general.cameras_swissfel",
#)
namespace.append_obj(
"OxygenSensor",
@@ -2112,7 +2113,21 @@ namespace.append_obj(
"name": "helium_control_valve",
},
# configuration=["ottifant"],
configuration=[],
configuration=["cube"],
)
namespace.append_obj(
"Organic_crystal_breadboard",
lazy=True,
name="ocb",
module_name="eco.endstations.bernina_sample_environments",
)
namespace.append_obj(
"Electro_optic_sampling",
lazy=True,
name="eos",
module_name="eco.endstations.bernina_sample_environments",
)
# class Sample_stages(Assembly):
@@ -2499,14 +2514,14 @@ namespace.append_obj(
module_name="eco.xoptics.dcm_new",
)
namespace.append_obj(
"AramisDcmFeedback",
mono=mono,
xbpm=mon_opt,
name="mono_feedback",
lazy=True,
module_name="eco.xoptics.xopt_feedback",
)
# namespace.append_obj(
# "AramisDcmFeedback",
# mono=mono,
# xbpm=mon_opt,
# name="mono_feedback",
# lazy=True,
# module_name="eco.xoptics.xopt_feedback",
# )
# namespace.append_obj(
@@ -2600,7 +2615,7 @@ from eco.loptics.bernina_laser import Stage_LXT_Delay
namespace.append_obj(
"StageLxtDelay",
pumpdelay.pdelay,
las.delay_pump,
las,
lazy=True,
name="lxt",
@@ -2627,7 +2642,8 @@ try:
pgroup_eco_path = TimeoutPath(
f"/sf/bernina/data/{config_bernina.pgroup()}/res/eco"
)
pgroup_eco_path.mkdir(mode=775, exist_ok=True)
pgroup_eco_path.mkdir(mode=0o775, exist_ok=True)
pgroup_eco_path.chmod(mode=0o775)
sys.path.append(pgroup_eco_path.as_posix())
else:
print(
@@ -2744,10 +2760,10 @@ class IlluminatorsLasers(Assembly):
def __init__(self, name="sample_illumination"):
super().__init__(name=name)
self._append(
MpodChannel,
pvbase="SARES21-CPCL-PS7071",
channel_number=5,
name="illumination_inline",
MpodChannel,
pvbase="SARES21-CPCL-PS7071",
channel_number=5,
name="illumination_inline",
)
self._append(
MpodChannel,
@@ -2755,18 +2771,18 @@ class IlluminatorsLasers(Assembly):
channel_number=2,
name="illumination_side",
)
self._append(
MpodChannel,
pvbase="SARES21-CPCL-PS7071",
channel_number=6,
name="illumination_top",
)
self._append(
MpodChannel,
pvbase="SARES21-CPCL-PS7071",
channel_number=4,
name="flattening_laser",
)
#self._append(
# MpodChannel,
# pvbase="SARES21-CPCL-PS7071",
# channel_number=6,
# name="illumination_top",
#)
#self._append(
# MpodChannel,
# pvbase="SARES21-CPCL-PS7071",
# channel_number=4,
# name="flattening_laser",
#)
namespace.append_obj(IlluminatorsLasers, name="sample_illumination", lazy=True)
@@ -3052,17 +3068,25 @@ def name2pgroups(name, beamline="bernina"):
return eq + ni
namespace.append_obj(
"Jungfrau",
"JF03T01V02",
name="det_i0",
pgroup_adj=config_bernina.pgroup,
module_name="eco.detector",
)
# namespace.append_obj(
# "Jungfrau",
# "JF01T03V01",
# name="det_diff",
# pgroup_adj=config_bernina.pgroup,
# module_name="eco.detector",
# )
def timetool_data_monitor(warning_threshold=1000, loopsleep=5):
dir(bs_worker)
tt_kb.spectrum_signal.stream.accumulate(do_accumulate=True)
print('Monitoring timetool data ...')
while True:
eid_diff= int(event_system.pulse_id.get_current_value() - tt_kb.spectrum_signal.stream.eventIds[-1][-1])
if eid_diff> warning_threshold:
message = f"Last timetool data {eid_diff} pulses ago!"
print(message)
try:
e = pyttsx3.init()
e.say(message)
e.runAndWait()
e.stop()
except:
pass
time.sleep(loopsleep)
+61 -8
View File
@@ -3,6 +3,7 @@ from tkinter import W
from eco.base.adjustable import Adjustable
from eco.devices_general.therm import ChillerThermotek
from eco.elements.adj_obj import AdjustableObject
from eco.elements.detector import DetectorGet
from ..elements.adjustable import AdjustableFS, AdjustableVirtual, AdjustableGetSet
from ..epics.adjustable import AdjustablePv
@@ -32,6 +33,7 @@ class Jungfrau(Assembly):
trigger_on=254,
trigger_off=255,
broker_address="http://sf-daq:10002",
broker_address_aux="http://sf-daq:10003",
pgroup_adj=None,
config_adj=None,
chiller_thermotek="SARES20-CHIL",
@@ -42,6 +44,7 @@ class Jungfrau(Assembly):
self.pgroup = pgroup_adj
self.jf_id = jf_id
self.broker_address = broker_address
self.broker_address_aux = broker_address_aux
self._append(
DetectorGet, lambda: f"http://{self.get_vis_url()}", name="visulization_url"
)
@@ -107,6 +110,21 @@ class Jungfrau(Assembly):
name="gain_file_in_run",
is_display=True,
)
self._append(
AdjustableGetSet,
self.get_dap_settings,
self.set_dap_settings,
name="_dap_settings",
is_display=False,
is_setting=False,
)
self._append(
AdjustableObject,
self._dap_settings,
is_setting_children=True,
name="settings_dap",
)
if config_adj:
self._append(
JungfrauDaqConfig,
@@ -118,7 +136,12 @@ class Jungfrau(Assembly):
is_display="recursive",
)
if chiller_thermotek:
self._append(ChillerThermotek,pvbase=chiller_thermotek,name="chiller",is_display="recursive")
self._append(
ChillerThermotek,
pvbase=chiller_thermotek,
name="chiller",
is_display="recursive",
)
def _set_trigger_enable(self, value):
if value:
@@ -139,8 +162,14 @@ class Jungfrau(Assembly):
dest = Path(
f"/sf/bernina/data/{self.pgroup()}/res/tmp/gainmaps_{self.jf_id}.h5"
)
if not dest.exists():
shutil.copyfile(f, dest)
try:
if not dest.exists():
dest.parent.mkdir(parents=True, exist_ok=True, mode=0o775)
shutil.copyfile(f, dest)
except PermissionError:
return "No permissions to res directory!"
if intempdir:
return dest.as_posix()
else:
@@ -157,14 +186,38 @@ class Jungfrau(Assembly):
dest = Path(
f"/sf/bernina/data/{self.pgroup()}/res/tmp/pedestal_{self.jf_id}_{f.stem}.h5"
)
if not dest.exists():
shutil.copyfile(f, dest)
try:
if not dest.exists():
dest.parent.mkdir(parents=True, exist_ok=True, mode=0o775)
dest.parent.chmod(0o775)
shutil.copyfile(f, dest)
except PermissionError:
return "No poermissions to res directory!"
if intempdir:
return dest.as_posix()
else:
return f"aux/{dest.name}"
def get_dap_settings(self):
m = requests.get(
f"{self.broker_address_aux}/get_dap_settings",
json={"detector_name": self.jf_id},
).json()
if m["status"] == "ok":
return m["parameters"]
def set_dap_settings(self, dap_setting_dict):
# print("Setting not implmented yet!")
# return
m = requests.post(
f"{self.broker_address_aux}/set_dap_settings",
json={"detector_name": self.jf_id, "parameters": dap_setting_dict},
).json()
if m["status"] == "ok":
return m
def get_detector_frequency(self):
return self._event_master.event_codes[
self._detectors_event_code
@@ -173,21 +226,21 @@ class Jungfrau(Assembly):
def get_availability(self):
is_available = (
self.jf_id
in requests.get(f"{self.broker_address}/get_allowed_detectors_list").json()[
in requests.get(f"{self.broker_address}/get_allowed_detectors").json()[
"detectors"
]
)
return is_available
def get_vis_url(self):
tmp = requests.get(f"{self.broker_address}/get_allowed_detectors_list").json()
tmp = requests.get(f"{self.broker_address}/get_allowed_detectors").json()
ix = tmp["detectors"].index(self.jf_id)
return tmp["visualisation_address"][ix]
def get_isrunning(self):
is_running = (
self.jf_id
in requests.get(f"{self.broker_address}/get_running_detectors_list").json()[
in requests.get(f"{self.broker_address}/get_running_detectors").json()[
"detectors"
]
)
+151 -2
View File
@@ -554,7 +554,7 @@ class PshellMotor(Assembly):
# # s += "\tuser limits (low,high) : {:1.6g},{1.6g}".format(self.get_limits())
else:
s += (
f"\t@ {colorama.Style.BRIGHT}{'NOT CONECTED'}{colorama.Style.RESET_ALL}"
f"\t@ {colorama.Style.BRIGHT}{'NOT CONNECTED'}{colorama.Style.RESET_ALL}"
)
return s
@@ -563,7 +563,156 @@ class PshellMotor(Assembly):
print(str(self))
return object.__repr__(self)
class AdjustablePiHex(AdjustablePv):
def __init__(self, pvname=None, pvreadbackname=None, accuracy=None, unit=None, name=None):
super().__init__(pvname, pvreadbackname=pvreadbackname, accuracy=accuracy, unit=unit, name=name)
self.limit_high = AdjustableFS(f'/sf/bernina/config/eco/reference_values/hex_pi_{name}_limit_high.json', default_value=0)
self.limit_low = AdjustableFS(f'/sf/bernina/config/eco/reference_values/hex_pi_{name}_limit_low.json', default_value=0)
def move(self, value, check=False):
if check:
if self.limit_low:
if value < self.limit_low():
raise Exception(
f"Target value of {self.name} is smaller than limit value!"
)
if self.limit_high:
if self.limit_high() < value:
raise Exception(
f"Target value of {self.name} is higher than limit value!"
)
self._pv.put(value)
time.sleep(0.1)
while self.get_change_done() == 0:
time.sleep(0.1)
def change(self, value):
return self.move(value)
def get_limits(self):
return (self.limit_low(), self.limit_high())
def set_limits(self, limit_low, limit_high):
self.limit_low(limit_low)
self.limit_high(limit_high)
@spec_convenience
@update_changes
@get_from_archive
@value_property
class ThorlabsPiezoRecord(Assembly):
def __init__(self, pvname=None, accuracy=0.1, unit=None, name=None):
super().__init__(name=name)
self.pvname=pvname
self._cb = None
self._append(
AdjustablePv,
self.pvname + ":DRIVE",
pvreadbackname=self.pvname+":MOTRBV",
accuracy = accuracy,
unit=unit,
name="pos",
is_setting=True,
is_display=True,
)
self._append(
AdjustablePv,
self.pvname+":HLM",
name="limit_high",
is_setting=True,
is_status=False,
is_display=False,
)
self._append(
AdjustablePv,
self.pvname+":LLM",
name="limit_low",
is_setting=True,
is_status=False,
is_display=False,
)
self._append(
AdjustablePv,
self.pvname + ":FRM_FORW.PROC",
name="home_forward",
is_setting=False,
is_status=False,
is_display=False,
)
self._append(
AdjustablePv,
self.pvname + ":FRM_BACK.PROC",
name="home_backward",
is_setting=False,
is_status=False,
is_display=False,
)
self._append(
AdjustablePv,
self.pvname + ":STOP.PROC",
name="_stop_pv",
is_setting=False,
is_status=False,
is_display=False,
)
def stop(self):
self._stop_pv(1)
def move(self, value, check=True, wait=False):
if check:
if self.limit_low:
if value < self.limit_low():
raise Exception(
f"Target value of {self.name} is smaller than limit value!"
)
if self.limit_high:
if self.limit_high() < value:
raise Exception(
f"Target value of {self.name} is higher than limit value!"
)
self.pos(value)
if wait:
time.sleep(0.02)
while self.pos.get_change_done() == 0:
time.sleep(0.02)
def get_limits(self):
return (self.limit_low(), self.limit_high())
def set_limits(self, limit_low, limit_high):
self.limit_low(limit_low)
self.limit_high(limit_high)
def get_current_value(self):
return self.pos()
def set_target_value(self, value, hold=False, check=True):
changer = lambda value: self.move(value, check=check, wait=True)
return Changer(
target=value,
parent=self,
changer=changer,
hold=hold,
stopper=self.stop,
)
# return string with motor value as variable representation
def __str__(self):
# """ return short info for the current motor"""
s = f"{self.name}"
# s += f"\t@ {colorama.Style.BRIGHT}{self.get_current_value():1.6g}{colorama.Style.RESET_ALL} stat: {self.status_flag().name}"
s += f"\t@ {colorama.Style.BRIGHT}{self.get_current_value():1.6g}{colorama.Style.RESET_ALL}"
# # s += "\tuser limits (low,high) : {:1.6g},{:1.6g}\n".format(*self.get_limits())
s += f"\n{colorama.Style.DIM}low limit {colorama.Style.RESET_ALL}"
s += ValueInRange(*self.get_limits()).get_str(self.get_current_value())
s += f" {colorama.Style.DIM}high limit{colorama.Style.RESET_ALL}"
# # s += "\tuser limits (low,high) : {:1.6g},{1.6g}".format(self.get_limits())
return s
def __repr__(self):
print(str(self))
return object.__repr__(self)
@spec_convenience
@update_changes
@get_from_archive
@@ -1222,7 +1371,7 @@ class SmaractRecord(Assembly):
self._append(
AdjustablePv,
self.pvname + ".HOMR",
self.pvname + ".HOMF",
name="home_forward",
is_setting=False,
is_status=False,
+5 -1
View File
@@ -380,7 +380,11 @@ class Assembly:
tab.append(
[".".join([main_name, name]), value, unit, typechar, description]
)
s = tabulate(tab, tablefmt=tablefmt, maxcolwidths=maxcolwidths)
if tab:
s = tabulate(tab, tablefmt=tablefmt, maxcolwidths=maxcolwidths)
else:
s=''
return s
def status_to_elog(
+9 -5
View File
@@ -156,7 +156,7 @@ class StaeubliTx200(Assembly):
def stop(self):
try:
self.z_lin.stop()
self.cartesian.z_lin.stop()
except:
print("Failed to stop linear axis")
self.get_eval_result("robot.stop()")
@@ -213,6 +213,10 @@ class StaeubliTx200(Assembly):
vals = {k: v for k, v in zip(["gamma", "delta", "r"], [gamma,delta,t_det]) if not v is None}
return self.get_eval_result(cmd=f"robot.sph2cart(**{vals})")
def remote_connection_to_server(self, resolution="2048x1280"):
cmd = f"xfreerdp /v:PC14742 /size:{resolution} /u:gac-bernina@psich"
return self._run_cmd(cmd)
######## Motion recording ##########
def record_motion(self, **kwargs):
"""
@@ -275,7 +279,7 @@ class StaeubliTx200(Assembly):
Simulated stored commands on the controller.
"""
sim = np.array(self.get_eval_result(f"robot.simulate_stored_commands()"))
lin = np.array([self.z_lin()]*len(sim))
lin = np.array([self.cartesian.z_lin()]*len(sim))
sim = np.vstack([lin,sim.T]).T
if plot:
if self._urdf is not None:
@@ -303,7 +307,7 @@ class StaeubliTx200(Assembly):
coordinates is returned. Setting coordinates only has an effect, when the motion is simulated.
"""
sim = np.array(self.get_eval_result(f"robot.move_spherical(r={t_det}, gamma={gamma}, delta={delta}, simulate=True, coordinates='{coordinates}')"))
lin = np.array([self.z_lin()]*len(sim))
lin = np.array([self.cartesian.z_lin()]*len(sim))
sim = np.vstack([lin,sim.T]).T
if plot:
if self._urdf is not None:
@@ -323,7 +327,7 @@ class StaeubliTx200(Assembly):
Simulated motion in the joint coordinate system.
"""
sim = np.array(self.get_eval_result(f"robot.move_joint(j1={j1}, j2={j2}, j3={j3}, j4={j4}, j5={j5}, j6={j6}, simulate=True"))
lin = np.array([self.z_lin()]*11)
lin = np.array([self.cartesian.z_lin()]*11)
sim = np.vstack([lin,sim.T]).T
if plot:
if self._urdf is not None:
@@ -350,7 +354,7 @@ class StaeubliTx200(Assembly):
coordinates is returned. Setting coordinates only has an effect, when the motion is simulated.
"""
sim = np.array(self.get_eval_result(f"robot.move_cartesian(x={x}, y={y}, z={z}, rx={rx}, ry={ry}, rz={rz}, simulate=True, coordinates='{coordinates}')"))
lin = np.array([self.z_lin()]*11)
lin = np.array([self.cartesian.z_lin()]*11)
sim = np.vstack([lin,sim.T]).T
if plot:
if self._urdf is not None:
+295 -161
View File
@@ -2,7 +2,7 @@ from eco.devices_general.powersockets import MpodChannel
import sys
sys.path.append("..")
from ..devices_general.motors import MotorRecord, SmaractRecord
from ..devices_general.motors import MotorRecord, SmaractRecord, ThorlabsPiezoRecord
from ..epics.adjustable import AdjustablePv
import numpy as np
from epics import PV
@@ -90,6 +90,53 @@ class High_field_thz_chamber(Assembly):
},
}
self.motor_configuration_cube = {
"inc_rz": {
"id": "SARES23-USR:MOT_5",
"pv_descr": "Module2:2 THz Inc Cube Rz",
"direction": 1,
"sensor": 53,
"speed": 250,
"home_direction": "back",
"kwargs": {"accuracy": 0.01},
},
"inc_z": {
"id": "SARES23-USR:MOT_4",
"pv_descr": "Module2:1 THz Inc Cube z ",
"direction": 1,
"sensor": 42,
"speed": 250,
"home_direction": "back",
},
"inc_x": {
"id": "SARES23-USR:MOT_6",
"pv_descr": "Module2:3 THz Inc Cube x ",
"direction": 1,
"sensor": 42,
"speed": 250,
"home_direction": "forward",
},
"inc_ry": {
"id": "SARES23-USR:MOT_18",
"pv_descr": "Module6:3 THz Inc Cube Ry ",
"direction": 0,
"sensor": 2,
"speed": 250,
"home_direction": "forward",
},
}
self.motor_configuration_ocb = {
"inc_x": {
"id": "SARES23-USR:MOT_6",
"pv_descr": "Module2:3 THz Inc Cube x ",
"direction": 1,
"sensor": 42,
"speed": 250,
"home_direction": "forward",
},
}
### lakeshore temperatures ####
self._append(
AdjustablePv,
@@ -136,6 +183,25 @@ class High_field_thz_chamber(Assembly):
name=name,
is_setting=True,
)
if "cube" in configuration:
for name, config in self.motor_configuration_cube.items():
self._append(
SmaractRecord,
pvname=config["id"],
name=name,
is_setting=True,
)
def home_smaract_stages_cube():
return self.home_smaract_stages(motor_configuration=self.motor_configuration_cube)
def set_stage_config_cube():
return self.set_stage_config(cfg=self.motor_configuration_cube)
self.home_smaract_stages_cube = home_smaract_stages_cube
self.set_stage_config_cube = set_stage_config_cube
if "ocb" in configuration:
pass
self._append(
AdjustableFS,
"/sf/bernina/config/eco/reference_values/thc_par_in_pos",
@@ -180,6 +246,7 @@ class High_field_thz_chamber(Assembly):
if illumination_mpod:
for illu in illumination_mpod:
self._append(MpodChannel,illu['pvbase'], illu['channel_number'], module_string=illu['module_string'], name=illu['name'])
if helium_control_valve:
self._append(MpodChannel,helium_control_valve['pvbase'], helium_control_valve['channel_number'], module_string=helium_control_valve['module_string'], name="_helium_valve_mpod_ch", is_display=True, is_setting=True)
@@ -198,7 +265,6 @@ class High_field_thz_chamber(Assembly):
else:
voltage = val*(5.5-2.9)/100+2.9
return voltage
self._append(AdjustableVirtual, [self._helium_valve_mpod_ch.voltage], get_valve, set_valve, name=helium_control_valve["name"], is_display=True, is_setting=False)
def moveout(self):
@@ -224,8 +290,10 @@ class High_field_thz_chamber(Assembly):
self.x.set_target_value(self.par_in_pos()[0]).wait()
self.z.set_target_value(self.par_in_pos()[1])
def set_stage_config(self):
for name, config in self.motor_configuration.items():
def set_stage_config(self, cfg=None):
if cfg is None:
cfg = self.motor_configuration
for name, config in cfg.items():
mot = self.__dict__[name]
mot.description(config["pv_descr"])
#mot.stage_type(config["type"])
@@ -235,13 +303,14 @@ class High_field_thz_chamber(Assembly):
sleep(0.5)
mot.calibrate_sensor()
def home_smaract_stages(self, stages=None):
if stages == None:
stages = self.motor_configuration.keys()
def home_smaract_stages(self, motor_configuration=None):
if motor_configuration == None:
motor_configuration= self.motor_configuration
stages = motor_configuration.keys()
print("#### Positions before homing ####")
print(self.__repr__())
for name in stages:
config = self.motor_configuration[name]
config = motor_configuration[name]
mot = self.__dict__[name]
print(
"#### Homing {} in {} direction ####".format(
@@ -272,6 +341,7 @@ class High_field_thz_chamber(Assembly):
)
mot.home_reverse(1)
def calc_otti(
self, otti_nu=None, otti_del=None, otti_det=None, plotit=True, **kwargs
):
@@ -291,136 +361,173 @@ class High_field_thz_chamber(Assembly):
class Organic_crystal_breadboard(Assembly):
def __init__(self, name=None, Id=None, alias_namespace=None):
def __init__(self, name=None, alias_namespace=None):
super().__init__(name=name)
self.Id = Id
self.name = name
self.alias = Alias(name)
self.motor_configuration = {
"mir_x": {
# "id": "-LIC17",
"id": "-USR:MOT_8",
"pv_descr": "Motor8:2 THz mirror x ",
"type": 1,
"sensor": 13,
"speed": 250,
"home_direction": "back",
},
"mir_rz": {
# "id": "-LIC18",
"id": "-USR:MOT_9",
"pv_descr": "Motor8:3 THz mirror rz ",
"type": 1,
"sensor": 13,
"speed": 250,
"home_direction": "back",
},
"mir_ry": {
# "id": "-ESB1",
"id": "-LIC:MOT_18",
"pv_descr": "Motor3:1 THz mirror ry ",
"type": 2,
"sensor": 1,
"speed": 250,
"home_direction": "forward",
},
"mir_z": {
# "id": "-LIC16",
"id": "-USR:MOT_7",
"pv_descr": "Motor8:1 THz mirror z",
"type": 1,
"sensor": 13,
"speed": 250,
"home_direction": "back",
},
"par_x": {
# "id": "-ESB3",
"id": "-LIC:MOT_17",
"pv_descr": "Motor3:3 THz parabola2 x",
"type": 1,
"sensor": 0,
"speed": 250,
"home_direction": "back",
},
"delaystage_thz": {
# "id": "-ESB18",
"id": "-USR:MOT_1",
"pv_descr": "Motor8:3 NIR delay stage",
"type": 1,
"sensor": 0,
"speed": 100,
"home_direction": "back",
},
#"mir_x": {
# # "id": "-LIC17",
# "id": "-USR:MOT_8",
# "pv_descr": "Motor8:2 THz mirror x ",
# "type": 1,
# "sensor": 13,
# "speed": 250,
# "home_direction": "back",
#},
#"mir_rz": {
# # "id": "-LIC18",
# "id": "-USR:MOT_9",
# "pv_descr": "Motor8:3 THz mirror rz ",
# "type": 1,
# "sensor": 13,
# "speed": 250,
# "home_direction": "back",
#},
#"mir_ry": {
# # "id": "-ESB1",
# "id": "-LIC:MOT_18",
# "pv_descr": "Motor3:1 THz mirror ry ",
# "type": 2,
# "sensor": 1,
# "speed": 250,
# "home_direction": "forward",
#},
#"mir_z": {
# # "id": "-LIC16",
# "id": "-USR:MOT_7",
# "pv_descr": "Motor8:1 THz mirror z",
# "type": 1,
# "sensor": 13,
# "speed": 250,
# "home_direction": "back",
#},
#"par_x": {
# # "id": "-ESB3",
# "id": "-LIC:MOT_17",
# "pv_descr": "Motor3:3 THz parabola2 x",
# "type": 1,
# "sensor": 0,
# "speed": 250,
# "home_direction": "back",
#},
#"delaystage_thz": {
# "id": "-USR:MOT_1",
# "pv_descr": "Motor8:3 NIR delay stage",
# "type": 1,
# "sensor": 0,
# "speed": 100,
# "home_direction": "back",
#},
"nir_m1_ry": {
# "id": "-ESB17",
"id": "-USR:MOT_3",
"pv_descr": "Motor8:2 near IR mirror 1 ry",
"type": 2,
"sensor": 1,
"id": "SARES23-LIC:MOT_18",
"pv_descr": "Module6:3 NIR Mirr1 Ry",
"sensor": 2,
"direction": 0,
"speed": 250,
"home_direction": "back",
},
"nir_m1_rx": {
"id": "-USR:MOT_16",
"pv_descr": "Motor8:1 near IR mirror 1 rx",
"type": 2,
"sensor": 1,
"id": "SARES23-USR:MOT_10",
"pv_descr": "Module4:1 NIR Mirr1 Rx",
"sensor": 53,
"speed": 250,
"direction": 1,
"home_direction": "back",
},
"nir_m2_ry": {
# "id": "-ESB9",
"id": "-USR:MOT_14",
"pv_descr": "Motor5:3 near IR mirror 2 ry",
"type": 2,
"sensor": 1,
"id": "SARES23-USR:MOT_1",
"pv_descr": "Module1:1 NIR Mirr2 Ry",
"sensor":2,
"speed": 250,
"direction": 1,
"home_direction": "back",
},
"nir_m2_rx": {
# "id": "-USR:MOT_4",
"id": "-USR:MOT_12",
"pv_descr": "Motor4:1 near IR mirror 2 rx",
"type": 1,
"sensor": 13,
"id": "SARES23-USR:MOT_7",
"pv_descr": "Module3:1 NIR Mirr2 rx",
"sensor": 53,
"direction": 0,
"speed": 250,
"home_direction": "back",
},
"crystal": {
"id": "-USR:MOT_2",
"pv_descr": "Motor3:2 crystal rotation",
"type": 2,
"sensor": 1,
"delay_400nm": {
# "id": "-USR:MOT_4",
"id": "SARES23-LIC:MOT_17",
"pv_descr": "Module6:2 400nm_stage",
"sensor": 2,
"direction": 0,
"speed": 250,
"home_direction": "back",
},
"wp": {
"id": "-USR:MOT_7",
"pv_descr": "Motor5:1 waveplate rotation",
"type": 2,
"sensor": 1,
"speed": 250,
"home_direction": "back",
"direction": 1,
},
#"crystal": {
# "id": "-USR:MOT_2",
# "pv_descr": "Motor3:2 crystal rotation",
# "type": 2,
# "sensor": 1,
# "speed": 250,
# "home_direction": "back",
#},
#"wp": {
# "id": "-USR:MOT_7",
# "pv_descr": "Motor5:1 waveplate rotation",
# "type": 2,
# "sensor": 1,
# "speed": 250,
# "home_direction": "back",
# "direction": 1,
#},
}
self.motor_configuration_thorlabs = {
"polarizer": {
"pvname": "SLAAR21-LMOT-ELL1",
},
"waveplate_ir": {
"pvname": "SLAAR21-LMOT-ELL2",
},
"crystal": {
"pvname": "SLAAR21-LMOT-ELL3",
},
"waveplate_thz": {
"pvname": "SLAAR21-LMOT-ELL4",
},
}
### smaract motors ###
for name, config in self.motor_configuration.items():
self._append(
SmaractRecord,
pvname=Id + config["id"],
pvname=config["id"],
name=name,
is_setting=True,
)
self.delay_thz = DelayTime(self.delaystage_thz, name="delay_thz")
### thorlabs piezo motors ###
for name, config in self.motor_configuration_thorlabs.items():
self._append(
ThorlabsPiezoRecord,
pvname=config["pvname"],
name=name,
is_setting=True,
)
self._append(
MotorRecord,
pvname = "SLAAR21-LMOT-M522:MOTOR_1",
name="delaystage_thz",
is_setting=True,
is_display=False,
is_status=True,
)
self._append(
DelayTime,
self.delaystage_thz,
name="delay_thz",
is_setting=False,
is_display=True,
is_status=True,
)
self.thz_polarization = AdjustableVirtual(
[self.crystal, self.wp],
[self.crystal, self.waveplate_ir],
self.thz_pol_get,
self.thz_pol_set,
name="thz_polarization",
@@ -432,25 +539,27 @@ class Organic_crystal_breadboard(Assembly):
def thz_pol_get(self, val, val2):
return 1.0 * val
def set_stage_config(self):
for name, config in self.motor_configuration.items():
def set_stage_config(self, cfg=None):
if cfg is None:
cfg = self.motor_configuration
for name, config in cfg.items():
mot = self.__dict__[name]
mot.caqtdm_name(config["pv_descr"])
mot.stage_type(config["type"])
mot.sensor_type(config["sensor"])
mot.speed(config["speed"])
if "direction" in config.keys():
mot.direction(config["direction"])
mot.description(config["pv_descr"])
#mot.stage_type(config["type"])
mot.motor_parameters.sensor_type_num(config["sensor"])
mot.direction(config["direction"])
mot.motor_parameters.max_frequency(config["speed"])
sleep(0.5)
mot.calibrate_sensor(1)
mot.calibrate_sensor()
def home_smaract_stages(self, stages=None):
if stages == None:
stages = self.motor_configuration.keys()
def home_smaract_stages(self, motor_configuration=None):
if motor_configuration == None:
motor_configuration= self.motor_configuration
stages = motor_configuration.keys()
print("#### Positions before homing ####")
print(self.__repr__())
for name in stages:
config = self.motor_configuration[name]
config = motor_configuration[name]
mot = self.__dict__[name]
print(
"#### Homing {} in {} direction ####".format(
@@ -459,25 +568,27 @@ class Organic_crystal_breadboard(Assembly):
)
sleep(1)
if config["home_direction"] == "back":
mot.home_backward(1)
while mot.status_channel().value == 7:
mot.home_reverse(1)
sleep(.5)
while not mot.flags.motion_complete():
sleep(1)
if mot.is_homed() == 0:
if not mot.flags.is_homed():
print(
"Homing failed, try homing {} in forward direction".format(name)
)
mot.home_forward(1)
elif config["home_direction"] == "forward":
mot.home_forward(1)
while mot.status_channel().value == 7:
sleep(.5)
while not mot.flags.motion_complete():
sleep(1)
if mot.is_homed() == 0:
if not mot.flags.is_homed():
print(
"Homing failed, try homing {} in backward direction".format(
name
)
)
mot.home_backward(1)
mot.home_reverse(1)
def get_adjustable_positions_str(self):
ostr = "*****Organic Crystal Breadboard positions******\n"
@@ -595,64 +706,85 @@ class LiNbO3_crystal_breadboard:
return self.get_adjustable_positions_str()
class Electro_optic_sampling:
class Electro_optic_sampling(Assembly):
def __init__(
self, name=None, Id=None, alias_namespace=None, pgroup=None, diode_channels=None
self, name=None, diode_channels=None
):
self.Id = Id
super().__init__(name=name)
self.name = name
self.alias = Alias(name)
self.diode_channels = diode_channels
self.basepath = f"/sf/bernina/data/p18915/res/scan_info/"
self.motor_configuration = {
"ry": {
"id": "-ESB16",
"pv_descr": "Motor8:1 EOS prism ry ",
"type": 2,
"sensor": 1,
"id": "SARES23-USR:MOT_3",
"pv_descr": "Module1:3 EOS Ry",
"sensor": 2,
"direction": 0,
"speed": 250,
"home_direction": "back",
},
"rx": {
"id": "-ESB5",
"pv_descr": "Motor4:1 EOS prism rx ",
"type": 1,
"sensor": 0,
"id": "SARES23-USR:MOT_11",
"pv_descr": "Motor4:2 EOS Rx",
"sensor": 53,
"speed": 250,
"direction": 0,
"home_direction": "back",
},
"x": {
"id": "-ESB4",
"pv_descr": "Motor4:2 EOS prism x ",
"type": 1,
"sensor": 0,
"id": "SARES23-USR:MOT_12",
"pv_descr": "Module4:3 EOS x",
"sensor":42,
"speed": 250,
"direction": 0,
"home_direction": "back",
},
}
self._append(
MotorRecord,
"SLAAR21-LMOT-M521:MOTOR_1",
name="delaystage_pump",
is_setting=True,
)
self._append(
DelayTime,
self.delaystage_pump,
name="delay_pump",
is_setting=True,
)
### in vacuum smaract motors ###
for name, config in self.motor_configuration.items():
addSmarActRecordToSelf(self, Id=Id + config["id"], name=name)
self._append(
SmaractRecord,
pvname=config["id"],
name=name,
is_setting=True,
)
def set_stage_config(self):
for name, config in self.motor_configuration.items():
mot = self.__dict__[name]._device
mot.put("NAME", config["pv_descr"])
mot.put("STAGE_TYPE", config["type"])
mot.put("SET_SENSOR_TYPE", config["sensor"])
mot.put("CL_MAX_FREQ", config["speed"])
def set_stage_config(self, cfg=None):
if cfg is None:
cfg = self.motor_configuration
for name, config in cfg.items():
mot = self.__dict__[name]
mot.description(config["pv_descr"])
#mot.stage_type(config["type"])
mot.motor_parameters.sensor_type_num(config["sensor"])
mot.direction(config["direction"])
mot.motor_parameters.max_frequency(config["speed"])
sleep(0.5)
mot.put("CALIBRATE.PROC", 1)
mot.calibrate_sensor()
def home_smaract_stages(self, stages=None):
if stages == None:
stages = self.motor_configuration.keys()
def home_smaract_stages(self, motor_configuration=None):
if motor_configuration == None:
motor_configuration= self.motor_configuration
stages = motor_configuration.keys()
print("#### Positions before homing ####")
print(self.__repr__())
for name in stages:
config = self.motor_configuration[name]
mot = self.__dict__[name]._device
config = motor_configuration[name]
mot = self.__dict__[name]
print(
"#### Homing {} in {} direction ####".format(
name, config["home_direction"]
@@ -660,25 +792,27 @@ class Electro_optic_sampling:
)
sleep(1)
if config["home_direction"] == "back":
mot.put("FRM_BACK.PROC", 1)
while mot.get("STATUS") == 7:
mot.home_reverse(1)
sleep(.5)
while not mot.flags.motion_complete():
sleep(1)
if mot.get("GET_HOMED") == 0:
if not mot.flags.is_homed():
print(
"Homing failed, try homing {} in forward direction".format(name)
)
mot.put("FRM_FORW.PROC", 1)
mot.home_forward(1)
elif config["home_direction"] == "forward":
mot.put("FRM_FORW.PROC", 1)
while mot.get("STATUS") == 7:
mot.home_forward(1)
sleep(.5)
while not mot.flags.motion_complete():
sleep(1)
if mot.get("GET_HOMED") == 0:
if not mot.flags.is_homed():
print(
"Homing failed, try homing {} in backward direction".format(
name
)
)
mot.put("FRM_BACK.PROC", 1)
mot.home_reverse(1)
def fit_funvction(self, t, t0, w, tau):
from scipy.special import erf
+1 -32
View File
@@ -8,7 +8,7 @@ from ..aliases import append_object_to_object, Alias
from scipy.spatial.transform import Rotation
import datetime
from ..elements.assembly import Assembly
from eco.devices_general.motors import AdjustablePiHex
class Hexapod_PI:
def __init__(self, Id):
@@ -26,37 +26,6 @@ class Hexapod_PI:
for i in "RST"
]
class AdjustablePiHex(AdjustablePv):
def __init__(self, pvname=None, pvreadbackname=None, accuracy=None, unit=None, name=None):
super().__init__(pvname, pvreadbackname=pvreadbackname, accuracy=accuracy, unit=unit, name=name)
self.limit_high = AdjustableFS(f'/sf/bernina/config/eco/reference_values/hex_pi_{name}_limit_high.json', default_value=0)
self.limit_low = AdjustableFS(f'/sf/bernina/config/eco/reference_values/hex_pi_{name}_limit_low.json', default_value=0)
def change(self, value):
if self.limit_low:
if value < self.limit_low():
raise Exception(
f"Target value of {self.name} is smaller than limit value!"
)
if self.limit_high:
if self.limit_high() < value:
raise Exception(
f"Target value of {self.name} is higher than limit value!"
)
self._pv.put(value)
time.sleep(0.1)
while self.get_change_done() == 0:
time.sleep(0.1)
def get_limits(self):
return (self.limit_low(), self.limit_high())
def set_limits(self, limit_low, limit_high):
self.limit_low(limit_low)
self.limit_high(limit_high)
class HexapodPI(Assembly):
def __init__(self, pvname, name=None, fina_angle_offset=None):
super().__init__(name=name)
+15 -6
View File
@@ -48,11 +48,17 @@ class TimetoolBerninaUSD(Assembly):
self._append(DelayTime, self.delaystage_tt_usd, name="delay", is_setting=True)
self.proc_client = PipelineClient()
self.proc_pipeline = processing_pipeline
self._append(Pipeline,self.proc_pipeline, name='pipeline_projection', is_setting=True)
self.proc_instance = processing_instance
self.proc_pipeline_edge = edge_finding_pipeline
self._append(Pipeline,self.proc_pipeline_edge, name='pipeline_edgefinding', is_setting=True)
try:
self.proc_pipeline = processing_pipeline
self._append(Pipeline,self.proc_pipeline, name='pipeline_projection', is_setting=True)
self.proc_instance = processing_instance
except Exception as e:
print(f"Timetool projection pipeline initialization failed with: \n{e}")
try:
self.proc_pipeline_edge = edge_finding_pipeline
self._append(Pipeline,self.proc_pipeline_edge, name='pipeline_edgefinding', is_setting=True)
except Exception as e:
print(f"Timetool edge finding pipeline initialization failed with: \n{e}")
self.spectrometer_camera_channel = spectrometer_camera_channel
self._append(
Target_xyz,
@@ -190,7 +196,10 @@ class TimetoolBerninaUSD(Assembly):
is_display=True,
)
if andor_spectrometer:
self._append(SpectrometerAndor,andor_spectrometer, name='spectrometer', is_setting=True, is_display='recursive')
try:
self._append(SpectrometerAndor,andor_spectrometer, name='spectrometer', is_setting=True, is_display='recursive')
except Exception as e:
print(f"Andor spectrometer initialization failed with: \n{e}")
def get_online_data(self):
+3
View File
@@ -1156,6 +1156,7 @@ class SolidTargetDetectorBerninaUSD(Assembly):
name=None,
# calc=None,
# calc_calib={},
pipeline_computation = None,
):
super().__init__(name=name)
@@ -1266,6 +1267,8 @@ class SolidTargetDetectorBerninaUSD(Assembly):
# is_setting=True,
# is_display=False,
# )
if pipeline_computation:
self._append(Pipeline, pipeline_computation,name='pipeline_comp', is_setting=True, is_display=False)
def get_calibration_values(self, seconds=5):
self.x_diodes.set_target_value(0).wait()