本文整理汇总了Python中odemis.model.CancellableThreadPoolExecutor.shutdown方法的典型用法代码示例。如果您正苦于以下问题:Python CancellableThreadPoolExecutor.shutdown方法的具体用法?Python CancellableThreadPoolExecutor.shutdown怎么用?Python CancellableThreadPoolExecutor.shutdown使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类odemis.model.CancellableThreadPoolExecutor
的用法示例。
在下文中一共展示了CancellableThreadPoolExecutor.shutdown方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: MFF
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
#.........这里部分代码省略.........
# 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
# We should make sure that the led is always off, but apparently, it's
# off by default until explicitly asking for it (cf MOD_IDENTIFY)
def terminate(self):
self._recover = False # to stop recovering if it's ongoing
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 _initHw(self):
# Ensure we don't receive anything
self.SendMessage(HW_STOP_UPDATEMSGS)
self._serial.flushInput()
# Documentation says it should be done first, though it doesn't seem
# required
self.SendMessage(HW_NO_FLASH_PROGRAMMING)
def _recoverHwError(self):
"""
Returns when the device is back online
"""
if self._serial:
self._serial.close()
self._serial = None
# keep looking for a serial port with the right serial number
while self._recover:
time.sleep(1)
try:
self._port = self._getSerialPort(self._sn)
except HwError:
logging.debug("Waiting more for the device %s to come back", self._sn)
except Exception:
示例2: DPSS
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
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()
#.........这里部分代码省略.........
示例3: AntiBacklashActuator
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
class AntiBacklashActuator(model.Actuator):
"""
This is a stage wrapper that takes a stage and ensures that every move
always finishes in the same direction.
"""
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
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown()
self._executor = None
def _antiBacklashMove(self, axes):
"""
Moves back the axes to their official position by reverting the anti-backlash shift
axes (list of str): the axes to revert
"""
sub_backlash = {} # same as backlash but only contains the axes moved
with self._shifted_lock:
for a in axes:
if self._shifted[a]:
if a in self._backlash:
sub_backlash[a] = self._backlash[a]
self._shifted[a] = False
if sub_backlash:
logging.debug("Running anti-backlash move %s", sub_backlash)
self._child.moveRelSync(sub_backlash)
def _doMoveRel(self, future, shift):
# move with the backlash subtracted
sub_shift = {}
for a, v in shift.items():
if a not in self._backlash:
sub_shift[a] = v
else:
# optimisation: if move goes in the same direction as backlash
# correction, then no need to do the correction
# TODO: only do this if backlash correction has already been applied once?
if v * self._backlash[a] >= 0:
sub_shift[a] = v
else:
with self._shifted_lock:
if self._shifted[a]:
sub_shift[a] = v
else:
sub_shift[a] = v - self._backlash[a]
self._shifted[a] = True
#.........这里部分代码省略.........
示例4: FixedPositionsActuator
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
#.........这里部分代码省略.........
update the referenced VA
"""
# .referenced is copied to detect changes to it on next update
self.referenced._set_value(self._referenced.copy(), force_write=True)
@isasync
def moveRel(self, shift):
if not shift:
return model.InstantaneousFuture()
self._checkMoveRel(shift)
raise NotImplementedError("Relative move on fixed positions axis not supported")
@isasync
def moveAbs(self, pos):
"""
Move the actuator to the defined position in m for each axis given.
pos dict(string-> float): name of the axis and position in m
"""
if not pos:
return model.InstantaneousFuture()
self._checkMoveAbs(pos)
pos = self._applyInversion(pos)
f = self._executor.submit(self._doMoveAbs, pos)
return f
def _doMoveAbs(self, pos):
axis, distance = pos.items()[0]
logging.debug("Moving axis %s (-> %s) to %g", self._axis, self._caxis, distance)
if self._cycle is None:
move = {self._caxis: distance}
self._child.moveAbs(move).result()
else:
# Optimize by moving through the closest way
cur_pos = self._child.position.value[self._caxis]
vector1 = distance - cur_pos
mod1 = vector1 % self._cycle
vector2 = cur_pos - distance
mod2 = vector2 % self._cycle
if abs(mod1) < abs(mod2):
self._move_sum += mod1
if self._move_sum >= self._cycle:
# Once we are about to complete a full cycle, reference again
# to get rid of accumulated error
self._move_sum = 0
# move to the reference switch
move_to_ref = (self._cycle - cur_pos) % self._cycle + self._offset
self._child.moveRel({self._caxis: move_to_ref}).result()
self._child.reference({self._caxis}).result()
move = {self._caxis: distance}
else:
move = {self._caxis: mod1}
else:
move = {self._caxis:-mod2}
self._move_sum -= mod2
self._child.moveRel(move).result()
def _doReference(self, axes):
logging.debug("Referencing axis %s (-> %s)", self._axis, self._caxis)
f = self._child.reference({self._caxis})
f.result()
# If we just did homing and ended up to an unsupported position, move to
# the nearest supported position
cp = self._child.position.value[self._caxis]
if (cp not in self._positions):
nearest = util.find_closest(cp, self._positions.keys())
self._doMoveAbs({self._axis: nearest})
@isasync
def reference(self, axes):
if not axes:
return model.InstantaneousFuture()
self._checkReference(axes)
f = self._executor.submit(self._doReference, axes)
return f
reference.__doc__ = model.Actuator.reference.__doc__
def stop(self, axes=None):
"""
stops the motion
axes (iterable or None): list of axes to stop, or None if all should be stopped
"""
if axes is not None:
axes = set()
if self._axis in axes:
axes.add(self._caxis)
self._child.stop(axes=axes)
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown(wait=True)
self._executor = None
self._child.position.unsubscribe(self._update_child_position)
示例5: CoupledStage
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
#.........这里部分代码省略.........
ref = {} # str (axes name) -> boolean (is referenced)
# consider an axis referenced iff it's referenced in every referenceable children
for c in self.children.value:
if not model.hasVA(c, "referenced"):
continue
cref = c.referenced.value
for a in (set(self.axes.keys()) & set(cref.keys())):
ref[a] = ref.get(a, True) and cref[a]
self.referenced._set_value(ref, force_write=True)
def _doMoveAbs(self, pos):
"""
move to the position
"""
f = self._master.moveAbs(pos)
try:
f.result()
finally: # synchronise slave position even if move failed
# TODO: Move simultaneously based on the expected position, and
# only if the final master position is different, move again.
mpos = self._master.position.value
# Move objective lens
f = self._stage_conv.moveAbs({"x": mpos["x"], "y": mpos["y"]})
f.result()
self._updatePosition()
def _doMoveRel(self, shift):
"""
move by the shift
"""
f = self._master.moveRel(shift)
try:
f.result()
finally:
mpos = self._master.position.value
# Move objective lens
f = self._stage_conv.moveAbs({"x": mpos["x"], "y": mpos["y"]})
f.result()
self._updatePosition()
@isasync
def moveRel(self, shift):
if not shift:
shift = {"x": 0, "y": 0}
self._checkMoveRel(shift)
shift = self._applyInversion(shift)
return self._executor.submit(self._doMoveRel, shift)
@isasync
def moveAbs(self, pos):
if not pos:
pos = self.position.value
self._checkMoveAbs(pos)
pos = self._applyInversion(pos)
return self._executor.submit(self._doMoveAbs, pos)
def stop(self, axes=None):
# Empty the queue for the given axes
self._executor.cancel()
self._master.stop(axes)
self._stage_conv.stop(axes)
logging.warning("Stopping all axes: %s", ", ".join(axes or self.axes))
def _doReference(self, axes):
fs = []
for c in self.children.value:
# only do the referencing for the stages that support it
if not model.hasVA(c, "referenced"):
continue
ax = axes & set(c.referenced.value.keys())
fs.append(c.reference(ax))
# wait for all referencing to be over
for f in fs:
f.result()
# Re-synchronize the 2 stages by moving the slave where the master is
mpos = self._master.position.value
f = self._stage_conv.moveAbs({"x": mpos["x"], "y": mpos["y"]})
f.result()
self._updatePosition()
@isasync
def reference(self, axes):
if not axes:
return model.InstantaneousFuture()
self._checkReference(axes)
return self._executor.submit(self._doReference, axes)
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown()
self._executor = None
示例6: MultiplexActuator
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
#.........这里部分代码省略.........
# move before we get to the next one => multi-threaded queue? Still need
# to ensure the order (ie, X>AB>X can be executed as X/AB>X or X>AB/X but
# XA>AB>X must be in the order XA>AB/X
futures = []
for child, move in self._moveToChildMove(shift).items():
f = child.moveRel(move, **kwargs)
futures.append(f)
# just wait for all futures to finish
for f in futures:
f.result()
@isasync
def moveAbs(self, pos, **kwargs):
if not pos:
return model.InstantaneousFuture()
self._checkMoveAbs(pos)
pos = self._applyInversion(pos)
if self._executor:
f = self._executor.submit(self._doMoveAbs, pos, **kwargs)
else:
cmv = self._moveToChildMove(pos)
child, move = cmv.popitem()
assert not cmv
f = child.moveAbs(move, **kwargs)
return f
def _doMoveAbs(self, pos, **kwargs):
futures = []
for child, move in self._moveToChildMove(pos).items():
f = child.moveAbs(move, **kwargs)
futures.append(f)
# just wait for all futures to finish
for f in futures:
f.result()
@isasync
def reference(self, axes):
if not axes:
return model.InstantaneousFuture()
self._checkReference(axes)
if self._executor:
f = self._executor.submit(self._doReference, axes)
else:
cmv = self._axesToChildAxes(axes)
child, a = cmv.popitem()
assert not cmv
f = child.reference(a)
return f
reference.__doc__ = model.Actuator.reference.__doc__
def _doReference(self, axes):
child_to_axes = self._axesToChildAxes(axes)
futures = []
for child, a in child_to_axes.items():
f = child.reference(a)
futures.append(f)
# just wait for all futures to finish
for f in futures:
f.result()
def stop(self, axes=None):
"""
stops the motion
axes (iterable or None): list of axes to stop, or None if all should be stopped
"""
# Empty the queue for the given axes
if self._executor:
self._executor.cancel()
all_axes = set(self.axes.keys())
axes = axes or all_axes
unknown_axes = axes - all_axes
if unknown_axes:
logging.error("Attempting to stop unknown axes: %s", ", ".join(unknown_axes))
axes &= all_axes
threads = []
for child, a in self._axesToChildAxes(axes).items():
# it's synchronous, but we want to stop all of them as soon as possible
thread = threading.Thread(name="Stopping axis", target=child.stop, args=(a,))
thread.start()
threads.append(thread)
# wait for completion
for thread in threads:
thread.join(1)
if thread.is_alive():
logging.warning("Stopping child actuator of '%s' is taking more than 1s", self.name)
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown()
self._executor = None
示例7: ChamberPressure
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
class ChamberPressure(model.Actuator):
"""
This is an extension of the model.Actuator class. It provides functions for
adjusting the chamber pressure. It actually allows the user to evacuate or
vent the chamber and get the current pressure of it.
"""
def __init__(self, name, role, parent, ranges=None, **kwargs):
axes = {"pressure": model.Axis(unit="Pa",
choices={PRESSURE_VENTED: "vented",
PRESSURE_PUMPED: "vacuum"})}
model.Actuator.__init__(self, name, role, parent=parent, axes=axes, **kwargs)
# last official position
if self.GetStatus() == 0:
self._position = PRESSURE_PUMPED
else:
self._position = PRESSURE_VENTED
# RO, as to modify it the client must use .moveRel() or .moveAbs()
self.position = model.VigilantAttribute(
{"pressure": self._position},
unit="Pa", readonly=True)
# Almost the same as position, but gives the current position
self.pressure = model.VigilantAttribute(self._position,
unit="Pa", readonly=True)
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
def GetStatus(self):
"""
return int: vacuum status,
-1 error
0 ready for operation
1 pumping in progress
2 venting in progress
3 vacuum off (pumps are switched off, valves are closed)
4 chamber open
"""
with self.parent._acquisition_init_lock:
status = self.parent._device.VacGetStatus() # channel 0, reserved
return status
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown()
self._executor = None
def _updatePosition(self):
"""
update the position VA and .pressure VA
"""
# it's read-only, so we change it via _value
pos = self.parent._device.VacGetPressure(0)
self.pressure._value = pos
self.pressure.notify(pos)
# .position contains the last known/valid position
# it's read-only, so we change it via _value
self.position._value = {"pressure": self._position}
self.position.notify(self.position.value)
@isasync
def moveRel(self, shift):
self._checkMoveRel(shift)
# convert into an absolute move
pos = {}
for a, v in shift.items:
pos[a] = self.position.value[a] + v
return self.moveAbs(pos)
@isasync
def moveAbs(self, pos):
if not pos:
return model.InstantaneousFuture()
self._checkMoveAbs(pos)
return self._executor.submit(self._changePressure, pos["pressure"])
def _changePressure(self, p):
"""
Synchronous change of the pressure
p (float): target pressure
"""
if p["pressure"] == PRESSURE_VENTED:
self.parent._device.VacVent()
else:
self.parent._device.VacPump()
start = time.time()
while not self.GetStatus() == 0:
if (time.time() - start) >= VACUUM_TIMEOUT:
raise TimeoutError("Vacuum action timed out")
# Update chamber pressure until pumping/venting process is done
self._updatePosition()
self._position = p
self._updatePosition()
#.........这里部分代码省略.........
示例8: TMCM3110
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
#.........这里部分代码省略.........
for i, a in enumerate(self._axes_names):
self._init_axis(i)
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "%s (serial driver: %s)" % (odemis.__version__, driver_name)
self._hwVersion = "TMCM-%d (firmware %d.%02d)" % (modl, vmaj, vmin)
self.position = model.VigilantAttribute({}, unit="m", readonly=True)
self._updatePosition()
# TODO: add support for changing speed. cf p.68: axis param 4 + p.81 + TMC 429 p.6
self.speed = model.VigilantAttribute({}, unit="m/s", readonly=True)
self._updateSpeed()
if refproc is not None:
# str -> boolean. Indicates whether an axis has already been referenced
axes_ref = dict([(a, False) for a in axes])
self.referenced = model.VigilantAttribute(axes_ref, readonly=True)
if temp:
# One sensor is at the top, one at the bottom of the sample holder.
# The most interesting is the temperature difference, so just
# report both.
self.temperature = model.FloatVA(0, unit=u"°C", readonly=True)
self.temperature1 = model.FloatVA(0, unit=u"°C", readonly=True)
self._temp_timer = util.RepeatingTimer(10, self._updateTemperatureVA,
"TMCM temperature update")
self._updateTemperatureVA() # make sure the temperature is correct
self._temp_timer.start()
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown(wait=True)
self._executor = None
if hasattr(self, "_temp_timer"):
self._temp_timer.cancel()
del self._temp_timer
with self._ser_access:
if self._serial:
self._serial.close()
self._serial = None
def _init_axis(self, axis):
"""
Initialise the given axis with "good" values for our needs (Delphi)
axis (int): axis number
"""
self.SetAxisParam(axis, 4, 1398) # maximum velocity to 1398 == 2 mm/s
self.SetAxisParam(axis, 5, 7) # maximum acc to 7 == 20 mm/s2
self.SetAxisParam(axis, 140, 8) # number of usteps ==2^8 =256 per fullstep
self.SetAxisParam(axis, 6, 15) # maximum RMS-current to 15 == 15/255 x 2.8 = 165mA
self.SetAxisParam(axis, 7, 0) # standby current to 0
self.SetAxisParam(axis, 204, 100) # power off after 100 ms standstill
self.SetAxisParam(axis, 154, 0) # step divider to 0 ==2^0 ==1
self.SetAxisParam(axis, 153, 0) # acc divider to 0 ==2^0 ==1
self.SetAxisParam(axis, 163, 0) # chopper mode
self.SetAxisParam(axis, 162, 2) # Chopper blank time (1 = for low current applications)
self.SetAxisParam(axis, 167, 3) # Chopper off time (2 = minimum)
self.MoveRelPos(axis, 0) # activate parameter with dummy move
if self._refproc == REFPROC_2XFF:
# set up the programs needed for the referencing
示例9: Stage
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
#.........这里部分代码省略.........
self._position = {}
rng = [-0.5, 0.5]
axes_def["x"] = model.Axis(unit="m", range=rng)
axes_def["y"] = model.Axis(unit="m", range=rng)
axes_def["z"] = model.Axis(unit="m", range=rng)
# Demand calibrated stage
if parent._device.StgIsCalibrated() !=1:
logging.warning("Stage was not calibrated. We are performing calibration now.")
parent._device.StgCalibrate()
#Wait for stage to be stable after calibration
while parent._device.StgIsBusy() != 0:
# If the stage is busy (movement is in progress), current position is
# updated approximately every 500 ms
time.sleep(0.5)
x, y, z, rot, tilt = parent._device.StgGetPosition()
self._position["x"] = -x * 1e-3
self._position["y"] = -y * 1e-3
self._position["z"] = -z * 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(
self._applyInversionAbs(self._position),
unit="m", readonly=True)
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.StgMoveTo(-pos["x"] * 1e3,
- pos["y"] * 1e3,
- pos["z"] * 1e3)
# Obtain the finally reached position after move is performed.
# This is mainly in order to keep the correct position in case the
# move we tried to perform was greater than the maximum possible
# one.
with self.parent._acquisition_init_lock:
x, y, z, rot, tilt = self.parent._device.StgGetPosition()
self._position["x"] = -x * 1e-3
self._position["y"] = -y * 1e-3
self._position["z"] = -z * 1e-3
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
示例10: EbeamFocus
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
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
示例11: PowerControlUnit
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
#.........这里部分代码省略.........
else:
# wait full time
self._last_start[comp] = time.time()
time.sleep(delay)
# Check it really worked
ans = self._sendCommand("PWR? " + str(pin))
if ans != "1":
logging.warning("Failed to turn on component %s", comp)
else:
self._sendCommand("PWR " + str(pin) + " 0")
self._updateSupplied()
def _updateSupplied(self):
"""
update the supplied VA
"""
pins_updated = set(self._pin_map.values()) # to avoid asking for the same pin multiple times
for pin in pins_updated:
ans = self._sendCommand("PWR? " + str(pin))
# Update all components that are connected to the same pin
to_update = [c for c in self.powered if pin == self._pin_map[c]]
for c_update in to_update:
self._supplied[c_update] = (ans == "1")
# it's read-only, so we change it via _value
self.supplied._value = self._supplied
self.supplied.notify(self.supplied.value)
def terminate(self):
if self._executor:
self._executor.cancel()
self._executor.shutdown()
self._executor = None
if self._serial:
with self._ser_access:
self._serial.close()
self._serial = None
if self._file:
self._file.close()
self._file = None
def _getIdentification(self):
return self._sendCommand("*IDN?")
def writeMemory(self, id, address, data):
"""
Write data to EEPROM.
id (str): EEPROM registration number #hex (little-endian format)
address (str): starting address #hex
data (str): data to be written #hex (little-endian format)
"""
self._sendCommand("WMEM %s %s %s" % (id, address, data))
def readMemory(self, id, address, length):
"""
Read data from EEPROM.
id (str): EEPROM registration number #hex (little-endian format)
address (str): starting address #hex
length (int): number of bytes to be read
returns (str): data read back #hex (little-endian format)
"""
ans = self._sendCommand("RMEM %s %s %s" % (id, address, length))
示例12: Chamber
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
class Chamber(model.Actuator):
"""
Simulated chamber component. Just pretends to be able to change pressure
"""
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
def terminate(self):
if self._press_timer:
self._press_timer.cancel()
self._press_timer = None
if self._executor:
self.stop()
self._executor.shutdown()
self._executor = None
def _updatePressure(self):
"""
update the pressure VA (called regularly from a thread)
"""
# Compute the current pressure
now = time.time()
if self._time_goal < now: # done
# goal ±5%
pos = self._goal * random.uniform(0.95, 1.05)
else:
# TODO make it logarithmic
ratio = (now - self._time_start) / (self._time_goal - self._time_start)
pos = self._position + (self._goal - self._position) * ratio
# it's read-only, so we change it via _value
self.pressure._value = pos
self.pressure.notify(pos)
def _updatePosition(self):
"""
update the position VA
"""
# .position contains the last known/valid position
# it's read-only, so we change it via _value
self.position._value = {"pressure": self._position}
self.position.notify(self.position.value)
@isasync
def moveRel(self, shift):
self._checkMoveRel(shift)
# convert into an absolute move
pos = {}
for a, v in shift.items:
pos[a] = self.position.value[a] + v
return self.moveAbs(pos)
#.........这里部分代码省略.........
示例13: PMTControl
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
class PMTControl(model.PowerSupplier):
'''
This represents the PMT control unit.
At start up the following is set:
* protection is on (=> gain is forced to 0)
* gain = 0
* power up
'''
def __init__(self, name, role, port, prot_time=1e-3, prot_curr=30e-6,
relay_cycle=None, powered=None, **kwargs):
'''
port (str): port name
prot_time (float): protection trip time (in s)
prot_curr (float): protection current threshold (in Amperes)
relay_cycle (None or 0<float): if not None, will power cycle the relay
with the given delay (in s)
powered (list of str or None): set of the HwComponents controlled by the relay
Raise an exception if the device cannot be opened
'''
if powered is None:
powered = []
self.powered = powered
model.PowerSupplier.__init__(self, name, role, **kwargs)
# get protection time (s) and current (A) properties
if not 0 <= prot_time < 1e3:
raise ValueError("prot_time should be a time (in s) but got %s" % (prot_time,))
self._prot_time = prot_time
if not 0 <= prot_curr <= 100e-6:
raise ValueError("prot_curr (%s A) is not between 0 and 100.e-6" % (prot_curr,))
self._prot_curr = prot_curr
# TODO: catch errors and convert to HwError
self._ser_access = threading.Lock()
self._port = self._findDevice(port) # sets ._serial
logging.info("Found PMT Control device on port %s", self._port)
# Get identification of the PMT control device
self._idn = self._getIdentification()
driver_name = driver.getSerialDriver(self._port)
self._swVersion = "serial driver: %s" % (driver_name,)
self._hwVersion = "%s" % (self._idn,)
# Set protection current and time
self._setProtectionCurrent(self._prot_curr)
self._setProtectionTime(self._prot_time)
# gain, powerSupply and protection VAs
self.protection = model.BooleanVA(True, setter=self._setProtection,
getter=self._getProtection)
self._setProtection(True)
gain_rng = (MIN_VOLT, MAX_VOLT)
gain = self._getGain()
self.gain = model.FloatContinuous(gain, gain_rng, unit="V",
setter=self._setGain)
self.powerSupply = model.BooleanVA(True, setter=self._setPowerSupply)
self._setPowerSupply(True)
# will take care of executing supply asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
# relay initialization
if relay_cycle is not None:
logging.info("Power cycling the relay for %f s", relay_cycle)
self.setRelay(False)
time.sleep(relay_cycle)
# Reset if no powered provided
if not powered:
self.setRelay(True)
else:
self._supplied = {}
self.supplied = model.VigilantAttribute(self._supplied, readonly=True)
self._updateSupplied()
def terminate(self):
if self._executor:
self._executor.cancel()
self._executor.shutdown()
self._executor = None
with self._ser_access:
if self._serial:
self._serial.close()
self._serial = None
@isasync
def supply(self, sup):
if not sup:
return model.InstantaneousFuture()
self._checkSupply(sup)
return self._executor.submit(self._doSupply, sup)
def _doSupply(self, sup):
"""
#.........这里部分代码省略.........
示例14: SpectraPro
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
#.........这里部分代码省略.........
def _doSetGrating(self, g, wl=None):
"""
Setter for the grating VA.
g (1<=int<=3): the new grating
wl (None or float): wavelength to set afterwards. If None, will put the
same wavelength as before the change of grating.
returns the actual new grating
Warning: synchronous until the grating is finished (up to 20s)
"""
try:
with self._ser_access:
if wl is None:
wl = self.position.value["wavelength"]
self.SetGrating(g)
self._setCalibratedWavelength(wl)
except Exception:
logging.exception("Failed to change grating to %d", g)
raise
self._updatePosition()
def stop(self, axes=None):
"""
stops the motion
Warning: Only not yet-executed moves can be cancelled, this hardware
doesn't support stopping while a move is going on.
"""
self._executor.cancel()
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown()
self._executor = None
if self._serial:
self._serial.close()
self._serial = None
def getPixelToWavelength(self, npixels, pxs):
"""
Return the lookup table pixel number of the CCD -> wavelength observed.
npixels (1 <= int): number of pixels on the CCD (horizontally), after
binning.
pxs (0 < float): pixel size in m (after binning)
return (list of floats): pixel number -> wavelength in m
"""
centerpixel = (npixels - 1) / 2
cw = self.position.value["wavelength"] # m
gid = self.position.value["grating"]
gl = self._getGrooveDensity(gid)
ca, sa, fl, ia, da = self._calib[gid]
# Formula based on the Winspec documentation:
# "Equations used in WinSpec Wavelength Calibration", p. 257 of the manual
# ftp://ftp.piacton.com/Public/Manuals/Princeton%20Instruments/WinSpec%202.6%20Spectroscopy%20Software%20User%20Manual.pdf
# Converted to code by Benjamin Brenny (from AMOLF)
G = math.asin(cw / (math.cos(ia / 2) * 2 / gl))
wllist = []
for i in range(npixels):
pxd = pxs * (i - centerpixel) # distance of pixel to sensor centre
E = math.atan((pxd * math.cos(da)) / (fl + pxd * math.sin(da)))
wl = (math.sin(G - ia / 2) + math.sin(G + ia / 2 + E)) / gl
wllist.append(wl)
示例15: PM8742
# 需要导入模块: from odemis.model import CancellableThreadPoolExecutor [as 别名]
# 或者: from odemis.model.CancellableThreadPoolExecutor import shutdown [as 别名]
class PM8742(model.Actuator):
"""
Represents one New Focus picomotor controller 8742.
"""
def __init__(self, name, role, address, axes, stepsize, sn=None, **kwargs):
"""
address (str): ip address (use "autoip" to automatically scan and find the
controller, "fake" for a simulator)
axes (list of str): names of the axes, from the 1st to the 4th, if present.
if an axis is not connected, put a "".
stepsize (list of float): size of a step in m (the smaller, the
bigger will be a move for a given distance in m)
sn (str or None): serial number of the device (eg, "11500"). If None, the
driver will use whichever controller is first found.
inverted (set of str): names of the axes which are inverted (IOW, either
empty or the name of the axis)
"""
if not 1 <= len(axes) <= 4:
raise ValueError("Axes must be a list of 1 to 4 axis names (got %s)" % (axes,))
if len(axes) != len(stepsize):
raise ValueError("Expecting %d stepsize (got %s)" %
(len(axes), stepsize))
self._name_to_axis = {} # str -> int: name -> axis number
for i, n in enumerate(axes):
if n == "": # skip this non-connected axis
continue
self._name_to_axis[n] = i + 1
for sz in stepsize:
if sz > 10e-3: # sz is typically ~1µm, so > 1 cm is very fishy
raise ValueError("stepsize should be in meter, but got %g" % (sz,))
self._stepsize = stepsize
self._address = address
self._sn = sn
self._accesser = self._openConnection(address, sn)
self._recover = False
self._resynchonise()
if name is None and role is None: # For scan only
return
# Seems to really be the device, so handle connection errors fully
self._recover = True
modl, fw, sn = self.GetIdentification()
if modl != "8742":
logging.warning("Controller %s is not supported, will try anyway", modl)
# will take care of executing axis move asynchronously
self._executor = CancellableThreadPoolExecutor(max_workers=1) # one task at a time
# Let the controller check the actuators are connected
self.MotorCheck()
axes_def = {}
speed = {}
for n, i in self._name_to_axis.items():
sz = self._stepsize[i - 1]
# TODO: allow to pass the range in m in the arguments
# Position supports ±2³¹, probably not that much in reality, but
# there is no info.
rng = [(-2 ** 31) * sz, (2 ** 31 - 1) * sz]
# Check the actuator is connected
mt = self.GetMotorType(i)
if mt in {MT_NONE, MT_UNKNOWN}:
raise HwError("Controller failed to detect motor %d, check the "
"actuator is connected to the controller" %
(i,))
max_stp_s = {MT_STANDARD: 2000, MT_TINY: 1750}[mt]
srng = (0, self._speedToMS(i, max_stp_s))
speed[n] = self._speedToMS(i, self.GetVelocity(i))
axes_def[n] = model.Axis(range=rng, speed=srng, unit="m")
model.Actuator.__init__(self, name, role, axes=axes_def, **kwargs)
self._swVersion = "%s (IP connection)" % (odemis.__version__,)
self._hwVersion = "New Focus %s (firmware %s, S/N %s)" % (modl, fw, sn)
# Note that the "0" position is just the position at which the
# controller turned on
self.position = model.VigilantAttribute({}, unit="m", readonly=True)
self._updatePosition()
max_speed = max(a.speed[1] for a in axes_def.values())
self.speed = model.MultiSpeedVA(speed, range=(0, max_speed),
unit="m/s", setter=self._setSpeed)
def terminate(self):
if self._executor:
self.stop()
self._executor.shutdown(wait=True)
self._executor = None
if self._accesser:
self._accesser.terminate()
self._accesser = None
#.........这里部分代码省略.........