Convert to load_from_config() handling v0.2
authorW. Trevor King <wking@tremily.us>
Fri, 24 May 2013 21:31:56 +0000 (17:31 -0400)
committerW. Trevor King <wking@tremily.us>
Fri, 24 May 2013 21:31:56 +0000 (17:31 -0400)
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
unfold_protein/config.py
unfold_protein/scan.py
unfold_protein/storage.py [new file with mode: 0644]
unfold_protein/unfolder.py

index 043cb3a202cc11ec485c68ed27262efc31a1fedb..128081eecb64f679d13fc5ed20a9258943de9dcb 100755 (executable)
--- 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:
index 66fc91b0a5e5dd36f620df49650e9b3e7f6c469f..d0b137b4a543e389015ac10ae70348319b9fe217 100644 (file)
@@ -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),
         ]
index 40fe80f759bfe24660434e617e43f8a8b3e65519..1a62e94f55ad8fca0fb2ca00480dc80cf8b15a4d 100644 (file)
@@ -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 (file)
index 0000000..9b0c64b
--- /dev/null
@@ -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
index cc5977ea1ddc64318e4f0ba03a31d31f5b054387..cdec01a44f9d217fb1c36692c50978148516f310 100755 (executable)
@@ -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)