X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=pyafm%2Fafm.py;h=fc8dacbefc4f3d8e37c2776241e3206e6016b7dd;hb=ec18beb90683ee76713c74bf5749234596a8747e;hp=dd6d2396a2e2bc95a110949e39a4c8e651654f70;hpb=c5e246b40f97558bfdfdffd5c98394fe30cc9dca;p=pyafm.git diff --git a/pyafm/afm.py b/pyafm/afm.py index dd6d239..fc8dacb 100644 --- a/pyafm/afm.py +++ b/pyafm/afm.py @@ -1,19 +1,18 @@ -# Copyright (C) 2009-2011 W. Trevor King +# Copyright (C) 2011-2012 W. Trevor King # # This file is part of pyafm. # -# pyafm is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. +# pyafm is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. # -# pyafm is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# pyafm is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. # -# You should have received a copy of the GNU General Public License -# along with pyafm. If not, see . +# You should have received a copy of the GNU General Public License along with +# pyafm. If not, see . """Tools for controlling atomic force microscopes. @@ -23,6 +22,14 @@ for controlling the piezo (`pypiezo`) and stepper (`stepper`), this module only contains methods that require the capabilities of both. """ +try: + import matplotlib as _matplotlib + import matplotlib.pyplot as _matplotlib_pyplot + import time as _time # for timestamping lines on plots +except (ImportError, RuntimeError), e: + _matplotlib = None + _matplotlib_import_error = e + from pypiezo.afm import AFMPiezo as _AFMPiezo from pypiezo.base import convert_bits_to_meters as _convert_bits_to_meters from pypiezo.base import convert_meters_to_bits as _convert_meters_to_bits @@ -31,6 +38,7 @@ from pypiezo.surface import FlatFit as _FlatFit from pypiezo.surface import SurfaceError as _SurfaceError from . import LOG as _LOG +from . import package_config as _package_config from .stepper import Stepper as _Stepper from .temperature import Temperature as _Temperature @@ -81,7 +89,8 @@ class AFM (object): >>> config['temperature'] = pyafm.config.TemperatureConfig() >>> config['temperature']['name'] = 'test temperature' - >>> afm = AFM(config=config, devices=devices) + >>> afm = AFM(config=config) + >>> afm.load_from_config(devices=devices) >>> afm.setup_config() >>> afm.get_temperature() # doctest: +SKIP @@ -260,7 +269,8 @@ class AFM (object): test temperature Celsius - >>> afm2 = pyafm.storage.load_afm(filename=filename, devices=devices) + >>> afm2 = pyafm.storage.load_afm(filename=filename) + >>> afm2.load_from_config(devices=devices) >>> afm2.get_temperature() # doctest: +SKIP 297.37 @@ -274,22 +284,23 @@ class AFM (object): >>> os.remove(filename) """ - def __init__(self, config, piezo=None, stepper=None, temperature=None, - devices=None): + def __init__(self, config, piezo=None, stepper=None, temperature=None): self.config = config self.piezo = piezo self.stepper = stepper self.temperature = temperature - self.load_from_config(devices=devices) def load_from_config(self, devices): c = self.config # reduce verbosity if self.piezo is None and c['piezo']: - self.piezo = _AFMPiezo(config=c['piezo'], devices=devices) + self.piezo = _AFMPiezo(config=c['piezo']) + self.piezo.load_from_config(devices=devices) if self.stepper is None and c['stepper']: - self.stepper = _Stepper(config=c['stepper'], devices=devices) + self.stepper = _Stepper(config=c['stepper']) + self.stepper.load_from_config(devices=devices) if self.temperature is None and c['temperature']: self.temperature = _Temperature(config=c['temperature']) + self.temperature.load_from_config() def setup_config(self): if self.piezo: @@ -373,8 +384,8 @@ class AFM (object): _LOG.debug('fine tune the stepper position') while pos_m < -stepper_tolerance: # step back if we need to - _LOG.debug('step back') self.stepper.single_step(-1) + _LOG.debug('step back to {}'.format(self.stepper.position)) try: pos = self.piezo.get_surface_position( axis_name=self.config['main-axis'], @@ -387,8 +398,8 @@ class AFM (object): _LOG.debug('located surface at stepper %d, piezo %d (%g m)' % (self.stepper.position, pos, pos_m)) while pos_m > stepper_tolerance: # step forward if we need to - _LOG.debug('step forward') self.stepper.single_step(1) + _LOG.debug('step forward to {}'.format(self.stepper.position)) try: pos = self.piezo.get_surface_position( axis_name=self.config['main-axis'], @@ -444,6 +455,7 @@ class AFM (object): except _SurfaceError, e: _LOG.info(e) self.stepper.single_step(-1) # step out + _LOG.debug('stepped back to {}'.format(self.stepper.position)) _LOG.debug('giving up on finding the surface') _LOG.warn(e) raise e @@ -451,6 +463,10 @@ class AFM (object): def stepper_approach(self, target_deflection): _LOG.info('approach with stepper until deflection > {}'.format( target_deflection)) + record_data = _package_config['matplotlib'] + if record_data: + position = [] + deflection = [] self._check_target_deflection(deflection=target_deflection) cd = self.piezo.read_deflection() # cd = current deflection in bits _LOG.debug('single stepping approach') @@ -459,6 +475,20 @@ class AFM (object): cd, target_deflection)) self.stepper.single_step(1) # step in cd = self.piezo.read_deflection() + if record_data: + position.append(self.stepper.position) + deflection.append(cd) + if _package_config['matplotlib']: + figure = _matplotlib_pyplot.figure() + axes = figure.add_subplot(1, 1, 1) + axes.hold(False) + timestamp = _time.strftime('%H-%M-%S') + axes.set_title('stepper approach {}'.format(timestamp)) + plot = axes.plot(position, deflection, 'b.-') + figure.canvas.draw() + figure.show() + if not _matplotlib.is_interactive(): + _matplotlib_pyplot.show() def move_toward_surface(self, distance): """Step in approximately `distance` meters.