Source code for pylablib.devices.AmericanMagnetics.base

from ...core.utils import py3
from ...core.devio import SCPI, interface, comm_backend

import re

[docs] class AmericanMagneticsError(comm_backend.DeviceError): """Generic American Magnetics devices error"""
[docs] class AmericanMagneticsBackendError(AmericanMagneticsError,comm_backend.DeviceBackendError): """Generic American Magnetics backend communication error"""
[docs] class AM1700(SCPI.SCPIDevice): """ American Magnetics 1700 level monitor. Args: conn: connection parameters; usually port or a tuple containing port and baudrate for serial connection, or a network/IP address and port (if not specified, use default 7180 port) for Ethernet connection """ Error=AmericanMagneticsError ReraiseError=AmericanMagneticsBackendError _skip_empty_lines=False _relays=[1,2] def __init__(self, conn): super().__init__(conn,backend="network",term_read="\r\n",term_write="\n",backend_defaults={"serial":("COM1",115200,8,"N",1),"network":("127.0.0.1",7180)}) with self._close_on_error(): self._channel_conf={ch:self.get_channel_configuration(ch) for ch in ["HE","N2"]} if self._channel_conf["HE"]!="none": self._default_channel="He" elif self._channel_conf["N2"]!="none": self._default_channel="N2" else: self._default_channel=None channels=self.get_connected_channels() self._add_info_variable("channels",self.get_connected_channels) self._add_info_variable("configuration",lambda: dict(self._channel_conf)) self._add_settings_variable("unit",self.get_unit,self.set_unit,mux=(channels,1),ignore_error=(AmericanMagneticsError,)) self._add_status_variable("level",self.get_level,mux=(channels,),ignore_error=(AmericanMagneticsError,)) self._add_settings_variable("refill_channel",self.get_refill_channel,self.set_refill_channel) self._add_settings_variable("high_level",self.get_high_level,self.set_high_level) self._add_settings_variable("low_level",self.get_low_level,self.set_low_level) self._add_settings_variable("relay_channel",self.get_relay_channel,self.set_relay_channel,mux=(self._relays,)) self._add_settings_variable("relay_level",self.get_relay_level,self.set_relay_level,mux=(self._relays,)) self._add_settings_variable("relay_mode",self.get_relay_mode,self.set_relay_mode,mux=(self._relays,)) def _check_reply(self, reply, msg=None): reply=py3.as_str(reply).strip() if re.match(r"^-\d$",reply): err=int(reply) err_desc={-1:"LO setpoint out of range",-2:"Fill B setpoint out of range",-3:"Fill A setpoint out of range",-4:"HI setpoint out of range", -5:"Attemped to set length in percent mode",-6:"Calibration value out of range",-7:"Interval value out of range", -8:"Unrecognized command",-9:"Invalid argument",-10:"Calibration factor out of range",-11:"SCPI buffer overflow"} raise AmericanMagneticsError("request returned an error {}: {}".format(err,err_desc.get(err,"N/A"))) return True _p_channel=interface.EnumParameterClass("channel",["N2","He"],value_case="upper") _n2_kind={0:"none",1:"int_osc",2:"ext_osc"} _he_kind={0:"none",1:"4.2_40in",2:"4.2_80in",3:"2.0_40in",5:"2.0_80in"} def _norm_channel(self, channel): if channel is None: channel=self._default_channel if channel is None: raise AmericanMagneticsError("no default channel is specified, since no connected channels are found") return {"ln":"N2","lhe":"He"}.get(channel,channel).upper() def _check_channel(self, channel): channel=self._norm_channel(channel) if self._channel_conf[channel]=="none": raise AmericanMagneticsError("channel {} is not connected".format(channel)) return channel
[docs] def get_default_channel(self): """Get the default channel (``"He"``, ``"LN"``, or ``None`` if no connected channel is found)""" return self._default_channel
[docs] def get_connected_channels(self): """Get all connected channels""" return [ch for ch,c in self._channel_conf.items() if c!="none"]
[docs] @interface.use_parameters def get_channel_configuration(self, channel=None): """Get the sensor configuration for the given channel (``"He"`` or ``"LN"``); ``"none"`` means that the channel is not connected""" channel=self._norm_channel(channel) kind=self.ask("{}?".format(channel),"int") kind=(self._n2_kind if channel=="N2" else self._he_kind).get(kind,kind) return kind
_unit_aliases={"P":"perc","%":"perc","I":"inch","C":"cm"} _unit_values={"perc":0,"inch":1,"cm":2} _id_comm="SER_NUM?" def _ensure_unit(self, unit, channel): if unit is not None: unit=self._unit_values[unit] self.ask("CONF:{}:UNIT {}".format(channel,unit))
[docs] @interface.use_parameters def get_unit(self, channel=None): """Get default units (``"perc"``, ``"in"``, or ``"cm"``) on the given channel (``"He"`` or ``"LN"``)""" channel=self._check_channel(channel) unit=self.ask("{}:UNIT?".format(channel)) return self._unit_aliases.get(unit,unit)
[docs] @interface.use_parameters def set_unit(self, unit="perc", channel=None): """Set default units (``"perc"``, ``"in"``, or ``"cm"``) on the given channel (``"He"`` or ``"LN"``)""" channel=self._check_channel(channel) unit=self._unit_values[unit] self.ask("CONF:{}:UNIT {}".format(channel,unit)) return self.get_unit(channel=channel)
[docs] @interface.use_parameters def get_level(self, channel=None, unit="perc"): """Get level reading on a given channel""" channel=self._check_channel(channel) self._ensure_unit(unit,channel) return self.ask("MEAS:{}:LEVEL?".format(channel),"float")
_p_relay_channel=interface.EnumParameterClass("relay_channel",{"none":0,"N2":1,"He":2})
[docs] @interface.use_parameters(_returns="relay_channel") def get_refill_channel(self): """Get channel for autofill control (``"He"``, ``"N2"``, or ``"none"`` if disabled)""" return self.ask("FILL:CH?","int")
[docs] @interface.use_parameters(channel="relay_channel") def set_refill_channel(self, channel): """Set channel for autofill control (``"He"``, ``"N2"``, or ``"none"`` if disabled)""" self.ask("CONF:FILL:CH {}".format(channel)) return self.get_refill_channel()
[docs] @interface.use_parameters def get_low_level(self): """Get low level (automated refill start) setting in the current units""" return self.ask("B","float")
[docs] @interface.use_parameters def set_low_level(self, level): """Set low level (automated refill start) setting in the current units""" self.ask("CONF:FILL:B {:.3f}".format(level)) return self.get_low_level()
[docs] @interface.use_parameters def get_high_level(self): """Get high level (automated refill stop) setting in the current units""" return self.ask("A","float")
[docs] @interface.use_parameters def set_high_level(self, level): """Set high level (automated refill stop) setting in the current units""" self.ask("CONF:FILL:A {:.3f}".format(level)) return self.get_high_level()
_p_relay=interface.EnumParameterClass("relay",_relays)
[docs] @interface.use_parameters(_returns="relay_channel") def get_relay_channel(self, relay): """Get channel for relay (1 or 2) control (``"He"``, ``"N2"``, or ``"none"`` if disabled)""" return self.ask("RELAY{}:CH?".format(relay),"int")
[docs] @interface.use_parameters(channel="relay_channel") def set_relay_channel(self, relay, channel): """Set channel for for relay (1 or 2) control (``"He"``, ``"N2"``, or ``"none"`` if disabled)""" self.ask("CONF:RELAY{}:CH {}".format(relay,channel)) return self.get_relay_channel(relay)
[docs] @interface.use_parameters def get_relay_level(self, relay): """Get trigger level setting for a given relay (1 or 2) in the current units""" return self.ask("RELAY{}:SET?".format(relay),"float")
[docs] @interface.use_parameters def set_relay_level(self, relay, level): """Set trigger level setting for a given relay (1 or 2) in the current units""" self.ask("CONF:RELAY{}:SET {:.3f}".format(relay,level)) return self.get_relay_level(relay)
_p_relay_mode=interface.EnumParameterClass("relay_mode",{"above":0,"below":1})
[docs] @interface.use_parameters(_returns="relay_mode") def get_relay_mode(self, relay): """Get trigger level setting for a given relay (1 or 2)""" return self.ask("RELAY{}:OP?".format(relay),"int")
[docs] @interface.use_parameters(mode="relay_mode") def set_relay_mode(self, relay, mode): """Set trigger level setting for a given relay (1 or 2)""" self.ask("CONF:RELAY{}:OP {}".format(relay,mode)) return self.get_relay_mode(relay)