from ...core.devio import SCPI, interface
from ...core.utils import py3, general
from .base import GenericSirahError, GenericSirahBackendError
import time
import collections
import warnings
TThinetCtlParameters=collections.namedtuple("TThinetCtlParameters",["setpoint","P","I","avg"])
TPiezoetDriveParameters=collections.namedtuple("TPiezoetDriveParameters",["amplitude","rate","oversamp"])
TPiezoetFeedbackParameters=collections.namedtuple("TPiezoetFeedbackParameters",["P","avg","phase"])
TPiezoetFeedforwardParameters=collections.namedtuple("TPiezoetFeedforwardParameters",["ampl","phase"])
TSlowpiezoCtlParameters=collections.namedtuple("TSlowpiezoCtlParameters",["setpoint","P","I","freeP"])
TFastpiezoCtlParameters=collections.namedtuple("TFastpiezoCtlParameters",["setpoint","I","lockpoint"])
TRefcellWaveformParameters=collections.namedtuple("TRefcellWaveformParameters",["lower_limit","upper_limit","oversamp","mode"])
TScanMode=collections.namedtuple("TScanMode",["falling","stop_lower","stop_upper"])
TScanParameters=collections.namedtuple("TScanParameters",["device","mode","lower_limit","upper_limit","rise_speed","fall_speed"])
[docs]
class SirahMatisse(SCPI.SCPIDevice):
"""
Sirah Matisse laser control.
Args:
addr: device address (usually a VISA name).
"""
Error=GenericSirahError
ReraiseError=GenericSirahBackendError
_bool_selector=("FALSE","TRUE")
def __init__(self, addr):
super().__init__(addr)
with self._close_on_error():
self.get_id()
self._add_scpi_parameter("diode_power","DPOW:DC")
self._add_scpi_parameter("diode_power_waveform","DPOW:WAVTAB",kind="string")
self._add_scpi_parameter("diode_power_lowlevel","DPOW:LOW",set_echo=True)
self._add_scpi_parameter("thinet_power","TE:DC")
self._add_scpi_parameter("refcell_waveform","REFCELL:TABLE",kind="string")
self._add_scpi_parameter("bifi_position","MOTBI:POS",kind="int",set_echo=True)
self._add_scpi_parameter("bifi_status","MOTBI:STA",kind="int")
self._add_scpi_parameter("bifi_position_max","MOTBI:MAX",kind="int")
self._add_scpi_parameter("thinet_position","MOTTE:POS",kind="int",set_echo=True)
self._add_scpi_parameter("thinet_status","MOTTE:STA",kind="int")
self._add_scpi_parameter("thinet_position_max","MOTTE:MAX",kind="int")
self._add_scpi_parameter("thinet_ctl_status","TE:CNTRSTA",kind="param",parameter="lock_ctl_status",set_echo=True)
self._add_scpi_parameter("thinet_ctl_errsig","TE:CNTRERR",kind="float")
self._add_scpi_parameter("thinet_ctl_setpoint","TE:CNTRSP",kind="float",set_echo=True)
self._add_scpi_parameter("thinet_ctl_P","TE:CNTRPROP",kind="float",set_echo=True)
self._add_scpi_parameter("thinet_ctl_I","TE:CNTRINT",kind="float",set_echo=True)
self._add_scpi_parameter("thinet_ctl_avg","TE:CNTRAVG",kind="int",set_echo=True)
self._add_scpi_parameter("piezoet_ctl_status","PZETL:CNTRSTA",kind="param",parameter="lock_ctl_status",set_echo=True)
self._add_scpi_parameter("piezoet_baseline","PZETL:BASE",kind="float",set_echo=True)
self._add_scpi_parameter("piezoet_drv_amp","PZETL:AMP",kind="float",set_echo=True)
self._add_scpi_parameter("piezoet_drv_rate","PZETL:SRATE",kind="param",parameter="piezoet_drv_rate",set_echo=True)
self._add_scpi_parameter("piezoet_drv_oversamp","PZETL:OVER",kind="int",set_echo=True)
self._add_scpi_parameter("piezoet_fb_P","PZETL:CNTRPROP",kind="float",set_echo=True)
self._add_scpi_parameter("piezoet_fb_avg","PZETL:CNTRAVG",kind="int",set_echo=True)
self._add_scpi_parameter("piezoet_fb_phase","PZETL:CNTRPHSF",kind="int",set_echo=True)
self._add_scpi_parameter("piezoet_ff_amp","FEF:AMP",kind="float",set_echo=True)
self._add_scpi_parameter("piezoet_ff_phase","FEF:PHSF",kind="int",set_echo=True)
self._add_scpi_parameter("slowpiezo_value","SPZT:NOW",kind="float",set_echo=True)
self._add_scpi_parameter("slowpiezo_ctl_status","SPZT:CNTRSTA",kind="param",parameter="lock_ctl_status",set_echo=True)
self._add_scpi_parameter("slowpiezo_ctl_setpoint","SPZT:CNTRSP",kind="float",set_echo=True)
self._add_scpi_parameter("slowpiezo_ctl_P","SPZT:LPROP",kind="float",set_echo=True)
self._add_scpi_parameter("slowpiezo_ctl_I","SPZT:LINT",kind="float",set_echo=True)
try:
self.ask("SPZT:FRSP?")
self._add_scpi_parameter("slowpiezo_ctl_freeP","SPZT:FRSP",kind="float",set_echo=True)
except GenericSirahError:
self._add_scpi_parameter("slowpiezo_ctl_freeP","SPZT:FPROP",kind="float",set_echo=True)
self._add_scpi_parameter("fastpiezo_value","FPZT:NOW",kind="float",set_echo=True)
self._add_scpi_parameter("fastpiezo_ctl_status","FPZT:CNTRSTA",kind="param",parameter="lock_ctl_status",set_echo=True)
self._add_scpi_parameter("fastpiezo_ctl_setpoint","FPZT:CNTRSP",kind="float",set_echo=True)
self._add_scpi_parameter("fastpiezo_ctl_lockpoint","FPZT:LKP",kind="float",set_echo=True)
self._add_scpi_parameter("fastpiezo_ctl_I","FPZT:CNTRINT",kind="float",set_echo=True)
self._add_scpi_parameter("fastpiezo_ctl_locked","FPZT:LOCK",kind="bool")
self._add_scpi_parameter("refcell_value","REFCELL:NOW",kind="float",set_echo=True)
self._add_scpi_parameter("refcell_wave_lowlim","REFCELL:LLM",kind="float",set_echo=True)
self._add_scpi_parameter("refcell_wave_upplim","REFCELL:ULM",kind="float",set_echo=True)
self._add_scpi_parameter("refcell_wave_oversamp","REFCELL:OVER",kind="int",set_echo=True)
self._add_scpi_parameter("refcell_wave_mode","REFCELL:MODE",kind="param",parameter="refcell_wave_mode",set_echo=True)
self._add_scpi_parameter("scan_status","SCAN:STA",kind="param",parameter="lock_ctl_status",set_echo=True)
self._add_scpi_parameter("scan_value","SCAN:NOW",kind="float",set_echo=True)
self._add_scpi_parameter("scan_device","SCAN:DEV",kind="param",parameter="scan_device",set_echo=True)
self._add_scpi_parameter("scan_mode","SCAN:MODE",kind="int",set_echo=True)
self._add_scpi_parameter("scan_lowlim","SCAN:LLM",kind="float",set_echo=True)
self._add_scpi_parameter("scan_upplim","SCAN:ULM",kind="float",set_echo=True)
self._add_scpi_parameter("scan_risespd","SCAN:RSPD",kind="float",set_echo=True)
self._add_scpi_parameter("scan_fallspd","SCAN:FSPD",kind="float",set_echo=True)
self._add_status_variable("diode_power",self.get_diode_power)
self._add_status_variable("diode_power_lowlevel",self.get_diode_power_lowlevel)
self._add_status_variable("thinet_power",self.get_thinet_power)
self._add_status_variable("bifi_position",self.bifi_get_position)
self._add_status_variable("bifi_range",self.bifi_get_range)
self._add_status_variable("bifi_status",self.bifi_get_status)
self._add_status_variable("thinet_position",self.thinet_get_position)
self._add_status_variable("thinet_range",self.thinet_get_range)
self._add_status_variable("thinet_status",self.thinet_get_status)
self._add_settings_variable("thinet_ctl_status",self.get_thinet_ctl_status,self.set_thinet_ctl_status)
self._add_settings_variable("thinet_ctl_params",self.get_thinet_ctl_params,self.set_thinet_ctl_params)
self._add_status_variable("piezoet_position",self.get_piezoet_position)
self._add_settings_variable("piezoet_ctl_status",self.get_piezoet_ctl_status,self.set_piezoet_ctl_status)
self._add_settings_variable("piezoet_drive_params",self.get_piezoet_drive_params,self.set_piezoet_drive_params)
self._add_settings_variable("piezoet_feedback_params",self.get_piezoet_feedback_params,self.set_piezoet_feedback_params)
self._add_settings_variable("piezoet_feedforward_params",self.get_piezoet_feedforward_params,self.set_piezoet_feedforward_params)
self._add_status_variable("slowpiezo_position",self.get_slowpiezo_position)
self._add_settings_variable("slowpiezo_ctl_status",self.get_slowpiezo_ctl_status,self.set_slowpiezo_ctl_status)
self._add_settings_variable("slowpiezo_ctl_params",self.get_slowpiezo_ctl_params,self.set_slowpiezo_ctl_params)
self._add_status_variable("fastpiezo_position",self.get_fastpiezo_position)
self._add_status_variable("fastpiezo_locked",self.is_fastpiezo_locked)
self._add_settings_variable("fastpiezo_ctl_status",self.get_fastpiezo_ctl_status,self.set_fastpiezo_ctl_status,ignore_error=GenericSirahError)
self._add_settings_variable("fastpiezo_ctl_params",self.get_fastpiezo_ctl_params,self.set_fastpiezo_ctl_params,ignore_error=GenericSirahError)
self._add_status_variable("refcell_position",self.get_refcell_position,ignore_error=GenericSirahError)
self._add_settings_variable("refcell_waveform_params",self.get_refcell_waveform_params,self.set_refcell_waveform_params,ignore_error=GenericSirahError)
self._add_settings_variable("scan_status",self.get_scan_status,self.set_scan_status)
self._add_settings_variable("scan_position",self.get_scan_position,self.set_scan_position)
self._add_settings_variable("scan_params",self.get_scan_params,self.set_scan_params)
_id_comm="IDN?"
_float_fmt="{:.8f}"
def _instr_read(self, raw=False, size=None):
res=super()._instr_read(raw=raw,size=size)
if not raw:
res=res.strip()
if res.startswith(b":"):
sres=res.split(maxsplit=1)
res=sres[1] if len(sres)>1 else b""
elif res.upper().startswith(b"!ERROR"):
raise GenericSirahError("device replied with an error: {}".format(py3.as_str(res[6:]).strip()))
return res
_ask_err_ntries=3
_ask_err_delay=1.
_ask_err_verbose=False
[docs]
def ask(self, *args, **kwargs):
for i in range(self._ask_err_ntries):
try:
return super().ask(*args,**kwargs)
except GenericSirahError as err:
if self._ask_err_verbose:
warnings.warn("Sirah Matisse error: {}".format(err))
if not err.args:
raise
msg=err.args[0]
hdr="device replied with an error:"
if not msg.startswith(hdr):
raise
emsg=msg[len(hdr):].strip()
if not emsg.startswith("12,"):
raise
if i==self._ask_err_ntries-1:
raise
time.sleep(self._ask_err_delay)
self.reconnect()
time.sleep(self._ask_err_delay)
def _parse_status(self, status_n, code_length, bits, codes, errs):
bits=[v for b,v in bits.items() if status_n&b]
code_mask=(1<<code_length)-1
if "error" in bits:
code=errs.get(status_n&code_mask,"unknown")
else:
code=codes.get(status_n&code_mask,"unknown")
return code,bits
def _wait_for_status_bit(self, getstat, bit, enabled, timeout=30.):
countdown=general.Countdown(timeout)
while True:
_,curr_bits=getstat()
bit_enabled=bit in curr_bits
if bool(enabled)==bit_enabled:
return
if countdown.passed():
raise GenericSirahError("status waiting timed out")
time.sleep(1E-3)
[docs]
def get_diode_power(self):
"""Get the current laser resonator power"""
return self._get_scpi_parameter("diode_power")
[docs]
def get_diode_power_lowlevel(self):
"""Get the low-level cutoff current laser resonator power"""
return self._get_scpi_parameter("diode_power_lowlevel")
[docs]
def set_diode_power_lowlevel(self, cutoff):
"""Set the low-level cutoff current laser resonator power"""
self._set_scpi_parameter("diode_power_lowlevel",cutoff)
return self.get_diode_power_lowlevel()
[docs]
def get_thinet_power(self):
"""Get the current thin etalon reflex power"""
return self._get_scpi_parameter("thinet_power")
[docs]
def bifi_get_position(self):
"""Get the current position of the birefringent filter motor"""
return self._get_scpi_parameter("bifi_position")
[docs]
def bifi_get_range(self):
"""Get the maximum position of the birefringent filter motor"""
return self._get_scpi_parameter("bifi_position_max")
[docs]
def bifi_get_status_n(self):
"""Get the numerical status of the birefringent filter motor"""
return self._get_scpi_parameter("bifi_status")
_bifi_bits={(1<<7):"error",(1<<8):"moving",(1<<9):"off",(1<<10):"invalid_position",(1<<11):"limit_sw1",(1<<12):"limit_sw2",(1<<13):"home_sw",(1<<14):"manual"}
_bifi_codes={0x00:"undefined",0x01:"init",0x02:"idle",0x03:"button_pressed",0x04:"moving_short_manual",0x05:"moving_long_manual",
0x06:"deccel",0x07:"finishing",0x08:"moving_abs",0x09:"moving_rel",0x10:"calc_accel_table"}
_bifi_errs={0x00:"none",0x01:"undef_command",0x02:"frequency_out_of_range",0x03:"ramp_length_invald",0x04:"limit_sw",0x05:"hold_current_off",0x06:"hold_current_off",
0x07:"position_out_of_range",0x08:"ignored_because_running",0x20:"internal",0x21:"watchdog",0x22:"memory_write_error",0x23:"checksum"}
[docs]
def bifi_get_status(self):
"""
Get the parsed status of the birefringent filter motor.
Return tuple ``(code, bits)`` with, correspondingly, the general status/error code (e.g., ``"idle"``, ``"moving_abs"``, or ``"position_out_of_range"``),
and a set of active status bits (e.g., ``"moving"``, ``"error"``, or ``"limit_sw1"``).
"""
return self._parse_status(self.bifi_get_status_n(),7,self._bifi_bits,self._bifi_codes,self._bifi_errs)
[docs]
def bifi_clear_errors(self):
"""Clear the indicated errors of the birefringent filter motor"""
self.ask("MOTBI:CL")
[docs]
def bifi_is_moving(self):
"""Check if the birefringent filter is moving"""
return "moving" in self.bifi_get_status()[1]
[docs]
def bifi_wait_move(self, timeout=30.):
"""Wait until birefringent filter is done moving"""
self._wait_for_status_bit(self.bifi_get_status,"moving",enabled=False,timeout=timeout)
[docs]
def bifi_move_to(self, position, wait=True, wait_timeout=30.):
"""Move the birefringent filter to the current position"""
self._set_scpi_parameter("bifi_position",position)
if wait:
self.bifi_wait_move(timeout=wait_timeout)
[docs]
def bifi_stop(self):
"""Stop the birefringent filter motor"""
self.ask("MOTBI:HALT")
self.bifi_wait_move()
[docs]
def bifi_home(self, wait=True, wait_timeout=30.):
"""Home the birefringent filter motor"""
self.ask("MOTBI:HOME")
if wait:
self.bifi_wait_move(timeout=wait_timeout)
[docs]
def thinet_get_position(self):
"""Get the current position of the thin etalon motor"""
return self._get_scpi_parameter("thinet_position")
[docs]
def thinet_get_range(self):
"""Get the maximum position of the thin etalon motor"""
return self._get_scpi_parameter("thinet_position_max")
[docs]
def thinet_get_status_n(self):
"""Get the numerical status of the thin etalon motor"""
return self._get_scpi_parameter("thinet_status")
_thinet_bits={(1<<7):"error",(1<<8):"moving",(1<<9):"off",(1<<10):"invalid_position",(1<<11):"limit_sw1",(1<<12):"limit_sw2",(1<<13):"home_sw",(1<<14):"manual"}
_thinet_codes={0x00:"undefined",0x01:"init",0x02:"idle",0x03:"button_pressed",0x04:"moving_short_manual",0x05:"moving_long_manual",
0x06:"deccel",0x07:"finishing",0x08:"moving_abs",0x09:"moving_rel",0x10:"calc_accel_table"}
_thinet_errs={0x00:"none",0x01:"undef_command",0x02:"frequency_out_of_range",0x03:"ramp_length_invald",0x04:"limit_sw",0x05:"hold_current_off",0x06:"hold_current_off",
0x07:"position_out_of_range",0x08:"ignored_because_running",0x20:"internal",0x21:"watchdog",0x22:"memory_write_error",0x23:"checksum"}
[docs]
def thinet_get_status(self):
"""
Get the parsed status of the thin etalon motor.
Return tuple ``(code, bits)`` with, correspondingly, the general status/error code (e.g., ``"idle"``, ``"moving_abs"``, or ``"position_out_of_range"``),
and a set of active status bits (e.g., ``"moving"``, ``"error"``, or ``"limit_sw1"``).
"""
return self._parse_status(self.thinet_get_status_n(),7,self._thinet_bits,self._thinet_codes,self._thinet_errs)
[docs]
def thinet_clear_errors(self):
"""Clear the indicated errors of the thin etalon motor"""
self.ask("MOTTE:CL")
[docs]
def thinet_is_moving(self):
"""Check if the thin etalon is moving"""
return "moving" in self.thinet_get_status()[1]
[docs]
def thinet_wait_move(self, timeout=30.):
"""Wait until thin etalon is done moving"""
self._wait_for_status_bit(self.thinet_get_status,"moving",enabled=False,timeout=timeout)
[docs]
def thinet_move_to(self, position, wait=True, wait_timeout=30.):
"""Move the thin etalon to the current position"""
self._set_scpi_parameter("thinet_position",position)
if wait:
self.thinet_wait_move(timeout=wait_timeout)
[docs]
def thinet_stop(self):
"""Stop the thin etalon motor"""
self.ask("MOTTE:HALT")
self.thinet_wait_move()
[docs]
def thinet_home(self, wait=True, wait_timeout=30.):
"""Home the thin etalon motor"""
self.ask("MOTTE:HOME")
if wait:
self.thinet_wait_move(timeout=wait_timeout)
_p_lock_ctl_status=interface.EnumParameterClass("lock_ctl_status",[("run","RUN"),("run","RU"),("stop","STOP"),("stop","ST")])
[docs]
def get_thinet_ctl_status(self):
"""Get thin etalon lock status (``"run"`` or ``"stop"``)"""
return self._get_scpi_parameter("thinet_ctl_status")
[docs]
def set_thinet_ctl_status(self, status="run"):
"""Set thin etalon lock status (``"run"`` or ``"stop"``)"""
self._set_scpi_parameter("thinet_ctl_status",status)
return self.get_thinet_ctl_status()
[docs]
def get_thinet_error_signal(self):
"""Get error signal of the thin etalon lock (emulated when not available on older firmware)"""
try:
return self._get_scpi_parameter("thinet_ctl_errsig")
except GenericSirahError:
return self._get_scpi_parameter("thinet_ctl_setpoint")-self.get_thinet_power()/self.get_diode_power()
[docs]
def get_thinet_ctl_params(self):
"""
Get thin etalon lock control parameters.
Return tuple ``(setpoint, P, I, avg)``.
"""
return TThinetCtlParameters(*[self._get_scpi_parameter(n) for n in ["thinet_ctl_setpoint","thinet_ctl_P","thinet_ctl_I","thinet_ctl_avg"]])
[docs]
def set_thinet_ctl_params(self, setpoint=None, P=None, I=None, avg=None):
"""
Set thin etalon lock control parameters.
Any parameters which are ``None`` remain unchanged.
"""
for n,v in zip(["thinet_ctl_setpoint","thinet_ctl_P","thinet_ctl_I","thinet_ctl_avg"],[setpoint,P,I,avg]):
if v is not None:
self._set_scpi_parameter(n,v)
return self.get_thinet_ctl_params()
[docs]
def get_piezoet_ctl_status(self):
"""Get piezo etalon lock status (``"run"`` or ``"stop"``)"""
return self._get_scpi_parameter("piezoet_ctl_status")
[docs]
def set_piezoet_ctl_status(self, status="run"):
"""Set piezo etalon lock status (``"run"`` or ``"stop"``)"""
self._set_scpi_parameter("piezoet_ctl_status",status)
return self.get_piezoet_ctl_status()
[docs]
def get_piezoet_position(self):
"""Get piezo etalon DC position"""
return self._get_scpi_parameter("piezoet_baseline")
[docs]
def set_piezoet_position(self, value):
"""Set piezo etalon lock DC position"""
self._set_scpi_parameter("piezoet_baseline",value)
return self.get_piezoet_position()
_p_piezoet_drv_rate=interface.EnumParameterClass("piezoet_drv_rate",{"8k":"0","32k":"1","48k":"2","96k":"3"})
[docs]
def get_piezoet_drive_params(self):
"""
Get piezo etalon drive parameters.
Return tuple ``(amplitude, rate, oversamp)``.
"""
return TPiezoetDriveParameters(*[self._get_scpi_parameter(n) for n in ["piezoet_drv_amp","piezoet_drv_rate","piezoet_drv_oversamp"]])
[docs]
def set_piezoet_drive_params(self, amplitude=None, rate=None, oversamp=None):
"""
Set piezo etalon drive parameters.
`oversamp` should be between 8 and 32.
`rate` can take values ``"8k"``, ``"32k"``, ``"48k"``, or ``"96k"``.
Any parameters which are ``None`` remain unchanged.
"""
for n,v in zip(["piezoet_drv_amp","piezoet_drv_rate","piezoet_drv_oversamp"],[amplitude,rate,oversamp]):
if v is not None:
self._set_scpi_parameter(n,v)
return self.get_piezoet_drive_params()
[docs]
def get_piezoet_feedback_params(self):
"""
Get piezo etalon feedback parameters.
Return tuple ``(P, avg, phase)`` (phase is integer between 0 and oversampling).
"""
return TPiezoetFeedbackParameters(*[self._get_scpi_parameter(n) for n in ["piezoet_fb_P","piezoet_fb_avg","piezoet_fb_phase"]])
[docs]
def set_piezoet_feedback_params(self, P=None, avg=None, phase=None):
"""
Set piezo etalon feedback parameters.
Phase is integer between 0 and oversampling.
Any parameters which are ``None`` remain unchanged.
"""
for n,v in zip(["piezoet_fb_P","piezoet_fb_avg","piezoet_fb_phase"],[P,avg,phase]):
if v is not None:
self._set_scpi_parameter(n,v)
return self.get_piezoet_feedback_params()
[docs]
def get_piezoet_feedforward_params(self):
"""
Get piezo etalon feedforward parameters.
Return tuple ``(amp, phase)`` (phase is integer between 0 and oversampling).
"""
return TPiezoetFeedforwardParameters(*[self._get_scpi_parameter(n) for n in ["piezoet_ff_amp","piezoet_ff_phase"]])
[docs]
def set_piezoet_feedforward_params(self, amp=None, phase=None):
"""
Set piezo etalon feedforward parameters.
Phase is integer between 0 and oversampling.
Any parameters which are ``None`` remain unchanged.
"""
for n,v in zip(["piezoet_ff_amp","piezoet_ff_phase"],[amp,phase]):
if v is not None:
self._set_scpi_parameter(n,v)
return self.get_piezoet_feedforward_params()
[docs]
def get_slowpiezo_ctl_status(self):
"""Get slow piezo lock status (``"run"`` or ``"stop"``)"""
return self._get_scpi_parameter("slowpiezo_ctl_status")
[docs]
def set_slowpiezo_ctl_status(self, status="run"):
"""Set slow piezo lock status (``"run"`` or ``"stop"``)"""
self._set_scpi_parameter("slowpiezo_ctl_status",status)
return self.get_slowpiezo_ctl_status()
[docs]
def get_slowpiezo_position(self):
"""Get slow piezo DC position"""
return self._get_scpi_parameter("slowpiezo_value")
[docs]
def set_slowpiezo_position(self, value):
"""Set slow piezo DC position"""
self._set_scpi_parameter("slowpiezo_value",value)
return self.get_slowpiezo_position()
[docs]
def get_slowpiezo_ctl_params(self):
"""
Get slow piezo lock control parameters.
Return tuple ``(setpoint, P, I, freeP)``.
"""
return TSlowpiezoCtlParameters(*[self._get_scpi_parameter(n) for n in ["slowpiezo_ctl_setpoint","slowpiezo_ctl_P","slowpiezo_ctl_I","slowpiezo_ctl_freeP"]])
[docs]
def set_slowpiezo_ctl_params(self, setpoint=None, P=None, I=None, freeP=None):
"""
Set slow piezo lock control parameters.
Any parameters which are ``None`` remain unchanged.
"""
for n,v in zip(["slowpiezo_ctl_setpoint","slowpiezo_ctl_P","slowpiezo_ctl_I","slowpiezo_ctl_freeP"],[setpoint,P,I,freeP]):
if v is not None:
self._set_scpi_parameter(n,v)
return self.get_slowpiezo_ctl_params()
[docs]
def get_fastpiezo_ctl_status(self):
"""Get fast piezo lock status (``"run"`` or ``"stop"``)"""
return self._get_scpi_parameter("fastpiezo_ctl_status")
[docs]
def set_fastpiezo_ctl_status(self, status="run"):
"""Set fast piezo lock status (``"run"`` or ``"stop"``)"""
self._set_scpi_parameter("fastpiezo_ctl_status",status)
return self.get_fastpiezo_ctl_status()
[docs]
def is_fastpiezo_locked(self):
"""Check if the fast piezo is locked (output is between 5% and 95%)"""
return self.get_fastpiezo_ctl_status()=="run" and self._get_scpi_parameter("fastpiezo_ctl_locked")
[docs]
def get_fastpiezo_position(self):
"""Get fast piezo DC position between 0 and 1"""
return self._get_scpi_parameter("fastpiezo_value")
[docs]
def set_fastpiezo_position(self, value):
"""Set fast piezo DC position between 0 and 1"""
self._set_scpi_parameter("fastpiezo_value",value)
return self.get_fastpiezo_position()
[docs]
def get_fastpiezo_ctl_params(self):
"""
Get fast piezo lock control parameters.
Return tuple ``(setpoint, I, lockpoint)``.
"""
return TFastpiezoCtlParameters(*[self._get_scpi_parameter(n) for n in ["fastpiezo_ctl_setpoint","fastpiezo_ctl_I","fastpiezo_ctl_lockpoint"]])
[docs]
def set_fastpiezo_ctl_params(self, setpoint=None, I=None, lockpoint=None):
"""
Set fast piezo lock control parameters.
Any parameters which are ``None`` remain unchanged.
"""
for n,v in zip(["fastpiezo_ctl_setpoint","fastpiezo_ctl_I","fastpiezo_ctl_lockpoint"],[setpoint,I,lockpoint]):
if v is not None:
self._set_scpi_parameter(n,v)
return self.get_fastpiezo_ctl_params()
_p_refcell_wave_mode=interface.EnumParameterClass("refcell_wave_mode",{"none":"0","avg":"1","min":"2","max":"3"})
[docs]
def get_refcell_position(self):
"""Get reference cell DC position between 0 and 1"""
return self._get_scpi_parameter("refcell_value")
[docs]
def set_refcell_position(self, value):
"""Set reference cell DC position between 0 and 1"""
self._set_scpi_parameter("refcell_value",value)
return self.get_refcell_position()
[docs]
def get_scan_status(self):
"""Get scan status (``"run"`` or ``"stop"``)"""
return self._get_scpi_parameter("scan_status")
[docs]
def set_scan_status(self, status="run"):
"""Set scan status (``"run"`` or ``"stop"``)"""
self._set_scpi_parameter("scan_status",status)
return self.get_scan_status()
[docs]
def wait_scan(self, timeout=None):
"""Wait until scan is stopped"""
countdown=general.Countdown(timeout)
while self.get_scan_status()=="run":
if countdown.passed():
raise GenericSirahError("status waiting timed out")
time.sleep(1E-3)
[docs]
def get_scan_position(self):
"""Get scan position"""
return self._get_scpi_parameter("scan_value")
[docs]
def set_scan_position(self, value):
"""Set scan position"""
self._set_scpi_parameter("scan_value",value)
return self.get_scan_position()
_p_scan_device=interface.EnumParameterClass("scan_device",{"none":"0","slow_piezo":"1","ref_cell":"2"})
[docs]
def get_scan_params(self):
"""
Get scan parameters.
Return tuple ``(device, mode, lower_limit, upper_limit, rise_speed, fall_speed)``.
``device`` can be ``"none"``, ``"slow_piezo"``, or ``"ref_cell"``.
``mode`` is a tuple ``(falling, stop_lower, stop_upper)``.
"""
params=[self._get_scpi_parameter(n) for n in ["scan_device","scan_mode","scan_lowlim","scan_upplim","scan_risespd","scan_fallspd"]]
params[1]=TScanMode(*[bool(params[1]&m) for m in [0x01,0x02,0x04]])
return TScanParameters(*params)
[docs]
def set_scan_params(self, device=None, mode=None, lower_limit=None, upper_limit=None, rise_speed=None, fall_speed=None):
"""
Set slow piezo lock control parameters.
`device` can be ``"none"``, ``"slow_piezo"``, or ``"ref_cell"``.
`mode` is a tuple ``(falling, stop_lower, stop_upper)``.
Any parameters which are ``None`` remain unchanged.
"""
if isinstance(mode,(tuple,list)):
mode=sum([m for m,v in zip([0x01,0x02,0x04],mode) if v])
for n,v in zip(["scan_device","scan_mode","scan_lowlim","scan_upplim","scan_risespd","scan_fallspd"],[device,mode,lower_limit,upper_limit,rise_speed,fall_speed]):
if v is not None:
self._set_scpi_parameter(n,v)
return self.get_scan_params()