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}
34 def run(self, stepper_tweaks=True):
36 _signal.signal(_signal.SIGTERM, self._handle_stop_signal)
37 self.unfolder.afm.move_away_from_surface()
38 self.stepper_approach()
39 for i in range(self.config['velocity']['num loops']):
40 _LOG.info('on loop {} of {}'.format(
41 i, self.config['velocity']['num loops']))
42 for velocity in self.config['velocity']['unfolding velocities']:
45 self.unfolder.config['unfold']['velocity'] = velocity
48 except _ExceptionTooFar:
50 self.stepper_approach()
53 except _ExceptionTooClose:
55 self.afm.move_away_from_surface()
56 self.stepper_approach()
60 self.position_scan_step()
62 def _handle_stop_signal(self, signal, frame):
65 def stepper_approach(self):
66 config = self.unfolder.config['approach']
67 deflection = self.unfolder.read_deflection()
68 setpoint = deflection + config['relative setpoint']
69 def_config = self.unfolder.afm.piezo.config.select_config(
70 'inputs', 'deflection')
71 setpoint_bits = _pypiezo_base.convert_volts_to_bits(
73 self.unfolder.afm.stepper_approach(target_deflection=setpoint_bits)
75 def position_scan_step(self):
77 config = self.config['position']
78 axis_config = self.unfolder.afm.piezo.config.select_config(
79 'axes', self.unfolder.afm.config['main-axis'],
80 get_attribute=_pypiezo_base.get_axis_name
82 pos = self.unfolder.afm.piezo.last_output[axis_name]
83 pos_m = _pypiezo_base.convert_bits_to_meters(axis_config, pos)
86 step = float(open('/home/wking/x-step', 'r').read())
87 _LOG.info('read step from file: {}'.format(step))
89 _LOG.warn('could not read step from file: {}'.format(e))
90 step = config['x step']
91 next_pos_m = pos_m + self._state['x direction']*step
92 if next_pos_m > config['x max']:
93 self._state['x direction'] = -1
94 next_pos_m = pos_m + self._state['x direction']*step
95 elif next_pos_m < config['x min']:
96 self._state['x direction'] = 1
97 next_pos_m = pos_m + self._state['x direction']*step
98 next_pos = _pypiezo_base.convert_meters_to_bits(
99 axis_config, next_pos_m)
100 _LOG.info('move {} from {:g} to {:g} bits'.format(
101 axis_name, pos, next_pos))
102 self.unfolder.afm.piezo.jump(axis_name, next_pos)