From e8c45d0ad87166273a281e44a03204a673a519cb Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 24 May 2013 17:31:56 -0400 Subject: [PATCH] Convert to load_from_config() handling Rather than juggling independent configurations, consolidate them under ScanConfig in the style of pyafm.storage. This makes it easy to load a full scanning config from ~/.config/unfold-default.yaml, which is a plain-text file that can easily be tweaked by hand. To generate an initial unfold-default.yaml file, try something like: >>> import unfold_protein.storage as storage >>> config = storage.get_default_config() >>> storage.save_scan_config(config=config)' which uses defaults from unfold_protein.config as well as the default AFM configuration from pyafm.storage.load_config(). --- unfold.py | 26 ++++---------- unfold_protein/config.py | 11 +++++- unfold_protein/scan.py | 21 +++++++++-- unfold_protein/storage.py | 71 ++++++++++++++++++++++++++++++++++++++ unfold_protein/unfolder.py | 25 ++++++++++---- 5 files changed, 124 insertions(+), 30 deletions(-) create mode 100644 unfold_protein/storage.py diff --git a/unfold.py b/unfold.py index 043cb3a..128081e 100755 --- a/unfold.py +++ b/unfold.py @@ -24,12 +24,8 @@ import os.path import numpy as _numpy -from pyafm.storage import load_afm as _load_afm -from pyafm.config import Kelvin as _Kelvin from unfold_protein import __version__ -from unfold_protein.unfolder import Unfolder -from unfold_protein.scan import UnfoldScanner -import unfold_protein.config as _config +import unfold_protein.storage as _storage if __name__ == '__main__': @@ -48,25 +44,15 @@ if __name__ == '__main__': args = parser.parse_args() - unfold_config = _config.UnfoldCycleConfig() - unfold_config['approach'] = _config.ApproachConfig() - unfold_config['unfold'] = _config.UnfoldConfig() - unfold_config['save'] = _config.SaveConfig() - scan_config = _config.ScanConfig() - scan_config['velocity'] = _config.VelocityScanConfig() - scan_config['position'] = _config.PositionScanConfig() - devices = [] try: - afm = _load_afm() - afm.load_from_config(devices=devices) - afm.piezo.zero() - unfolder = Unfolder(config=unfold_config, afm=afm) - scanner = UnfoldScanner(config=scan_config, unfolder=unfolder) + scanner = _storage.load_scanner() + scanner.load_from_config(devices=devices) + scanner.unfolder.afm.piezo.zero() scanner.run(stepper_tweaks=args.stepper_tweaks) finally: - afm.move_away_from_surface() - afm.piezo.zero() + scanner.unfolder.afm.move_away_from_surface() + scanner.unfolder.afm.piezo.zero() for device in devices: device.close() if args.song: diff --git a/unfold_protein/config.py b/unfold_protein/config.py index 66fc91b..d0b137b 100644 --- a/unfold_protein/config.py +++ b/unfold_protein/config.py @@ -25,6 +25,7 @@ from FFT_tools import window_hann as _window_hann import h5config.config as _config import h5config.tools as _h5config_tools import numpy as _numpy +import pyafm.config as _pyafm_config class PackageConfig (_h5config_tools.PackageConfig): @@ -108,6 +109,10 @@ class UnfoldCycleConfig (_config.Config): name='save', help='Configure saving.', config_class=SaveConfig), + _config.ConfigSetting( + name='afm', + help='Configure the AFM used for the unfolding experiments.', + config_class=_pyafm_config.AFMConfig), ] class VelocityScanConfig (_config.Config): @@ -143,7 +148,7 @@ class PositionScanConfig (_config.Config): ] class ScanConfig (_config.Config): - "Configure a full `unfold_protein` approach-bind-unfold cycle" + "Configure a series of `unfold_protein` unfolding cycles" settings = [ _config.ConfigSetting( name='velocity', @@ -153,4 +158,8 @@ class ScanConfig (_config.Config): name='position', help='Configure unfolding position scan pattern.', config_class=PositionScanConfig), + _config.ConfigSetting( + name='unfold', + help='Configure a single approach-bind-unfold cycle.', + config_class=UnfoldCycleConfig), ] diff --git a/unfold_protein/scan.py b/unfold_protein/scan.py index 40fe80f..1a62e94 100644 --- a/unfold_protein/scan.py +++ b/unfold_protein/scan.py @@ -22,15 +22,30 @@ import signal as _signal import pypiezo.base as _pypiezo_base from . import LOG as _LOG +from . import unfolder as _unfolder from .unfolder import ExceptionTooFar as _ExceptionTooFar from .unfolder import ExceptionTooClose as _ExceptionTooClose + class UnfoldScanner (object): - def __init__(self, config, unfolder): + def __init__(self, config=None, unfolder=None): self.config = config self.unfolder = unfolder self._state = {'x direction': 1} + def load_from_config(self, devices): + c = self.config # reduce verbosity + if self.unfolder is None and c['unfold']: + self.unfolder = _unfolder.Unfolder(config=c['unfold']) + self.unfolder.load_from_config(devices=devices) + + def setup_config(self): + if self.unfolder: + self.unfolder.setup_config() + self.config['unfolder'] = self.unfolder.config + else: + self.config['unfolder'] = None + def run(self, stepper_tweaks=True): self._stop = False _signal.signal(_signal.SIGTERM, self._handle_stop_signal) @@ -45,12 +60,12 @@ class UnfoldScanner (object): self.unfolder.config['unfold']['velocity'] = velocity try: self.unfolder.run() - except _ExceptionTooFar: + except _unfolder.ExceptionTooFar: if stepper_tweaks: self.stepper_approach() else: raise - except _ExceptionTooClose: + except _unfolder.ExceptionTooClose: if stepper_tweaks: self.afm.move_away_from_surface() self.stepper_approach() diff --git a/unfold_protein/storage.py b/unfold_protein/storage.py new file mode 100644 index 0000000..9b0c64b --- /dev/null +++ b/unfold_protein/storage.py @@ -0,0 +1,71 @@ +# Copyright + +import os.path as _os_path + +from h5config.storage.hdf5 import HDF5_Storage as _HDF5_Storage +from h5config.storage.yaml import YAML_Storage as _YAML_Storage +import pyafm.storage as _pyafm_storage + +from . import LOG as _LOG +from . import config as _config +from . import scan as _scan + + +DEFAULT_FILENAME = _os_path.expanduser(_os_path.join( + '~', '.config', 'unfold-default.yaml')) +DEFAULT_GROUP = '/' + + +def _get_storage(filename=None, group=None, action=None): + if filename is None: + filename = DEFAULT_FILENAME + if filename.endswith('.h5'): + if group is None: + group = DEFAULT_GROUP + assert group.endswith('/'), group + _LOG.info('{} {} {}'.format(action, filename, group)) + storage = _HDF5_Storage(filename=filename, group=group) + elif filename.endswith('.yaml'): + assert group is None, group + _LOG.info('{} {}'.format(action, filename)) + storage = _YAML_Storage(filename=filename) + else: + raise ValueError('unrecognized file extension in {}'.format(filename)) + return storage + + +def save_scan_config(config, filename=None, group=None): + storage = _get_storage( + filename=filename, group=group, + action='saving unfolding scan config to') + storage.save(config=config) + + +def load_scan_config(filename=None, group=None): + storage = _get_storage( + filename=filename, group=group, + action='loading unfolding scan config from') + config = _config.ScanConfig(storage=storage) + config.load() + return config + + +def load_scanner(filename=None, group=None): + config = load_scan_config(filename=group, group=group) + _LOG.debug( + 'constructing UnfoldScanner from configuration:\n{}'.format( + config.dump())) + scanner = _scan.UnfoldScanner(config=config) + return scanner + + +def get_default_config(): + scan_config = _config.ScanConfig() + scan_config['velocity'] = _config.VelocityScanConfig() + scan_config['position'] = _config.PositionScanConfig() + scan_config['unfold'] = _config.UnfoldCycleConfig() + scan_config['unfold']['approach'] = _config.ApproachConfig() + scan_config['unfold']['unfold'] = _config.UnfoldConfig() + scan_config['unfold']['save'] = _config.SaveConfig() + scan_config['unfold']['afm'] = _pyafm_storage.load_config() + return scan_config diff --git a/unfold_protein/unfolder.py b/unfold_protein/unfolder.py index cc5977e..cdec01a 100755 --- a/unfold_protein/unfolder.py +++ b/unfold_protein/unfolder.py @@ -23,10 +23,11 @@ import email.utils as _email_utils import os.path as _os_path import time as _time -import h5py as _h5py -import pypiezo.base as _pypiezo_base from h5config.storage.hdf5 import HDF5_Storage as _HDF5_Storage from h5config.storage.hdf5 import h5_create_group as _h5_create_group +import h5py as _h5py +import pyafm.afm as _pyafm_afm +import pypiezo.base as _pypiezo_base from . import LOG as _LOG from . import package_config as _package_config @@ -56,10 +57,24 @@ class ExceptionTooFar (Exception): class Unfolder (object): - def __init__(self, config, afm): + def __init__(self, config=None, afm=None): self.config = config self.afm = afm - self.zero_piezo() + if self.afm: + self.zero_piezo() + + def load_from_config(self, devices): + c = self.config # reduce verbosity + if self.afm is None and c['afm']: + self.afm = _pyafm_afm.AFM(config=c['afm']) + self.afm.load_from_config(devices=devices) + + def setup_config(self): + if self.afm: + self.afm.setup_config() + self.config['afm'] = self.afm.config + else: + self.config['afm'] = None def run(self): """Approach-bind-unfold-save[-plot] cycle. @@ -217,8 +232,6 @@ class Unfolder (object): storage = _HDF5_Storage() config_cwg = _h5_create_group(f, 'config') storage.save(config=self.config, group=config_cwg) - afm_piezo_cwg = _h5_create_group(config_cwg, 'afm/piezo') - storage.save(config=self.afm.piezo.config, group=afm_piezo_cwg) f['/environment/timestamp'] = timestamp x_axis_name = 'x' f['/environment/{}-position/data'.format(x_axis_name) -- 2.26.2