Source code for pylablib.devices.Thorlabs.misc

from ...core.devio import SCPI, interface
from ...core.utils import funcargparse
from .base import ThorlabsError, ThorlabsBackendError

import collections

TPMDeviceInfo=collections.namedtuple("TPMDeviceInfo",["manufacturer","name","serial","firmware"])
TPMSensorInfo=collections.namedtuple("TPMSensorInfo",["name","serial","calibration","type","subtype","flags"])
[docs] class GenericPM(SCPI.SCPIDevice): """ Generic Thorlabs optical Power Meter. Args: addr: connection address (usually, a VISA connection string or a COM port for bluetooth devices) """ Error=ThorlabsError ReraiseError=ThorlabsBackendError def __init__(self, addr): super().__init__(addr,backend_defaults={"serial":("COM1",115200)}) with self._close_on_error(): self.flush() self.write("INIT") self.update_sensor_modes() self._add_info_variable("device_info",self.get_device_info) self._add_info_variable("sensor_info",self.get_sensor_info) self._add_info_variable("supported_modes",self.get_supported_sensor_modes) self._add_settings_variable("mode",self.get_sensor_mode,self.set_sensor_mode) self._add_settings_variable("autorange",self.is_autorange_enabled,self.enable_autorange) self._add_status_variable("range",self.get_range) self._add_info_variable("wavelength_range",self.get_wavelength_range) self._add_settings_variable("wavelength",self.get_wavelength,self.set_wavelength) self._add_status_variable("reading",self.get_reading)
[docs] def open(self): super().open() self.flush()
[docs] def get_device_info(self): """ Get device info. Return tuple ``(manufacturer, name, serial, firmware)``. """ info=self.ask("*IDN?",["string"]*4) return TPMDeviceInfo(*info)
_sensor_flags=[("power",1),("energy",2),("response_set",16),("wavelength_set",32),("tau_set",64),("temp_sens",256)]
[docs] def get_sensor_info(self): """ Get sensor info. Return tuple ``(name, serial, calibration, type, subtype, flags)``. For devices with integrated sensors (e.g., PM160) the sensor name is the same as the device name. """ info=self.ask(":SYST:SENS:IDN?",["string","string","string","int","int","int"]) flags=tuple([n for (n,v) in self._sensor_flags if info[-1]&v]) return TPMSensorInfo(info[0],info[1],info[2],info[3],info[4],flags)
def _enumerate_sensor_modes(self): return [(m,c) for (m,c) in self._all_sensor_modes.items() if self._is_command_valid(":SENSE:{}:RANGE?".format(c),cached=False)]
[docs] def update_sensor_modes(self): """Update the list of supported sensor modes (only makes sense if the sensor has been changed since the connection was opened)""" self._sensor_modes=self._enumerate_sensor_modes()
_all_sensor_modes={"power":"POW","energy":"ENER","voltage":"VOLT","current":"CURR","frequency":"FREQ"} _p_sensor_mode=interface.EnumParameterClass("sensor_mode",_all_sensor_modes,value_case="upper")
[docs] def get_supported_sensor_modes(self): """ Get a list of supported sensor modes. Can contain ``"power"``, ``"energy"``, ``"voltage"``, ``"current"``, or ``"frequency"``. """ return [m for m,_ in self._sensor_modes]
def _check_sensor_mode(self, sensor_mode): if sensor_mode.upper() not in [c for _,c in self._sensor_modes]: raise ThorlabsError("mode '{}' is not available with this device; available modes are {}".format(sensor_mode,self._sensor_modes))
[docs] @interface.use_parameters(_returns="sensor_mode") def get_sensor_mode(self): """ Get current sensor mode. Can be ``"power"``, ``"energy"``, ``"voltage"``, ``"current"``, or ``"frequency"``. """ return self.ask(":CONF?")
[docs] @interface.use_parameters def set_sensor_mode(self, sensor_mode="power"): """ Set current sensor mode. Can be one of the modes returned by :meth:`get_supported_sensor_modes`. """ self._check_sensor_mode(sensor_mode) self.write(":CONF:{}".format(sensor_mode.upper())) return self.get_sensor_mode()
[docs] @interface.use_parameters def is_autorange_enabled(self, sensor_mode=None): """ Check if autorange is enabled for the given sensor mode. If `sensor_mode` is ``None``, return value for the current sensor mode. """ if sensor_mode is None: sensor_mode=self._wop.get_sensor_mode() return self.ask(":SENS:{}:RANG:AUTO?".format(sensor_mode),"bool")
[docs] def enable_autorange(self, enable=True, sensor_mode=None): """ Enable or disable autorange for the given sensor mode. If `sensor_mode` is ``None``, set value for the current sensor mode. """ if sensor_mode is None: sensor_mode=self._wop.get_sensor_mode() self.write(":SENS:{}:RANG:AUTO".format(sensor_mode),enable,"bool") return self._wip.is_autorange_enabled(sensor_mode)
[docs] @interface.use_parameters def get_range(self, sensor_mode=None): """ Get measurement range for the given sensor mode. If `sensor_mode` is ``None``, return value for the current sensor mode. """ if sensor_mode is None: sensor_mode=self._wop.get_sensor_mode() return self.ask(":SENS:{}:RANG?".format(sensor_mode),"float")
[docs] @interface.use_parameters def set_range(self, rng=None, sensor_mode=None): """ Set measurement range for the given sensor mode. If `rng` is ``None`` or ``"full"``, set the maximal range. If `sensor_mode` is ``None``, return value for the current sensor mode. """ if sensor_mode is None: sensor_mode=self._wop.get_sensor_mode() if rng is None or rng=="full": rng=self.ask(":SENS:{}:RANG? MAX".format(sensor_mode),"float")*.99 self.write(":SENS:{}:RANG".format(sensor_mode),rng,"float") return self._wip.get_range(sensor_mode)
[docs] def get_wavelength(self): """Get current wavelength (in nm)""" return self.ask(":SENS:CORR:WAV?","float")*1E-9
[docs] def get_wavelength_range(self): """Get available wavelength range (in nm)""" return (self.ask(":SENS:CORR:WAV? MIN","float")*1E-9,self.ask(":SENS:CORR:WAV? MAX","float")*1E-9)
[docs] def set_wavelength(self, wavelength): """Set current wavelength (in nm)""" self.write(":SENS:CORR:WAV",wavelength*1E9,"float") return self.get_wavelength()
_overrng_threshold=1E12
[docs] def get_reading(self, sensor_mode=None, measure=True, overrng="keep"): """ Get the reading in a given mode. If `sensor_mode` is ``None``, return reading in the currently set up mode (:meth:`get_sensor_mode`); otherwise, set the sensor mode to the requested one. If ``measure==True``, initiate a new measurement; otherwise, return the last measured value. `overrng` describes behavior if the power readings are outside of the current range; can be ``"keep"`` (keep the default device behavior, which returns a very large number, about 9.9E37), ``"error"`` (raise an error), or ``"max"`` (trim to the maximal value for the current range). """ funcargparse.check_parameter_range(overrng,"overrng",["keep","max","error"]) if sensor_mode is not None: self.set_sensor_mode(sensor_mode) comm=":READ?" if measure else ":FETCH?" value=self.ask(comm,"float") if overrng!="keep" and value>=self._overrng_threshold: if overrng=="error": raise ThorlabsError("the value is higher than the measurement range") value=self._wip.get_range(sensor_mode=sensor_mode) return value
[docs] def get_power(self): """Measure and return the optical power""" return self.get_reading(sensor_mode="power")
[docs] class PM160(GenericPM): """ Thorlabs PM160 optical Power Meter. Args: addr: connection address (usually, a VISA connection string or a COM port for bluetooth devices) """