Source code for contrast.scans.Tweak
from ..environment import macro, MacroSyntaxError
from .Mesh import Mesh
import tty
import sys
import termios
from ..motors import all_are_motors
# constants to keep track of key buttons
KEY_UP = '\x1b[A'
KEY_DOWN = '\x1b[B'
KEY_RIGHT = '\x1b[C'
KEY_LEFT = '\x1b[D'
[docs]def getarrowkey():
"""
A function which waits for a keypress and returns one of the above
constants.
"""
ch = None
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setcbreak(sys.stdin.fileno())
ch = sys.stdin.read(3)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
if ch in (KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_LEFT):
return ch
else:
return None
[docs]@macro
class Tweak(Mesh):
"""
An interactive scan where motor positions are chosen manually for
each point. Useful for tweaking motors and reading the currently
active detectors after each step. ::
tweak <motor1> <stepsize1> [<motor2> <stepsize2>] <exp_time>
"""
def __init__(self, *args, **kwargs):
try:
exposuretime = float(args[-1])
super(Mesh, self).__init__(exposuretime)
self.motors = args[:-1:2]
self.steps = args[1::2]
self.n_positions = 1000
assert len(args) in (3, 5)
assert all_are_motors(self.motors)
except:
raise
raise MacroSyntaxError
print('\nUse the arrow keys to tweak motors and ctrl-C to stop.')
def _generate_positions(self):
positions = {m.name: m.position() for m in self.motors}
yield positions
n = 1
while n < self.n_positions:
key = getarrowkey()
imotor = 0 if key in (KEY_LEFT, KEY_RIGHT) else -1
direction = -1 if key in (KEY_DOWN, KEY_LEFT) else 1
positions[self.motors[imotor].name] \
+= direction * self.steps[imotor]
yield positions
n += 1
def _before_move(self):
# Override so as not to respect the scheduler.
pass