From e3413657a1bd05ac960ab986a0062e2bd89aff81 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 15 Sep 2011 08:18:39 -0400 Subject: [PATCH] Restructure and convert to new, nestable h5config. --- pyafm/__init__.py | 24 ++++++++++ pyafm.py => pyafm/afm.py | 94 ++++++++++++++++++++++------------------ pyafm/config.py | 26 +++++++++++ 3 files changed, 101 insertions(+), 43 deletions(-) create mode 100644 pyafm/__init__.py rename pyafm.py => pyafm/afm.py (69%) create mode 100644 pyafm/config.py diff --git a/pyafm/__init__.py b/pyafm/__init__.py new file mode 100644 index 0000000..c6e5737 --- /dev/null +++ b/pyafm/__init__.py @@ -0,0 +1,24 @@ +# Copyright (C) 2009-2011 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 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 . + +from .config import PackageConfig as _PackageConfig + + +__version__ = '0.3' + +package_config = _PackageConfig(package_name=__name__) +package_config.load_system() diff --git a/pyafm.py b/pyafm/afm.py similarity index 69% rename from pyafm.py rename to pyafm/afm.py index b78284f..940c216 100644 --- a/pyafm.py +++ b/pyafm/afm.py @@ -1,3 +1,20 @@ +# Copyright (C) 2009-2011 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 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 . + """Tools for controlling atomic force microscopes. Provides control of AFM postition using both short-range (piezo) and @@ -6,27 +23,18 @@ for controlling the piezo (`pypiezo`) and stepper (`stepper`), this module only contains methods that require the capabilities of both. """ -import logging as _logging - -from pypiezo.base import convert_volts_to_bits as _convert_volts_to_bits -from pypiezo.base import convert_meters_to_bits as _convert_meters_to_bits -from pypiezo.base import convert_bits_to_meters as _convert_bits_to_meters -from pypiezo.surface import SurfaceError as _SurfaceError -from pypiezo.surface import FlatFit as _FlatFit - - -__version__ = '0.1' - - -LOG = _logging.getLogger('pyafm') -"pyafm logger" - -LOG.setLevel(_logging.DEBUG) -h = _logging.StreamHandler() -f = _logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") -h.setFormatter(f) -LOG.addHandler(h) -del h, f +from pycomedi.device import Device +from pycomedi.subdevice import StreamingSubdevice +from pycomedi.channel import AnalogChannel, DigitalChannel +from pycomedi.constant import AREF, IO_DIRECTION, SUBDEVICE_TYPE, UNIT +from pypiezo.afm import AFMPiezo +from pypiezo.base import PiezoAxis, InputChannel +from pypiezo.config import HDF5_ChannelConfig, HDF5_AxisConfig, pprint_HDF5 +from stepper import Stepper +from pyafm import AFM +from pypid.controller import Controller +from pypid.backend import get_backend +from . import LOG as _LOG class AFM (object): @@ -74,7 +82,7 @@ class AFM (object): moving the zpiezo) until deflection voltage is greater than `setpoint`. """ - LOG.info('moving to %g onto the surface' % depth) + _LOG.info('moving to %g onto the surface' % depth) stepper_tolerance = 2*self.stepper.step_size @@ -83,92 +91,92 @@ class AFM (object): zero = _convert_volts_to_bits(axis.axis_channel_config, 0) target_def = _convert_volts_to_bits(axis.axis_channel_config, setpoint) - LOG.debug('zero the %s piezo output' % self.axis_name) + _LOG.debug('zero the %s piezo output' % self.axis_name) self.piezo.jump(axis_name=self.axis_name, position=zero) - LOG.debug("see if we're starting near the surface") + _LOG.debug("see if we're starting near the surface") try: pos = self.piezo.get_surface_position( axis_name=self.axis_name, max_deflection=target_def) except _FlatFit, e: - LOG.info(e) + _LOG.info(e) pos = self._stepper_approach_again( target_deflection=target_def, far=far) except _SurfaceError, e: - LOG.info(e) + _LOG.info(e) pos = self._stepper_approach_again( target_deflection=target_def, far=far) pos_m = _convert_bits_to_meters( axis.axis_channel_config, axis.axis_config, pos) - LOG.debug('located surface at stepper %d, piezo %d (%g m)' + _LOG.debug('located surface at stepper %d, piezo %d (%g m)' % (self.stepper.position, pos, pos_m)) - LOG.debug('fine tune the stepper position') + _LOG.debug('fine tune the stepper position') while pos_m < -stepper_tolerance: # step back if we need to - LOG.debug('step back') + _LOG.debug('step back') self.stepper.step_relative(-1, backlash_safe=True) try: pos = self.piezo.get_surface_position( axis_name=self.axis_name, max_deflection=target_def) except _FlatFit, e: - LOG.debug(e) + _LOG.debug(e) continue pos_m = _convert_bits_to_meters( axis.axis_channel_config, axis.axis_config, pos) - LOG.debug('located surface at stepper %d, piezo %d (%g m)' + _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') + _LOG.debug('step forward') self.stepper.step_relative(1) try: pos = self.piezo.get_surface_position( axis_name=self.axis_name, max_deflection=target_def) except _FlatFit, e: - LOG.debug(e) + _LOG.debug(e) continue pos_m = _convert_bits_to_meters( axis.axis_channel_config, axis.axis_config, pos) - LOG.debug('located surface at stepper %d, piezo %d (%g m)' + _LOG.debug('located surface at stepper %d, piezo %d (%g m)' % (self.stepper.position, pos, pos_m)) - LOG.debug('adjust the %s piezo to place us just onto the surface' + _LOG.debug('adjust the %s piezo to place us just onto the surface' % self.axis_name) target_m = pos_m + depth target = _convert_meters_to_bits( axis.axis_channel_config, axis.axis_config, target_m) self.piezo.jump(self.axis_name, target) - LOG.debug( + _LOG.debug( 'positioned %g m into the surface at stepper %d, piezo %d (%g m)' % (depth, self.stepper.position, target, target_m)) def _stepper_approach_again(self, target_deflection, far): - LOG.info('back off %d half steps and approach until deflection > %g' + _LOG.info('back off %d half steps and approach until deflection > %g' % (far, target_deflection)) # back away self.stepper.step_relative(-far, backlash_safe=True) cd = self.piezo.read_deflection() # cd = current deflection in bits - LOG.debug('single stepping approach') + _LOG.debug('single stepping approach') while cd < target_deflection: - LOG.debug('deflection %g < setpoint %g. step closer' + _LOG.debug('deflection %g < setpoint %g. step closer' % (cd, target_deflection)) self.stepper.single_step(1) # step in cd = self.piezo.read_deflection() for i in range(2*max(1, self.stepper.backlash)): - LOG.debug( + _LOG.debug( 'additional surface location attempt (stepping backwards)') try: pos = self.piezo.get_surface_position( axis_name=self.axis_name, max_deflection=target_deflection) return pos except _SurfaceError, e: - LOG.info(e) + _LOG.info(e) self.stepper.single_step(-1) # step out - LOG.debug('giving up on finding the surface') - LOG.warn(e) + _LOG.debug('giving up on finding the surface') + _LOG.warn(e) raise e diff --git a/pyafm/config.py b/pyafm/config.py new file mode 100644 index 0000000..81b9364 --- /dev/null +++ b/pyafm/config.py @@ -0,0 +1,26 @@ +# Copyright (C) 2011 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 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 . + +"AFM configuration" + +import h5config.config as _config +import h5config.tools as _h5config_tools + + +class PackageConfig (_h5config_tools.PackageConfig): + "Configure `pyafm` module operation" + pass -- 2.26.2