From 277131b4942c353fbecaf30d944e1bd4360511ef Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 30 Sep 2011 14:36:22 -0400 Subject: [PATCH] Fix problems with the transition to the new nested-Config h5config package. Also restore BumpConfig's `initial-position` setting, since it's critical to running a bump. I removed it when I mistakenly thought it was storeing the output voltage used as the initial position (something that you'd measure during a bump). I guess I should have read the help string before I deleted it ;). There are also a number of numpy array -> float conversions when loading HDF5. This avoids excessive numpy-fication with h5py v2.0. --- calibcant/T_analyze.py | 5 +- calibcant/analyze.py | 13 ++-- calibcant/bump.py | 128 ++++++++++++++++++++++++------- calibcant/bump_analyze.py | 9 ++- calibcant/calibrate.py | 153 +++++++++++++++++++++++++++++++++----- calibcant/config.py | 9 ++- calibcant/vib.py | 62 +++++++-------- calibcant/vib_analyze.py | 2 +- 8 files changed, 291 insertions(+), 90 deletions(-) diff --git a/calibcant/T_analyze.py b/calibcant/T_analyze.py index d03bf4d..f7a92e3 100644 --- a/calibcant/T_analyze.py +++ b/calibcant/T_analyze.py @@ -115,9 +115,10 @@ def T_save(filename, group='/', raw_T=None, temperature_config=None, except KeyError: pass cwg['raw'] = raw_T - if temperature_config: + if temperature_config is not None: config_cwg = _h5_create_group(cwg, 'config') - temperature_config.save(group=config_cwg) + storage = _HDF5_Storage() + storage.save(config=temperature_config, group=config_cwg) if processed_T is not None: try: del cwg['processed'] diff --git a/calibcant/analyze.py b/calibcant/analyze.py index e29d6c7..dcfc747 100644 --- a/calibcant/analyze.py +++ b/calibcant/analyze.py @@ -234,7 +234,8 @@ def calib_save(filename, group='/', bumps=None, temperatures=None, cwg = _h5_create_group(f, group) if calibration_config is not None: config_cwg = _h5_create_group(cwg, 'config') - calibration_config.save(group=config_cwg) + storage = _HDF5_Storage() + storage.save(config=calibration_config, group=config_cwg) if bumps is not None: try: del cwg['raw/photodiode-sensitivity/data'] @@ -304,11 +305,12 @@ def calib_load(filename, group='/'): except KeyError: pass try: - k = f[group+'processed/spring-constant/data'][...] + k = float(f[group+'processed/spring-constant/data'][...]) except KeyError: pass try: - k_s = f[group+'processed/spring-constant/standard-deviation'][...] + k_s = float( + f[group+'processed/spring-constant/standard-deviation'][...]) except KeyError: pass calibration_config = _CalibrationConfig(storage=_HDF5_Storage( @@ -345,13 +347,12 @@ def calib_load_all(filename, group='/'): filename, group+'calibration/') bump_details = [] for i in range(calibration_config['num-bumps']): - (raw_bump,bump_config,z_channel_config,z_axis_config, - deflection_channel_config,processed_bump) = _bump_load( + (raw_bump,bump_config,z_axis_config,deflection_channel_config, + processed_bump) = _bump_load( filename=filename, group='%sbump/%d/' % (group, i)) bump_details.append({ 'raw_bump': raw_bump, 'bump_config': bump_config, - 'z_channel_config': z_channel_config, 'z_axis_config': z_axis_config, 'deflection_channel_config': deflection_channel_config, 'processed_bump': processed_bump, diff --git a/calibcant/bump.py b/calibcant/bump.py index 1e2a5b0..90a4b92 100644 --- a/calibcant/bump.py +++ b/calibcant/bump.py @@ -87,6 +87,7 @@ def bump_acquire(afm, bump_config): """ afm.move_just_onto_surface( depth=bump_config['initial-position'], far=bump_config['far-steps']) + #afm.piezo.jump('z', 32000) _LOG.info('bump the surface to a depth of %g m' % bump_config['push-depth']) @@ -94,11 +95,9 @@ def bump_acquire(afm, bump_config): axis = afm.piezo.axis_by_name(afm.axis_name) start_pos = afm.piezo.last_output[afm.axis_name] - start_pos_m = _convert_bits_to_meters( - axis.axis_channel_config, axis.axis_config, start_pos) + start_pos_m = _convert_bits_to_meters(axis.config, start_pos) close_pos_m = start_pos_m + bump_config['push-depth'] - close_pos = _convert_meters_to_bits( - axis.axis_channel_config, axis.axis_config, close_pos_m) + close_pos = _convert_meters_to_bits(axis.config, close_pos_m) dtype = afm.piezo.channel_dtype(afm.axis_name, direction='output') appr = _numpy.linspace( @@ -123,7 +122,7 @@ def bump(afm, bump_config, filename, group='/'): >>> import os >>> import tempfile - >>> from h5config.storage.hdf5 import HDF5_Storage, pprint_HDF5 + >>> from h5config.storage.hdf5 import pprint_HDF5 >>> from pycomedi.device import Device >>> from pycomedi.subdevice import StreamingSubdevice >>> from pycomedi.channel import AnalogChannel, DigitalChannel @@ -132,7 +131,7 @@ def bump(afm, bump_config, filename, group='/'): >>> from pypiezo.base import PiezoAxis, InputChannel >>> from pypiezo.config import ChannelConfig, AxisConfig >>> from stepper import Stepper - >>> from pyafm import AFM + >>> from pyafm.afm import AFM >>> from .config import BumpConfig >>> fd,filename = tempfile.mkstemp(suffix='.h5', prefix='calibcant-') @@ -161,26 +160,22 @@ def bump(afm, bump_config, filename, group='/'): first few surface approaching steps, which could lead to an `EdgeKink` error instead of a `FlatFit` error. - >>> axis_config = AxisConfig(storage=HDF5_Storage( - ... filename=filename, group='/bump/config/z/axis')) + >>> axis_config = AxisConfig() >>> axis_config.update( ... {'gain':20, 'sensitivity':8e-9, 'minimum':-9}) - >>> axis_channel_config = ChannelConfig(storage=HDF5_Storage( - ... filename=filename, group='/bump/config/z/channel')) - >>> input_channel_config = ChannelConfig(storage=HDF5_Storage( - ... filename=filename, group='/bump/config/deflection/channel')) - - >>> a = PiezoAxis(axis_config=axis_config, - ... axis_channel_config=axis_channel_config, - ... axis_channel=axis_channel, name='z') + >>> axis_channel_config = ChannelConfig() + >>> axis_channel_config['name'] = 'z' + >>> axis_config['channel'] = axis_channel_config + >>> input_channel_config = ChannelConfig() + >>> input_channel_config['name'] = 'deflection' + + >>> a = PiezoAxis(config=axis_config, axis_channel=axis_channel) >>> a.setup_config() - >>> c = InputChannel( - ... channel_config=input_channel_config, channel=input_channel, - ... name='deflection') + >>> c = InputChannel(config=input_channel_config, channel=input_channel) >>> c.setup_config() - >>> piezo = AFMPiezo(axes=[a], input_channels=[c]) + >>> piezo = AFMPiezo(axes=[a], inputs=[c]) Setup a `stepper` instance. @@ -201,11 +196,90 @@ def bump(afm, bump_config, filename, group='/'): Test a bump: - >>> bump_config = BumpConfig(storage=HDF5_Storage( - ... filename=filename, group='/bump/config/bump')) + >>> bump_config = BumpConfig() >>> bump(afm, bump_config, filename, group='/bump') TODO: replace skipped example data with real-world values >>> pprint_HDF5(filename) # doctest: +ELLIPSIS, +REPORT_UDIFF + / + /bump + /bump/config + /bump/config/bump + + 200 + + -5e-08 + + quadratic + + 2e-07 + + 1e-06 + + 1024 + + 2.0 + /bump/config/deflection + /bump/config/deflection/channel + + 0 + + [ -1.00000000e+01 3.05180438e-04] + + 0.0 + + /dev/comedi0 + + [ 0. 3276.75] + + -10.0 + + 65535 + + deflection + + 0 + + 0 + /bump/config/z + /bump/config/z/axis + /bump/config/z/axis/channel + + 0 + + [ -1.00000000e+01 3.05180438e-04] + + 0.0 + + /dev/comedi0 + + [ 0. 3276.75] + + -10.0 + + 65535 + + z + + 0 + + 1 + + 20 + + 10.0 + + -9 + + + + 8e-09 + + ... + /bump/raw + + [...] + + [...] Close the Comedi device. @@ -220,13 +294,11 @@ def bump(afm, bump_config, filename, group='/'): data = bump_acquire(afm, bump_config) photo_sensitivity = _bump_analyze( - data, bump_config, z_channel_config=axis.axis_channel_config, - z_axis_config=axis.axis_config, - deflection_channel_config=deflection_channel.channel_config) + data, bump_config, z_axis_config=axis.config, + deflection_channel_config=deflection_channel.config) _bump_save( filename, group, data, bump_config, - z_channel_config=axis.axis_channel_config, - z_axis_config=axis.axis_config, - deflection_channel_config=deflection_channel.channel_config, + z_axis_config=axis.config, + deflection_channel_config=deflection_channel.config, processed_bump=photo_sensitivity) return photo_sensitivity diff --git a/calibcant/bump_analyze.py b/calibcant/bump_analyze.py index ab745b8..9f5412e 100644 --- a/calibcant/bump_analyze.py +++ b/calibcant/bump_analyze.py @@ -87,6 +87,8 @@ measured slope `Vphoto/Vout` is converted to `photo_sensitivity` with /bump/config/bump 200 + + -5e-08 quadratic @@ -278,6 +280,9 @@ def limited_linear_param_guess(x, y): i_high = i x_contact = float(x[i_low]) x_high = float(x[i_high]) + if x_high == x_contact: + x.tofile('x-bad.dat', sep='\n') + y.tofile('y-bad.dat', sep='\n') slope = (y_high - y_contact) / (x_high - x_contact) return (x_contact, y_contact, slope) @@ -368,7 +373,7 @@ def bump_fit(z, deflection, high_voltage_rail, _LOG.debug('solution converged') else: _LOG.debug('solution did not converge') - if plot or _package_config['matplotlib'] or True: + if plot or _package_config['matplotlib']: yguess = model(z, param_guess, high_voltage_rail=high_voltage_rail) yfit = model(z, p, high_voltage_rail=high_voltage_rail) bump_plot({'z': z, 'deflection': deflection}, yguess=yguess, yfit=yfit) @@ -422,7 +427,7 @@ def bump_load(filename, group='/'): filename=filename, group=group+key)) configs.append(config) try: - processed_bump = f[group+'processed'][...] + processed_bump = float(f[group+'processed'][...]) except KeyError: pass ret = [raw_bump] diff --git a/calibcant/calibrate.py b/calibcant/calibrate.py index 426abbf..2f850e1 100644 --- a/calibcant/calibrate.py +++ b/calibcant/calibrate.py @@ -187,7 +187,7 @@ def calib(afm, calibration_config, filename=None, group='/'): >>> from pypiezo.base import PiezoAxis, InputChannel >>> from pypiezo.config import ChannelConfig, AxisConfig >>> from stepper import Stepper - >>> from pyafm import AFM + >>> from pyafm.afm import AFM >>> from .config import (CalibrationConfig, BumpConfig, ... TemperatureConfig, VibrationConfig) >>> from .analyze import calib_load_all @@ -222,19 +222,18 @@ def calib(afm, calibration_config, filename=None, group='/'): >>> axis_config.update( ... {'gain':20, 'sensitivity':8e-9, 'minimum':-9}) >>> axis_channel_config = ChannelConfig() + >>> axis_channel_config['name'] = 'z' + >>> axis_config['channel'] = axis_channel_config >>> input_channel_config = ChannelConfig() + >>> input_channel_config['name'] = 'deflection' - >>> a = PiezoAxis(axis_config=axis_config, - ... axis_channel_config=axis_channel_config, - ... axis_channel=axis_channel, name='z') + >>> a = PiezoAxis(config=axis_config, axis_channel=axis_channel) >>> a.setup_config() - >>> c = InputChannel( - ... channel_config=input_channel_config, channel=input_channel, - ... name='deflection') + >>> c = InputChannel(config=input_channel_config, channel=input_channel) >>> c.setup_config() - >>> piezo = AFMPiezo(axes=[a], input_channels=[c]) + >>> piezo = AFMPiezo(axes=[a], inputs=[c]) Setup a `stepper` instance. @@ -256,16 +255,137 @@ def calib(afm, calibration_config, filename=None, group='/'): Test calibration: >>> calibration_config = CalibrationConfig() - >>> bump_config = BumpConfig() - >>> temperature_config = TemperatureConfig() - >>> vibration_config = VibrationConfig() - >>> calib(afm, calibration_config, bump_config, temperature_config, - ... vibration_config, filename=filename, group='/') + >>> calibration_config['bump'] = BumpConfig() + >>> calibration_config['temperature'] = TemperatureConfig() + >>> calibration_config['vibration'] = VibrationConfig() + >>> calib(afm, calibration_config, filename=filename, group='/') TODO: replace skipped example data with real-world values >>> pprint_HDF5(filename) # doctest: +ELLIPSIS, +REPORT_UDIFF + / + /bump + /bump/0 + /bump/0/config + /bump/0/config/bump + + 200 + ... + /bump/0/config/deflection + /bump/0/config/deflection/channel + + 0 + ... + /bump/0/config/z + /bump/0/config/z/axis + /bump/0/config/z/axis/channel + + 0 + ... + + 20 + ... + + ... + /bump/0/raw + + [...] + + [...] + /bump/1 + ... + /calibration + /calibration/config + /calibration/config/bump + + 200 + ... + + 10 + ... + /calibration/processed + /calibration/processed/spring-constant + + ... + + ... + + N/m + /calibration/raw + /calibration/raw/photodiode-sensitivity + + [...] + + V/m + /calibration/raw/temperature + + [...] + + K + /calibration/raw/thermal-vibration-variance + + [...] + + V^2 + /temperature + /temperature/0 + /temperature/0/config + + False + + Celsius + + 295.15 + + 22 + /temperature/1 + ... + /vibration + /vibration/0 + /vibration/0/config + /vibration/0/config/deflection + + 0 + ... + /vibration/0/config/vibration + + 2048 + ... + + ... + /vibration/0/raw + + [...] + /vibration/1 + ... + /vibration/19 + ... + /vibration/19/raw + + [...] >>> everything = calib_load_all(filename, '/') - >>> pprint(everything) - + >>> pprint(everything) # doctest: +ELLIPSIS, +REPORT_UDIFF + {'bump_details': [{'bump_config': , + 'deflection_channel_config': , + 'processed_bump': ..., + 'raw_bump': {'deflection': array([...], dtype=uint16), + 'z': array([...], dtype=uint16)}, + 'z_axis_config': }, + ...], + 'bumps': array([...]), + 'calibration_config': , + 'k': ..., + 'k_s': ..., + 'temperature_details': [{'processed_temperature': ..., + 'raw_temperature': array(22), + 'temperature_config': }, + ...], + 'temperatures': array([...]), + 'vibration_details': [{'deflection_channel_config': , + 'processed_vibration': ..., + 'raw_vibration': array([...], dtype=uint16), + 'vibration_config': }, + ...], + 'vibrations': array([...])} + Close the Comedi device. >>> d.close() @@ -275,8 +395,7 @@ def calib(afm, calibration_config, filename=None, group='/'): os.remove(filename) """ bumps, Ts, vibs = calib_acquire( - afm, calibration_config, bump_config, temperature_config, - vibration_config, filename=filename, group=group) + afm, calibration_config, filename=filename, group=group) # TODO: convert vib units? k,k_s = _calib_analyze(bumps, Ts, vibs) _calib_save(filename, group=group+'calibration/', bumps=bumps, diff --git a/calibcant/config.py b/calibcant/config.py index cffb58f..c80e791 100644 --- a/calibcant/config.py +++ b/calibcant/config.py @@ -77,6 +77,12 @@ class Quadratic (_BumpModel): class BumpConfig (_config.Config): "Configure `calibcant` bump operation" settings = [ + _config.FloatSetting( + name='initial-position', + help=('Position relative to surface for start of bump in meters. ' + 'Should be less than zero to ensure non-contact region ' + 'before you hit the surface.'), + default=-50e-9), _config.FloatSetting( name='setpoint', help=('Maximum deflection in volts in case of stepper positioning ' @@ -110,9 +116,6 @@ class BumpConfig (_config.Config): ]), ] -class BumpResult (_config.Config): - "The result of a `calibcant` bump operation" - class _VibrationModel (object): pass diff --git a/calibcant/vib.py b/calibcant/vib.py index 608b9b0..0c71f07 100644 --- a/calibcant/vib.py +++ b/calibcant/vib.py @@ -114,13 +114,12 @@ def vib(piezo, vibration_config, filename, group='/'): >>> channel.range = channel.find_range( ... unit=UNIT.volt, min=-10, max=10) >>> channel_config = ChannelConfig() + >>> channel_config['name'] = 'deflection' - >>> c = InputChannel( - ... channel_config=channel_config, channel=channel, - ... name='deflection') + >>> c = InputChannel(config=channel_config, channel=channel) >>> c.setup_config() - >>> piezo = AFMPiezo(axes=[], input_channels=[c]) + >>> piezo = AFMPiezo(axes=[], inputs=[c]) Test a vibration: @@ -132,39 +131,40 @@ def vib(piezo, vibration_config, filename, group='/'): /vibration /vibration/config /vibration/config/deflection - /vibration/config/deflection/channel - - 0 - - -10.0, 0.000305180437934 - - 0.0 - - /dev/comedi0 - - 0.0, 3276.75 - - -10.0 - - 65535 - - 0 - - 0 + + 0 + + [ -1.00000000e+01 3.05180438e-04] + + 0.0 + + /dev/comedi0 + + [ 0. 3276.75] + + -10.0 + + 65535 + + deflection + + 0 + + 0 /vibration/config/vibration - + 2048 - + 50000.0 - + 25000.0 - + 500.0 Breit-Wigner - - no - + + False + 1 Hann @@ -184,7 +184,7 @@ def vib(piezo, vibration_config, filename, group='/'): """ deflection_input_channel = piezo.input_channel_by_name('deflection') - deflection_channel_config = deflection_input_channel.channel_config + deflection_channel_config = deflection_input_channel.config deflection = vib_acquire(piezo, vibration_config) variance = _vib_analyze( diff --git a/calibcant/vib_analyze.py b/calibcant/vib_analyze.py index 6b5d682..bf74558 100644 --- a/calibcant/vib_analyze.py +++ b/calibcant/vib_analyze.py @@ -489,7 +489,7 @@ def vib_load(filename, group='/'): filename=filename, group=group+key)) configs.append(config) try: - processed_vibration = f[group+'processed'][...] + processed_vibration = float(f[group+'processed'][...]) except KeyError: pass ret = [raw_vibration] -- 2.26.2