1 # Copyright (C) 2012 W. Trevor King <wking@tremily.us>
3 # This file is part of unfold_protein.
5 # unfold_protein is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation, either version 3 of the License, or (at your option) any
10 # unfold_protein is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 # You should have received a copy of the GNU General Public License along with
16 # unfold_protein. If not, see <http://www.gnu.org/licenses/>.
18 """Define `UnfoldScanner` for sequential unfolding experiments."""
20 import signal as _signal
22 import pypiezo.base as _pypiezo_base
24 from . import LOG as _LOG
25 from .unfolder import ExceptionTooFar as _ExceptionTooFar
26 from .unfolder import ExceptionTooClose as _ExceptionTooClose
28 class UnfoldScanner (object):
29 def __init__(self, config, unfolder):
31 self.unfolder = unfolder
32 self._state = {'x direction': 1}
36 _signal.signal(_signal.SIGTERM, self._handle_stop_signal)
37 for i in range(self.config['velocity']['num loops']):
38 _LOG.info('on loop {} of {}'.format(
39 i, self.config['velocity']['num loops']))
40 for velocity in self.config['velocity']['unfolding velocities']:
43 self.unfolder.config['unfold']['velocity'] = velocity
46 except _ExceptionTooFar:
47 self.stepper_approach()
48 except _ExceptionTooClose:
49 self.afm.move_far_from_surface()
50 self.stepper_approach()
52 self.position_scan_step()
54 def _handle_stop_signal(self, signal, frame):
57 def stepper_approach(self):
58 config = self.unfolder.config['approach']
59 deflection = self.unfolder.read_deflection()
60 setpoint = deflection + config['relative setpoint']
61 def_config = self.unfolder.afm.piezo.config.select_config(
62 'inputs', 'deflection')
63 setpoint_bits = _pypiezo_base.convert_volts_to_bits(
65 self.unfolder.afm.stepper_approach(target_deflection=setpoint_bits)
67 def position_scan_step(self):
69 config = self.config['position']
70 axis_config = self.unfolder.afm.piezo.config.select_config(
71 'axes', self.unfolder.afm.config['main-axis'],
72 get_attribute=_pypiezo_base.get_axis_name
74 pos = self.unfolder.afm.piezo.last_output[axis_name]
75 pos_m = _pypiezo_base.convert_bits_to_meters(axis_config, pos)
78 step = float(open('/home/wking/x-step', 'r').read())
79 _LOG.info('read step from file: {}'.format(step))
81 _LOG.warn('could not read step from file: {}'.format(e))
82 step = config['x step']
83 next_pos_m = pos_m + self._state['x direction']*step
84 if next_pos_m > config['x max']:
85 self._state['x direction'] = -1
86 next_pos_m = pos_m + self._state['x direction']*step
87 elif next_pos_m < config['x min']:
88 self._state['x direction'] = 1
89 next_pos_m = pos_m + self._state['x direction']*step
90 next_pos = _pypiezo_base.convert_meters_to_bits(
91 axis_config, next_pos_m)
92 _LOG.info('move {} from {:g} to {:g} bits'.format(
93 axis_name, pos, next_pos))
94 self.unfolder.afm.piezo.jump(axis_name, next_pos)