本文整理汇总了Python中odemis.model.CancellableThreadPoolExecutor类的典型用法代码示例。如果您正苦于以下问题:Python CancellableThreadPoolExecutor类的具体用法?Python CancellableThreadPoolExecutor怎么用?Python CancellableThreadPoolExecutor使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了CancellableThreadPoolExecutor类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: __init__
def __init__(self, name, role, parent, axes, ranges=None, **kwargs):
assert len(axes) > 0
if ranges is None:
ranges = {}
axes_def = {}
self._position = {}
# Just z axis
a = axes[0]
# The maximum, obviously, is not 1 meter. We do not actually care
# about the range since Tescan API will adjust the value set if the
# required one is out of limits.
rng = [0, 1]
axes_def[a] = model.Axis(unit="m", range=rng)
# start at the centre
self._position[a] = parent._device.GetWD() * 1e-3
model.Actuator.__init__(self, name, role, parent=parent, axes=axes_def, **kwargs)
# RO, as to modify it the client must use .moveRel() or .moveAbs()
self.position = model.VigilantAttribute(
self._applyInversionAbs(self._position),
unit="m", readonly=True)
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
示例2: __init__
def __init__(self, name, role, parent, **kwargs):
"""
axes (set of string): names of the axes
"""
self.parent = parent
axes_def = {
# Ranges are from the documentation
"z": model.Axis(unit="m", range=(FOCUS_RANGE[0] * 1e-3, FOCUS_RANGE[1] * 1e-3)),
}
model.Actuator.__init__(self, name, role, parent=parent, axes=axes_def, **kwargs)
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
# RO, as to modify it the client must use .moveRel() or .moveAbs()
self.position = model.VigilantAttribute({},
unit="m", readonly=True)
self._updatePosition()
# Refresh regularly the position
self._pos_poll = util.RepeatingTimer(5, self._refreshPosition, "Position polling")
self._pos_poll.start()
示例3: __init__
def __init__(self, name, role, port, bands, _scan=False, **kwargs):
"""
port (string): name of the serial port to connect to. Can be a pattern,
in which case, all the ports fitting the pattern will be tried, and the
first one which looks like an FW102C will be used.
bands (dict 1<=int<=12 -> 2-tuple of floats > 0 or str):
filter position -> lower and higher bound of the wavelength (m) of the
light which goes _through_. If it's a list, it implies that the filter
is multi-band.
_scan (bool): only for internal usage
raise IOError if no device answering or not a compatible device
"""
self._ser_access = threading.Lock()
self._port = self._findDevice(port)
logging.info("Found FW102C device on port %s", self._port)
if _scan:
return
# check bands contains correct data
self._maxpos = self.GetMaxPosition()
if not bands:
raise ValueError("Argument bands must contain at least one band")
try:
for pos, band in bands.items():
if not 1 <= pos <= self._maxpos:
raise ValueError("Filter position should be between 1 and "
"%d, but got %d." % (self._maxpos, pos))
# To support "weird" filter, we accept strings
if isinstance(band, basestring):
if not band.strip():
raise ValueError("Name of filter %d is empty" % pos)
else:
driver.checkLightBand(band)
except Exception:
logging.exception("Failed to parse bands %s", bands)
raise
curpos = self.GetPosition()
if curpos not in bands:
logging.info("Current position %d is not configured, will add it", curpos)
bands[curpos] = "unknown"
axes = {"band": model.Axis(choices=bands)}
model.Actuator.__init__(self, name, role, axes=axes, **kwargs)
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "%s (serial driver: %s)" % (odemis.__version__, driver_name)
self._hwVersion = self._idn
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
self._speed = self.GetSpeed()
self.position = model.VigilantAttribute({"band": curpos}, readonly=True)
示例4: __init__
def __init__(self, name, role, children, backlash, **kwargs):
"""
children (dict str -> Stage): dict containing one component, the stage
to wrap
backlash (dict str -> float): for each axis of the stage, the additional
distance to move (and the direction). If an axis of the stage is not
present, then it’s the same as having 0 as backlash (=> no antibacklash
motion is performed for this axis)
"""
if len(children) != 1:
raise ValueError("AntiBacklashActuator needs 1 child")
for a, v in backlash.items():
if not isinstance(a, basestring):
raise ValueError("Backlash key must be a string but got '%s'" % (a,))
if not isinstance(v, numbers.Real):
raise ValueError("Backlash value of %s must be a number but got '%s'" % (a, v))
self._child = children.values()[0]
self._backlash = backlash
axes_def = {}
for an, ax in self._child.axes.items():
axes_def[an] = copy.deepcopy(ax)
axes_def[an].canUpdate = True
# Whether currently a backlash shift is applied on an axis
# If True, moving the axis by the backlash value would restore its expected position
# _shifted_lock must be taken before modifying this attribute
self._shifted = dict((a, False) for a in axes_def.keys())
self._shifted_lock = threading.Lock()
# look for axes in backlash not existing in the child
missing = set(backlash.keys()) - set(axes_def.keys())
if missing:
raise ValueError("Child actuator doesn't have the axes %s" % (missing,))
model.Actuator.__init__(self, name, role, axes=axes_def,
children=children, **kwargs)
# will take care of executing axis moves asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
# Duplicate VAs which are just identical
# TODO: shall we "hide" the antibacklash move by not updating position
# while doing this move?
self.position = self._child.position
if model.hasVA(self._child, "referenced"):
self.referenced = self._child.referenced
if model.hasVA(self._child, "speed"):
self.speed = self._child.speed
示例5: __init__
def __init__(self, name, role, positions, has_pressure=True, **kwargs):
"""
Initialises the component
positions (list of str): each pressure positions supported by the
component (among the allowed ones)
has_pressure (boolean): if True, has a pressure VA with the current
pressure.
"""
# TODO: or just provide .targetPressure (like .targetTemperature) ?
# Or maybe provide .targetPosition: position that would be reached if
# all the requested move were instantly applied?
chp = {}
for p in positions:
try:
chp[PRESSURES[p]] = p
except KeyError:
raise ValueError("Pressure position %s is unknown" % (p,))
axes = {"pressure": model.Axis(unit="Pa", choices=chp)}
model.Actuator.__init__(self, name, role, axes=axes, **kwargs)
# For simulating moves
self._position = PRESSURE_VENTED # last official position
self._goal = PRESSURE_VENTED
self._time_goal = 0 # time the goal was/will be reached
self._time_start = 0 # time the move started
# RO, as to modify it the client must use .moveRel() or .moveAbs()
self.position = model.VigilantAttribute(
{"pressure": self._position},
unit="Pa", readonly=True)
if has_pressure:
# Almost the same as position, but gives the current position
self.pressure = model.VigilantAttribute(self._position,
unit="Pa", readonly=True)
self._press_timer = util.RepeatingTimer(1, self._updatePressure,
"Simulated pressure update")
self._press_timer.start()
else:
self._press_timer = None
# Indicates whether the chamber is opened or not
# Just pretend it's always closed, and allow the user to change that
# for instance via CLI.
self.opened = model.BooleanVA(False)
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
示例6: __init__
def __init__(self, name, role, children, backlash, **kwargs):
"""
children (dict str -> Stage): dict containing one component, the stage
to wrap
backlash (dict str -> float): for each axis of the stage, the additional
distance to move (and the direction). If an axis of the stage is not
present, then it’s the same as having 0 as backlash (=> no antibacklash
motion is performed for this axis)
"""
if len(children) != 1:
raise ValueError("AntiBacklashActuator needs 1 child")
self._child = children.values()[0]
self._backlash = backlash
axes_def = self._child.axes
# look for axes in backlash not existing in the child
missing = set(backlash.keys()) - set(axes_def.keys())
if missing:
raise ValueError("Child actuator doesn't have the axes %s", missing)
model.Actuator.__init__(self, name, role, axes=axes_def,
children=children, **kwargs)
# will take care of executing axis moves asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
# Duplicate VAs which are just identical
# TODO: shall we "hide" the antibacklash move by not updating position
# while doing this move?
self.position = self._child.position
if (hasattr(self._child, "referenced") and
isinstance(self._child.referenced, model.VigilantAttributeBase)):
self.referenced = self._child.referenced
if (hasattr(self._child, "speed") and
isinstance(self._child.speed, model.VigilantAttributeBase)):
self.speed = self._child.speed
示例7: __init__
def __init__(self, name, role, port, light_name, max_power, **kwargs):
'''
port (str): port name. Can be a pattern, in which case it will pick the
first one which responds well
ligth_name (str): the name of the component that is controlled by this
power supplier
max_power (float): maximum power, in W. Will be set at initialisation.
'''
# TODO: allow to pass the serial number, to select the right device
model.PowerSupplier.__init__(self, name, role, **kwargs)
self._light_name = light_name
self._ser_access = threading.Lock()
self._port = self._findDevice(port) # sets ._serial
logging.info("Found Cobolt DPSS device on port %s", self._port)
self._sn = self.GetSerialNumber()
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "serial driver: %s" % (driver_name,)
self._hwVersion = "Cobolt DPSS (s/n: %s)" % (self._sn,)
# Reset sequence
# TODO: do a proper one. For now it's just everything we can throw, so
# that it's a bit easier to debug
self._sendCommand("ilk?")
self._sendCommand("leds?")
self._sendCommand("@cobasky?")
self._sendCommand("cf") # Clear fault
# self._sendCommand("@cob1") # used to force the laser on after interlock opened error
# will take care of executing switch asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
# Dict str -> bool: component name -> turn on/off
self.supplied = model.VigilantAttribute({light_name: False}, readonly=True)
self._updateSupplied()
self.SetOutputPower(max_power)
示例8: MultiplexActuator
class MultiplexActuator(model.Actuator):
"""
An object representing an actuator made of several (real actuators)
= a set of axes that can be moved and optionally report their position.
"""
def __init__(self, name, role, children, axes_map, ref_on_init=None, **kwargs):
"""
name (string)
role (string)
children (dict str -> actuator): axis name (in this actuator) -> actuator to be used for this axis
axes_map (dict str -> str): axis name in this actuator -> axis name in the child actuator
ref_on_init (list): axes to be referenced during initialization
"""
if not children:
raise ValueError("MultiplexActuator needs children")
if set(children.keys()) != set(axes_map.keys()):
raise ValueError("MultiplexActuator needs the same keys in children and axes_map")
ref_on_init = ref_on_init or []
self._axis_to_child = {} # axis name => (Actuator, axis name)
self._position = {}
self._speed = {}
self._referenced = {}
axes = {}
for axis, child in children.items():
caxis = axes_map[axis]
self._axis_to_child[axis] = (child, caxis)
# Ducktyping (useful to support also testing with MockComponent)
# At least, it has .axes
if not isinstance(child, model.ComponentBase):
raise ValueError("Child %s is not a component." % (child,))
if not hasattr(child, "axes") or not isinstance(child.axes, dict):
raise ValueError("Child %s is not an actuator." % child.name)
axes[axis] = copy.deepcopy(child.axes[caxis])
self._position[axis] = child.position.value[axes_map[axis]]
if model.hasVA(child, "speed") and caxis in child.speed.value:
self._speed[axis] = child.speed.value[caxis]
if model.hasVA(child, "referenced") and caxis in child.referenced.value:
self._referenced[axis] = child.referenced.value[caxis]
# this set ._axes and ._children
model.Actuator.__init__(self, name, role, axes=axes,
children=children, **kwargs)
if len(self.children.value) > 1:
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
# TODO: make use of the 'Cancellable' part (for now cancelling a running future doesn't work)
else: # Only one child => optimize by passing all requests directly
self._executor = None
# keep a reference to the subscribers so that they are not
# automatically garbage collected
self._subfun = []
children_axes = {} # dict actuator -> set of string (our axes)
for axis, (child, ca) in self._axis_to_child.items():
logging.debug("adding axis %s to child %s", axis, child.name)
if child in children_axes:
children_axes[child].add(axis)
else:
children_axes[child] = set([axis])
# position & speed: special VAs combining multiple VAs
self.position = model.VigilantAttribute(self._position, readonly=True)
for c, ax in children_axes.items():
def update_position_per_child(value, ax=ax, c=c):
logging.debug("updating position of child %s", c.name)
for a in ax:
try:
self._position[a] = value[axes_map[a]]
except KeyError:
logging.error("Child %s is not reporting position of axis %s", c.name, a)
self._updatePosition()
c.position.subscribe(update_position_per_child)
self._subfun.append(update_position_per_child)
# TODO: change the speed range to a dict of speed ranges
self.speed = model.MultiSpeedVA(self._speed, [0., 10.], setter=self._setSpeed)
for axis in self._speed.keys():
c, ca = self._axis_to_child[axis]
def update_speed_per_child(value, a=axis, ca=ca, cname=c.name):
try:
self._speed[a] = value[ca]
except KeyError:
logging.error("Child %s is not reporting speed of axis %s (%s): %s", cname, a, ca, value)
self._updateSpeed()
c.speed.subscribe(update_speed_per_child)
self._subfun.append(update_speed_per_child)
# whether the axes are referenced
self.referenced = model.VigilantAttribute(self._referenced.copy(), readonly=True)
for axis in self._referenced.keys():
c, ca = self._axis_to_child[axis]
def update_ref_per_child(value, a=axis, ca=ca, cname=c.name):
#.........这里部分代码省略.........
示例9: __init__
def __init__(self, name, role, children=None, sn=None, port=None, axis="rz",
inverted=None, positions=None, **kwargs):
"""
children (dict string->model.HwComponent): they are not actually used.
This is currently in place just to enforce PMT control to be
initialized before the Fiber Flipper since we need the relay reset
to happen before the flipper is turned on.
sn (str): serial number (recommended)
port (str): port name (only if sn is not specified)
axis (str): name of the axis
inverted (set of str): names of the axes which are inverted (IOW, either
empty or the name of the axis)
positions (None, or list of 2 tuples (value, str)): positions values and
their corresponding name. If None: 0 and Pi/2 are used, without names.
"""
if (sn is None and port is None) or (sn is not None and port is not None):
raise ValueError("sn or port argument must be specified (but not both)")
if sn is not None:
if not sn.startswith(SN_PREFIX_MFF) or len(sn) != 8:
logging.warning("Serial number '%s' is unexpected for a MFF "
"device (should be 8 digits starting with %s).",
sn, SN_PREFIX_MFF)
self._port = self._getSerialPort(sn)
self._sn = sn
else:
self._port = port
# The MFF returns no serial number from GetInfo(), so find via USB
try:
self._sn = self._getSerialNumber(port)
logging.info("Found serial number %s for device %s", self._sn, name)
except LookupError:
self._sn = None
self._serial = self._openSerialPort(self._port)
self._ser_access = threading.RLock() # reentrant, so that recovery can keep sending messages
self._recover = False
self._initHw()
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
if positions is None:
positions = ((0, None), (math.radians(90), None))
else:
if len(positions) != 2 or any(len(p) != 2 for p in positions):
raise ValueError("Positions must be exactly 2 tuples of 2 values")
# TODO: have the standard inverted Actuator functions work on enumerated axis
if inverted and axis in inverted:
positions = (positions[1], positions[0])
self._pos_to_jog = {positions[0][0]: 1,
positions[1][0]: 2}
self._status_to_pos = {STA_FWD_HLS: positions[0][0],
STA_RVS_HLS: positions[1][0]}
if positions[0][1] is None:
choices = set(p[0] for p in positions)
else:
choices = dict(positions)
# TODO: add support for speed
axes = {axis: model.Axis(unit="rad", choices=choices)}
model.Actuator.__init__(self, name, role, axes=axes, **kwargs)
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "%s (serial driver: %s)" % (odemis.__version__, driver_name)
try:
snd, modl, typ, fmv, notes, hwv, state, nc = self.GetInfo()
except IOError:
# This is the first communication with the hardware, if it fails
# it can be a sign the device is in a bad state. (it is known to
# fail when turned on and plugged in before the host computer is
# turned on)
logging.exception("GetInfo() failed.")
raise HwError("USB device with S/N %s seems in bad state. "
"Check that the Thorlabs filter flipper was "
"turned on *after* the host computer." % sn)
self._hwVersion = "%s v%d (firmware %s)" % (modl, hwv, fmv)
# It has worked at least once, so if it fails, there are hopes
self._recover = True
self.position = model.VigilantAttribute({}, readonly=True)
self._updatePosition()
示例10: DPSS
class DPSS(model.PowerSupplier):
'''
Implements the PowerSupplier class to regulate the power supply of the
Cobolt DPSS laser, connected via USB.
'''
def __init__(self, name, role, port, light_name, max_power, **kwargs):
'''
port (str): port name. Can be a pattern, in which case it will pick the
first one which responds well
ligth_name (str): the name of the component that is controlled by this
power supplier
max_power (float): maximum power, in W. Will be set at initialisation.
'''
# TODO: allow to pass the serial number, to select the right device
model.PowerSupplier.__init__(self, name, role, **kwargs)
self._light_name = light_name
self._ser_access = threading.Lock()
self._port = self._findDevice(port) # sets ._serial
logging.info("Found Cobolt DPSS device on port %s", self._port)
self._sn = self.GetSerialNumber()
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "serial driver: %s" % (driver_name,)
self._hwVersion = "Cobolt DPSS (s/n: %s)" % (self._sn,)
# Reset sequence
# TODO: do a proper one. For now it's just everything we can throw, so
# that it's a bit easier to debug
self._sendCommand("ilk?")
self._sendCommand("leds?")
self._sendCommand("@cobasky?")
self._sendCommand("cf") # Clear fault
# self._sendCommand("@cob1") # used to force the laser on after interlock opened error
# will take care of executing switch asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
# Dict str -> bool: component name -> turn on/off
self.supplied = model.VigilantAttribute({light_name: False}, readonly=True)
self._updateSupplied()
self.SetOutputPower(max_power)
# Wrapper for the actual firmware functions
def GetSerialNumber(self):
return self._sendCommand("sn?")
def SetOutputPower(self, p):
"""
p (0 < float): power in W
"""
assert 1e-6 < p < 1e6
self._sendCommand("p %.5f" % p)
def SetLaser(self, state):
"""
state (bool): True to turn on
"""
v = 1 if state else 0
self._sendCommand("l%d" % v) # No space, as they are different commands
@isasync
def supply(self, sup):
"""
Change the power supply to the defined state for each component given.
This is an asynchronous method.
sup dict(string-> boolean): name of the component and new state
returns (Future): object to control the supply request
"""
if not sup:
return model.InstantaneousFuture()
self._checkSupply(sup)
return self._executor.submit(self._doSupply, sup)
def _doSupply(self, sup):
"""
supply power
"""
for comp, val in sup.items():
self.SetLaser(val)
self._updateSupplied()
def _updateSupplied(self):
"""
update the supplied VA
"""
res = self._sendCommand("l?")
pwrd = (res == "1")
# it's read-only, so we change it via _value
self.supplied._set_value({self._light_name: pwrd}, force_write=True)
def terminate(self):
if self._executor:
self._executor.cancel()
self._executor.shutdown()
#.........这里部分代码省略.........
示例11: MFF
class MFF(model.Actuator):
"""
Represents one Thorlabs Motorized Filter Flipper (ie: MFF101 or MFF102)
"""
def __init__(self, name, role, children=None, sn=None, port=None, axis="rz",
inverted=None, positions=None, **kwargs):
"""
children (dict string->model.HwComponent): they are not actually used.
This is currently in place just to enforce PMT control to be
initialized before the Fiber Flipper since we need the relay reset
to happen before the flipper is turned on.
sn (str): serial number (recommended)
port (str): port name (only if sn is not specified)
axis (str): name of the axis
inverted (set of str): names of the axes which are inverted (IOW, either
empty or the name of the axis)
positions (None, or list of 2 tuples (value, str)): positions values and
their corresponding name. If None: 0 and Pi/2 are used, without names.
"""
if (sn is None and port is None) or (sn is not None and port is not None):
raise ValueError("sn or port argument must be specified (but not both)")
if sn is not None:
if not sn.startswith(SN_PREFIX_MFF) or len(sn) != 8:
logging.warning("Serial number '%s' is unexpected for a MFF "
"device (should be 8 digits starting with %s).",
sn, SN_PREFIX_MFF)
self._port = self._getSerialPort(sn)
self._sn = sn
else:
self._port = port
# The MFF returns no serial number from GetInfo(), so find via USB
try:
self._sn = self._getSerialNumber(port)
logging.info("Found serial number %s for device %s", self._sn, name)
except LookupError:
self._sn = None
self._serial = self._openSerialPort(self._port)
self._ser_access = threading.RLock() # reentrant, so that recovery can keep sending messages
self._recover = False
self._initHw()
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
if positions is None:
positions = ((0, None), (math.radians(90), None))
else:
if len(positions) != 2 or any(len(p) != 2 for p in positions):
raise ValueError("Positions must be exactly 2 tuples of 2 values")
# TODO: have the standard inverted Actuator functions work on enumerated axis
if inverted and axis in inverted:
positions = (positions[1], positions[0])
self._pos_to_jog = {positions[0][0]: 1,
positions[1][0]: 2}
self._status_to_pos = {STA_FWD_HLS: positions[0][0],
STA_RVS_HLS: positions[1][0]}
if positions[0][1] is None:
choices = set(p[0] for p in positions)
else:
choices = dict(positions)
# TODO: add support for speed
axes = {axis: model.Axis(unit="rad", choices=choices)}
model.Actuator.__init__(self, name, role, axes=axes, **kwargs)
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "%s (serial driver: %s)" % (odemis.__version__, driver_name)
try:
snd, modl, typ, fmv, notes, hwv, state, nc = self.GetInfo()
except IOError:
# This is the first communication with the hardware, if it fails
# it can be a sign the device is in a bad state. (it is known to
# fail when turned on and plugged in before the host computer is
# turned on)
logging.exception("GetInfo() failed.")
raise HwError("USB device with S/N %s seems in bad state. "
"Check that the Thorlabs filter flipper was "
"turned on *after* the host computer." % sn)
self._hwVersion = "%s v%d (firmware %s)" % (modl, hwv, fmv)
# It has worked at least once, so if it fails, there are hopes
self._recover = True
self.position = model.VigilantAttribute({}, readonly=True)
self._updatePosition()
# It'd be nice to know when a move is over, but it the MFF10x doesn't
# report ends of move.
# self.SendMessage(MOT_RESUME_ENDOFMOVEMSGS)
# If we need constant status updates, then, we'll need to answer them
# with MOT_ACK_DCSTATUSUPDATE at least once per second.
# For now we don't track the current device status, so it's easy.
# When requesting update messages, messages are sent at ~10Hz, even if
# no change has happened.
# self.SendMessage(HW_START_UPDATEMSGS) # Causes a lot of messages
#.........这里部分代码省略.........
示例12: __init__
def __init__(self, name, role, port, pin_map=None, delay=None, init=None, ids=None, **kwargs):
'''
port (str): port name
pin_map (dict of str -> int): names of the components
and the pin where the component is connected.
delay (dict str -> float): time to wait for each component after it is
turned on.
init (dict str -> boolean): turn on/off the corresponding component upon
initialization.
ids (list str): EEPROM ids expected to be detected during initialization.
Raise an exception if the device cannot be opened
'''
if pin_map:
self.powered = pin_map.keys()
else:
self.powered = []
model.PowerSupplier.__init__(self, name, role, **kwargs)
# TODO: catch errors and convert to HwError
self._ser_access = threading.Lock()
self._file = None
self._port = self._findDevice(port) # sets ._serial and ._file
logging.info("Found Power Control device on port %s", self._port)
# Get identification of the Power control device
self._idn = self._getIdentification()
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "serial driver: %s" % (driver_name,)
self._hwVersion = "%s" % (self._idn,)
pin_map = pin_map or {}
self._pin_map = pin_map
delay = delay or {}
# fill the missing pairs with 0 values
self._delay = dict.fromkeys(pin_map, 0)
self._delay.update(delay)
self._last_start = dict.fromkeys(self._delay, time.time())
# will take care of executing switch asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
self._supplied = {}
self.supplied = model.VigilantAttribute(self._supplied, readonly=True)
self._updateSupplied()
init = init or {}
# Remove all None's from the dict, so it can be passed as-is to _doSupply()
for k, v in init.items():
if v is None:
del init[k]
try:
self._doSupply(init, apply_delay=False)
except IOError as ex:
# This is in particular to handle some cases where the device resets
# when turning on the power. One or more trials and the
logging.exception("Failure during turning on initial power.")
raise HwError("Device error when initialising power: %s. "
"Try again or contact support if the problem persists." %
(ex,))
self.memoryIDs = model.VigilantAttribute(None, readonly=True, getter=self._getIdentities)
if ids:
mem_ids = self.memoryIDs.value
for eid in ids:
if eid not in mem_ids:
raise HwError("EEPROM id %s was not detected. Make sure "
"all EEPROM components are connected." % (eid,))
示例13: FixedPositionsActuator
class FixedPositionsActuator(model.Actuator):
"""
A generic actuator component which only allows moving to fixed positions
defined by the user upon initialization. It is actually a wrapper to just
one axis/actuator and it can also apply cyclic move e.g. in case the
actuator moves a filter wheel.
"""
def __init__(self, name, role, children, axis_name, positions, cycle=None, **kwargs):
"""
name (string)
role (string)
children (dict str -> actuator): axis name (in this actuator) -> actuator to be used for this axis
axis_name (str): axis name in the child actuator
positions (set or dict value -> str): positions where the actuator is allowed to move
cycle (float): if not None, it means the actuator does a cyclic move and this value represents a full cycle
"""
# TODO: forbid inverted
if len(children) != 1:
raise ValueError("FixedPositionsActuator needs precisely one child")
self._cycle = cycle
self._move_sum = 0
self._position = {}
self._referenced = {}
axis, child = children.items()[0]
self._axis = axis
self._child = child
self._caxis = axis_name
self._positions = positions
# Executor used to reference and move to nearest position
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
if not isinstance(child, model.ComponentBase):
raise ValueError("Child %s is not a component." % (child,))
if not hasattr(child, "axes") or not isinstance(child.axes, dict):
raise ValueError("Child %s is not an actuator." % child.name)
if cycle is not None:
# just an offset to reference switch position
self._offset = self._cycle / len(self._positions)
if not all(0 <= p < cycle for p in positions.keys()):
raise ValueError("Positions must be between 0 and %s (non inclusive)" % (cycle,))
ac = child.axes[axis_name]
axes = {axis: model.Axis(choices=positions, unit=ac.unit)} # TODO: allow the user to override the unit?
model.Actuator.__init__(self, name, role, axes=axes, children=children, **kwargs)
self._position = {}
self.position = model.VigilantAttribute({}, readonly=True)
logging.debug("Subscribing to position of child %s", child.name)
child.position.subscribe(self._update_child_position, init=True)
if model.hasVA(child, "referenced") and axis_name in child.referenced.value:
self._referenced[axis] = child.referenced.value[axis_name]
self.referenced = model.VigilantAttribute(self._referenced.copy(), readonly=True)
child.referenced.subscribe(self._update_child_ref)
# If the axis can be referenced => do it now (and move to a known position)
# In case of cyclic move always reference
if not self._referenced.get(axis, True) or (self._cycle and axis in self._referenced):
# The initialisation will not fail if the referencing fails
f = self.reference({axis})
f.add_done_callback(self._on_referenced)
else:
# If not at a known position => move to the closest known position
nearest = util.find_closest(self._child.position.value[self._caxis], self._positions.keys())
self.moveAbs({self._axis: nearest}).result()
def _on_referenced(self, future):
try:
future.result()
except Exception as e:
self._child.stop({self._caxis}) # prevent any move queued
self.state._set_value(e, force_write=True)
logging.exception(e)
def _update_child_position(self, value):
p = value[self._caxis]
if self._cycle is not None:
p %= self._cycle
self._position[self._axis] = p
self._updatePosition()
def _update_child_ref(self, value):
self._referenced[self._axis] = value[self._caxis]
self._updateReferenced()
def _updatePosition(self):
"""
update the position VA
"""
# if it is an unsupported position report the nearest supported one
real_pos = self._position[self._axis]
nearest = util.find_closest(real_pos, self._positions.keys())
if not util.almost_equal(real_pos, nearest):
logging.warning("Reporting axis %s @ %s (known position), while physical axis %s @ %s",
self._axis, nearest, self._caxis, real_pos)
#.........这里部分代码省略.........
示例14: FW102c
class FW102c(model.Actuator):
"""
Represents a Thorlabs filter wheel FW102C as an actuator.
It provides one enumerated axis, whose actual band values are provided by
the user at init.
"""
# Regex matching the compatible identification strings
re_idn = "THORLABS.*FW102C.*"
def __init__(self, name, role, port, bands, _scan=False, **kwargs):
"""
port (string): name of the serial port to connect to. Can be a pattern,
in which case, all the ports fitting the pattern will be tried, and the
first one which looks like an FW102C will be used.
bands (dict 1<=int<=12 -> 2-tuple of floats > 0 or str):
filter position -> lower and higher bound of the wavelength (m) of the
light which goes _through_. If it's a list, it implies that the filter
is multi-band.
_scan (bool): only for internal usage
raise IOError if no device answering or not a compatible device
"""
self._ser_access = threading.Lock()
self._port = self._findDevice(port)
logging.info("Found FW102C device on port %s", self._port)
if _scan:
return
# check bands contains correct data
self._maxpos = self.GetMaxPosition()
if not bands:
raise ValueError("Argument bands must contain at least one band")
try:
for pos, band in bands.items():
if not 1 <= pos <= self._maxpos:
raise ValueError("Filter position should be between 1 and "
"%d, but got %d." % (self._maxpos, pos))
# To support "weird" filter, we accept strings
if isinstance(band, basestring):
if not band.strip():
raise ValueError("Name of filter %d is empty" % pos)
else:
driver.checkLightBand(band)
except Exception:
logging.exception("Failed to parse bands %s", bands)
raise
curpos = self.GetPosition()
if curpos not in bands:
logging.info("Current position %d is not configured, will add it", curpos)
bands[curpos] = "unknown"
axes = {"band": model.Axis(choices=bands)}
model.Actuator.__init__(self, name, role, axes=axes, **kwargs)
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "%s (serial driver: %s)" % (odemis.__version__, driver_name)
self._hwVersion = self._idn
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
self._speed = self.GetSpeed()
self.position = model.VigilantAttribute({"band": curpos}, readonly=True)
def getMetadata(self):
return self._metadata
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown()
self._executor = None
with self._ser_access:
if self._serial:
self._serial.close()
self._serial = None
def _findDevice(self, ports):
"""
Look for a compatible device
ports (str): pattern for the port name
return (str): the name of the port used
It also sets ._serial and ._idn to contain the opened serial port, and
the identification string.
raises:
IOError: if no device are found
"""
if os.name == "nt":
# TODO
# ports = ["COM" + str(n) for n in range(15)]
raise NotImplementedError("Windows not supported")
else:
names = glob.glob(ports)
for n in names:
try:
self._serial = self._openSerialPort(n)
except serial.SerialException:
#.........这里部分代码省略.........
示例15: EbeamFocus
class EbeamFocus(model.Actuator):
"""
This is an extension of the model.Actuator class. It provides functions for
adjusting the ebeam focus by changing the working distance i.e. the distance
between the end of the objective and the surface of the observed specimen
"""
def __init__(self, name, role, parent, axes, ranges=None, **kwargs):
assert len(axes) > 0
if ranges is None:
ranges = {}
axes_def = {}
self._position = {}
# Just z axis
a = axes[0]
# The maximum, obviously, is not 1 meter. We do not actually care
# about the range since Tescan API will adjust the value set if the
# required one is out of limits.
rng = [0, 1]
axes_def[a] = model.Axis(unit="m", range=rng)
# start at the centre
self._position[a] = parent._device.GetWD() * 1e-3
model.Actuator.__init__(self, name, role, parent=parent, axes=axes_def, **kwargs)
# RO, as to modify it the client must use .moveRel() or .moveAbs()
self.position = model.VigilantAttribute(
self._applyInversionAbs(self._position),
unit="m", readonly=True)
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
def _updatePosition(self):
"""
update the position VA
"""
# it's read-only, so we change it via _value
self.position._value = self._applyInversionAbs(self._position)
self.position.notify(self.position.value)
def _doMove(self, pos):
"""
move to the position
"""
# Perform move through Tescan API
# Position from m to mm and inverted
self.parent._device.SetWD(self._position["z"] * 1e03)
# Obtain the finally reached position after move is performed.
with self.parent._acquisition_init_lock:
wd = self.parent._device.GetWD()
self._position["z"] = wd * 1e-3
# Changing WD results to change in fov
self.parent._scanner.updateHorizontalFOV()
self._updatePosition()
@isasync
def moveRel(self, shift):
if not shift:
return model.InstantaneousFuture()
self._checkMoveRel(shift)
shift = self._applyInversionRel(shift)
for axis, change in shift.items():
self._position[axis] += change
pos = self._position
return self._executor.submit(self._doMove, pos)
@isasync
def moveAbs(self, pos):
if not pos:
return model.InstantaneousFuture()
self._checkMoveAbs(pos)
pos = self._applyInversionAbs(pos)
for axis, new_pos in pos.items():
self._position[axis] = new_pos
pos = self._position
return self._executor.submit(self._doMove, pos)
def stop(self, axes=None):
# Empty the queue for the given axes
self._executor.cancel()
logging.warning("Stopping all axes: %s", ", ".join(self.axes))
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown()
self._executor = None