-# Copyright (C) 2009-2011 W. Trevor King <wking@drexel.edu>
+# Copyright (C) 2011-2012 W. Trevor King <wking@tremily.us>
#
# 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 <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU General Public License along with
+# pyafm. If not, see <http://www.gnu.org/licenses/>.
"""Tools for controlling atomic force microscopes.
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
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
>>> 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
test temperature
<HDF5 dataset "units": shape (), type "|S7">
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
>>> 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:
_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'],
_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'],
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
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')
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.