Fix temperature -> vibration typo in check_vibration().
[calibcant.git] / calibcant / analyze.py
index 839a51bb72076125cd8285fa8a184a92c481378a..780d6dac2e45627c8a0b826b777b79aa0d92199a 100644 (file)
@@ -95,6 +95,8 @@ from .temperature_analyze import analyze as _temperature_analyze
 from .temperature_analyze import save as _temperature_save
 from .vibration_analyze import analyze as _vibration_analyze
 from .vibration_analyze import save as _vibration_save
+from .util import SaveSpec as _SaveSpec
+from .util import save as _save
 
 
 def analyze(bumps, temperatures, vibrations):
@@ -128,6 +130,13 @@ def analyze(bumps, temperatures, vibrations):
     v2_m = vibrations.mean()  # average voltage variance
     v2_s = vibrations.std()
 
+    if ps_m == 0:
+        raise ValueError('invalid bumps: {}'.format(bumps))
+    if T_m == 0:
+        raise ValueError('invalid temperatures: {}'.format(temperatures))
+    if v2_m == 0:
+        raise ValueError('invalid vibrations: {}'.format(vibrations))
+
     # Vphoto / photo_sensitivity = x
     # k = kB T / <x**2> = kB T photo_sensitivity**2 / Vphoto_var
     #
@@ -189,6 +198,20 @@ def plot(bumps, temperatures, vibrations):
     return figure
 _plot = plot  # alternative name for use inside analyze_all()
 
+def save_results(filename=None, group='/', bump=None,
+                 temperature=None, vibration=None, spring_constant=None,
+                 spring_constant_deviation=None):
+    specs = [
+        _SaveSpec(item=bump, relpath='raw/photodiode-sensitivity',
+                  array=True, units='V/m'),
+        _SaveSpec(item=temperature, relpath='raw/temperature',
+                  array=True, units='K'),
+        _SaveSpec(item=vibration, relpath='raw/vibration',
+                  array=True, units='V^2/Hz'),
+        _SaveSpec(item=spring_constant, relpath='processed/spring-constant',
+                  units='N/m', deviation=spring_constant_deviation),
+        ]
+    _save(filename=filename, group=group, specs=specs)
 
 def analyze_all(config, data, raw_data, maximum_relative_error=1e-5,
                 filename=None, group=None, plot=False, dry_run=False):
@@ -208,34 +231,43 @@ def analyze_all(config, data, raw_data, maximum_relative_error=1e-5,
     input_config = config['afm']['piezo'].select_config(
         setting_name='inputs', attribute_value='deflection')
     bumps_changed = temperatures_changed = vibrations_changed = False
+    calibration_group = None
     if not isinstance(group, _h5py.Group) and not dry_run:
         f = _h5py.File(filename, mode='a')
         group = _h5_create_group(f, group)
     else:
         f = None
     try:
-        for i,bump in enumerate(raw_data['bump']):        
+        if len(data.get('raw', {}).get('bump', [])) != len(data['bump']):
+            bumps_changed = True
+        for i,bump in enumerate(raw_data['bump']):
             data['bump'][i],changed = check_bump(
-                index=i, bump=bump, z_axis_config=axis_config,
+                index=i, bump=bump, config=config, z_axis_config=axis_config,
                 deflection_channel_config=input_config, plot=plot,
                 maximum_relative_error=maximum_relative_error)
             if changed and not dry_run:
                 bumps_changed = True
                 bump_group = _h5_create_group(group, 'bump/{}'.format(i))
                 _bump_save(group=bump_group, processed=data['bump'][i])
+        if len(data.get('raw', {}).get('temperature', [])
+               ) != len(data['temperature']):
+            temperatures_changed = True
         for i,temperature in enumerate(raw_data['temperature']):
             data['temperature'][i],changed = check_temperature(
-                index=i, temperature=temperature,
+                index=i, temperature=temperature, config=config,
                 maximum_relative_error=maximum_relative_error)
             if changed and not dry_run:
                 temperatures_changed = True
                 temperature_group = _h5_create_group(
                     group, 'temperature/{}'.format(i))
                 _temperature_save(
-                    group=temerature_group, processed=data['temperature'][i])
+                    group=temperature_group, processed=data['temperature'][i])
+        if len(data.get('raw', {}).get('vibration', [])
+               ) != len(data['vibration']):
+            vibrations_changed = True
         for i,vibration in enumerate(raw_data['vibration']):
             data['vibration'][i],changed = check_vibration(
-                    index=i, vibration=vibration,
+                    index=i, vibration=vibration, config=config,
                     deflection_channel_config=input_config, plot=plot,
                     maximum_relative_error=maximum_relative_error)
             if changed and not dry_run:
@@ -244,25 +276,43 @@ def analyze_all(config, data, raw_data, maximum_relative_error=1e-5,
                     group, 'vibration/{}'.format(i))
                 _vibration_save(
                     group=vibration_group, processed=data['vibration'])
-        k,k_s,changed = check_calibration(
-            k=data['processed']['spring_constant'],
-            k_s=data['processed']['spring_constant_deviation'],
-            bumps=data['bump'],
-            temperatures=data['temperature'], vibrations=data['vibration'],
-            maximum_relative_error=maximum_relative_error)
-        if (changed or bumps_changed or temperatures_changed or
-            vibrations_changed) and not dry_run:
+        if (bumps_changed or temperatures_changed or vibrations_changed
+            ) and not dry_run:
             calibration_group = _h5_create_group(group, 'calibration')
             if bumps_changed:
-                calib_save(group=calibration_group, bump=data['bump'])
+                save_results(
+                    group=calibration_group, bump=data['bump'])
             if temperatures_changed:
-                calib_save(
+                save_results(
                     group=calibration_group, temperature=data['temperature'])
             if vibrations_changed:
-                calib_save(
+                save_results(
                     group=calibration_group, vibration=data['vibration'])
-            if changed:
-                calib_save(group=calibration_group, k=k, k_s=k_s)
+        if len(raw_data['bump']) != len(data['bump']):
+            raise ValueError(
+                'not enough raw bump data: {} of {}'.format(
+                    len(raw_data['bump']), len(data['bump'])))
+        if len(raw_data['temperature']) != len(data['temperature']):
+            raise ValueError(
+                'not enough raw temperature data: {} of {}'.format(
+                    len(raw_data['temperature']), len(data['temperature'])))
+        if len(raw_data['vibration']) != len(data['vibration']):
+            raise ValueError(
+                'not enough raw vibration data: {} of {}'.format(
+                    len(raw_data['vibration']), len(data['vibration'])))
+        k,k_s,changed = check_calibration(
+            k=data.get('processed', {}).get('spring_constant', None),
+            k_s=data.get('processed', {}).get(
+                'spring_constant_deviation', None),
+            bumps=data['bump'],
+            temperatures=data['temperature'], vibrations=data['vibration'],
+            maximum_relative_error=maximum_relative_error)
+        if changed and not dry_run:
+            if calibration_group is None:
+                calibration_group = _h5_create_group(group, 'calibration')
+            save_results(
+                group=calibration_group,
+                spring_constant=k, spring_constant_deviation=k_s)
     finally:
         if f:
             f.close()
@@ -272,10 +322,14 @@ def analyze_all(config, data, raw_data, maximum_relative_error=1e-5,
              vibrations=data['raw']['vibration'])
     return (k, k_s)
 
-def check_bump(index, bump, maximum_relative_error, **kwargs):
+def check_bump(index, bump, config=None, maximum_relative_error=0, **kwargs):
     changed = False
+    try:
+        bump_config = bump['config']['bump']
+    except KeyError:
+        bump_config = config['bump']
     sensitivity = _bump_analyze(
-        config=bump['config']['bump'], data=bump['raw'], **kwargs)
+        config=bump_config, data=bump['raw'], **kwargs)
     if bump.get('processed', None) is None:
         changed = True            
         _LOG.warn('new analysis for bump {}: {}'.format(index, sensitivity))
@@ -289,10 +343,15 @@ def check_bump(index, bump, maximum_relative_error, **kwargs):
                     sensitivity-bump['processed'], rel_error))
     return (sensitivity, changed)
 
-def check_temperature(index, temperature, maximum_relative_error, **kwargs):
+def check_temperature(index, temperature, config=None,
+                      maximum_relative_error=0, **kwargs):
     changed = False
+    try:
+        temp_config = temperature['config']['temperature']
+    except KeyError:
+        temp_config = config['temperature']
     temp = _temperature_analyze(
-        config=temperature['config']['temperature'],
+        config=temp_config,
         temperature=temperature['raw'], **kwargs)
     if temperature.get('processed', None) is None:
         changed = True            
@@ -309,14 +368,18 @@ def check_temperature(index, temperature, maximum_relative_error, **kwargs):
                     temp-temperature['processed'], rel_error))
     return (temp, changed)
 
-def check_vibration(index, vibration, maximum_relative_error, **kwargs):
+def check_vibration(index, vibration, config=None, maximum_relative_error=0,
+                    **kwargs):
     changed = False
+    try:
+        vib_config = vibration['config']['vibration']
+    except KeyError:
+        vib_config = config['vibration']
     variance = _vibration_analyze(
-        config=vibration['config']['vibration'],
-        deflection=vibration['raw'], **kwargs)
+        config=vib_config, deflection=vibration['raw'], **kwargs)
     if vibration.get('processed', None) is None:
         changed = True
-        _LOG.warn('new analysis for temperature {}: {}'.format(
+        _LOG.warn('new analysis for vibration {}: {}'.format(
                 index, variance))
     else:
         rel_error = abs(variance-vibration['processed'])/vibration['processed']
@@ -336,6 +399,7 @@ def check_calibration(k, k_s, maximum_relative_error, **kwargs):
     else:
         rel_error = abs(new_k-k)/k
         if rel_error > maximum_relative_error:
+            changed = True
             _LOG.warn(("new analysis doesn't match for the spring constant: "
                        "{} != {} (difference: {}, relative error: {})").format(
                     new_k, k, new_k-k, rel_error))
@@ -344,8 +408,9 @@ def check_calibration(k, k_s, maximum_relative_error, **kwargs):
         _LOG.warn('new analysis for the spring constant deviation: {}'.format(
                 new_k_s))
     else:
-        rel_error = abs(new_k-k)/k
+        rel_error = abs(new_k_s-k_s)/k_s
         if rel_error > maximum_relative_error:
+            changed = True
             _LOG.warn(
                 ("new analysis doesn't match for the spring constant deviation"
                  ": {} != {} (difference: {}, relative error: {})").format(