From: W. Trevor King Date: Fri, 4 Jun 2010 12:01:34 +0000 (-0400) Subject: Brought picoforce driver up to speed with 0x06130001 and 0x07200000 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=b919ceccf1b2f3ce1d70453122cf0e5895fbd66b;p=hooke.git Brought picoforce driver up to speed with 0x06130001 and 0x07200000 --- diff --git a/hooke/driver/picoforce.py b/hooke/driver/picoforce.py index 8018eb5..e664a95 100644 --- a/hooke/driver/picoforce.py +++ b/hooke/driver/picoforce.py @@ -152,7 +152,7 @@ class PicoForceDriver (Driver): Otherwise, raise `ValueError`. """ version = info['Force file list'].get('Version', None) - if version not in ['0x06120002']: + if version not in ['0x06120002', '0x06130001', '0x07200000']: raise NotImplementedError( '%s file version %s not supported (yet!)\n%s' % (self.name, version, @@ -171,35 +171,39 @@ class PicoForceDriver (Driver): def _read_data_file(self, file, info): file.seek(0) traces = self._extract_traces(buffer(file.read()), info) - deflection,z_piezo,deflection_B = traces - self._validate_traces(z_piezo, deflection, deflection_B) - L = len(deflection) + for k,t in traces.items(): + t.tofile('t-%s' % k, sep='\n') + self._validate_traces( + traces['Z sensor'], traces['Deflection']) + L = len(traces['Deflection']) approach = self._extract_block( - info, z_piezo, deflection, 0, L/2, 'approach') + info, traces['Z sensor'], traces['Deflection'], 0, L/2, 'approach') retract = self._extract_block( - info, z_piezo, deflection, L/2, L, 'retract') + info, traces['Z sensor'], traces['Deflection'], L/2, L, 'retract') data = [approach, retract] return data def _extract_traces(self, buffer, info): """Extract each of the three vector blocks in a PicoForce file. - The blocks are: + The blocks are (in variable order): - * Deflection input * Z piezo sensor input + * Deflection input * Deflection again? And their headers are marked with 'Ciao force image list'. """ - traces = [] + traces = {} + version = info['Force file list']['Version'] + type_re = re.compile('S \[(\w*)\] "([\w\s.]*)"') for image in info['Ciao force image list']: offset = int(image['Data offset']) length = int(image['Data length']) sample_size = int(image['Bytes/pixel']) - rows = length / sample_size if sample_size != 2: raise NotImplementedError('Size: %s' % sample_size) + rows = length / sample_size d = curve.Data( shape=(rows), dtype=numpy.int16, @@ -207,19 +211,55 @@ class PicoForceDriver (Driver): offset=offset, info=image, ) - traces.append(d) + if version in ['0x06120002', '0x06130001']: + match = type_re.match(image['@4:Image Data']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@4:Image Data', image['@4:Image Data']) + assert match.group(1).lower() == match.group(2).replace(' ','').lower(), \ + 'Name missmatch: "%s", "%s"' % (match.group(1), match.group(2)) + tname = match.group(2) + else: + assert version == '0x07200000', version + match = type_re.match(image['@4:Image Data']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@4:Image Data', image['@4:Image Data']) + if match.group(1) == 'PulseFreq1': + assert match.group(2) == 'Freq. 1', match.group(2) + else: + assert match.group(1).lower() == match.group(2).replace(' ','').lower(), \ + 'Name missmatch: "%s", "%s"' % (match.group(1), match.group(2)) + tname = match.group(2) + if tname == 'Freq. 1': # Normalize trace names between versions + tname = 'Z sensor' + elif tname == 'Deflection Error': + tname = 'Deflection' + if tname in traces: + continue + msg = None + if (traces[tname].info != image): + ik = set(image.keys()) + ok = set(traces[tname].info.keys()) + if ik != ok: + mmsg = 'extra keys: %s, missing keys %s' % (ik-ok, ok-ik) + else: + mmsg = [] + for key in image.keys(): + if image[key] != traces[tname].info[key]: + mmsg.append( + '%s (%s != %s)' + % (key, image[key], traces[tname].info[key])) + mmsg = ', '.join(mmsg) + msg = 'info difference: %s' % mmsg + elif not (traces[tname] == d).all(): + msg = 'data difference' + if msg != None: + raise NotImplementedError( + 'Missmatched duplicate traces for %s: %s' + % (tname, msg)) + traces[tname] = d return traces - def _validate_traces(self, z_piezo, deflection, deflection_B): - key = 'Spring Constant' - spring_constant = z_piezo.info[key] - for trace in [deflection, deflection_B]: - if trace.info[key] != spring_constant: - raise NotImplementedError( - 'spring constant missmatch: %s != %s' - % (spring_constant, trace.info[key])) - if max(abs(deflection_B[:-1]-deflection[:-1])) != 0: - raise NotImplementedError('trace 0 != trace 2') + def _validate_traces(self, z_piezo, deflection): if len(z_piezo) != len(deflection): raise ValueError('Trace length missmatch: %d != %d' % (len(z_piezo), len(deflection))) @@ -232,44 +272,46 @@ class PicoForceDriver (Driver): block[:,1] = deflection[start:stop] block.info = self._translate_block_info( info, z_piezo.info, deflection.info, name) + block.info['columns'] = ['z piezo (m)', 'deflection (m)'] block = self._scale_block(block) return block def _translate_block_info(self, info, z_piezo_info, deflection_info, name): + version = info['Force file list']['Version'] ret = { - 'name':name, - 'raw info':info, + 'name': name, + 'raw info': info, 'raw z piezo info': z_piezo_info, 'raw deflection info': deflection_info, - 'spring constant (N/m)':float(z_piezo_info['Spring Constant']), + 'spring constant (N/m)': float(z_piezo_info['Spring Constant']), } t = info['Force file list']['Date'] # 04:42:34 PM Tue Sep 11 2007 ret['time'] = time.strptime(t, '%I:%M:%S %p %a %b %d %Y') - type_re = re.compile('S \[(\w*)\] "([\w\s]*)"') - match = type_re.match(z_piezo_info['@4:Image Data']) - assert match.group(1).lower() == match.group(2).replace(' ','').lower(), \ - 'Name missmatch: "%s", "%s"' % (match.group(1), match.group(2)) - ret['columns'] = [match.group(2)] - match = type_re.match(deflection_info['@4:Image Data']) - assert match.group(1).lower() == match.group(2).replace(' ','').lower(), \ - 'Name missmatch: "%s", "%s"' % (match.group(1), match.group(2)) - ret['columns'].append(match.group(2)) - assert ret['columns'] == ['Z sensor', 'Deflection'], \ - 'Unexpected columns: %s' % ret['columns'] - ret['columns'] = ['z piezo (m)', 'deflection (m)'] - volt_re = re.compile( - 'V \[Sens. (\w*)\] \(([.0-9]*) V/LSB\) (-?[.0-9]*) V') - match = volt_re.match(z_piezo_info['@4:Z scale']) - assert match.group(1) == 'ZSensorSens', z_piezo_info['@4:Z scale'] + 'V \[Sens. ([\w\s.]*)\] \(([.0-9]*) V/LSB\) (-?[.0-9]*) V') + hz_re = re.compile( + 'V \[Sens. ([\w\s.]*)\] \(([.0-9]*) kHz/LSB\) (-?[.0-9]*) kHz') + if version in ['0x06120002', '0x06130001']: + match = volt_re.match(z_piezo_info['@4:Z scale']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@4:Z scale', z_piezo_info['@4:Z scale']) + assert match.group(1) == 'ZSensorSens', z_piezo_info['@4:Z scale'] + else: + assert version == '0x07200000', version + match = hz_re.match(z_piezo_info['@4:Z scale']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@4:Z scale', z_piezo_info['@4:Z scale']) + assert match.group(1) == 'Freq. 1', z_piezo_info['@4:Z scale'] ret['z piezo sensitivity (V/bit)'] = float(match.group(2)) ret['z piezo range (V)'] = float(match.group(3)) ret['z piezo offset (V)'] = 0.0 # offset assumed if raw data is signed... match = volt_re.match(deflection_info['@4:Z scale']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@4:Z scale', deflection_info['@4:Z scale']) assert match.group(1) == 'DeflSens', z_piezo_info['@4:Z scale'] ret['deflection sensitivity (V/bit)'] = float(match.group(2)) ret['deflection range (V)'] = float(match.group(3)) @@ -278,34 +320,54 @@ class PicoForceDriver (Driver): nm_sens_re = re.compile('V ([.0-9]*) nm/V') match = nm_sens_re.match(info['Scanner list']['@Sens. Zsens']) + assert match != None, 'Bad regexp for %s/%s, %s' \ + % ('Scanner list', '@Sens. Zsens', info['Scanner list']['@4:Z scale']) ret['z piezo sensitivity (m/V)'] = float(match.group(1))*1e-9 match = nm_sens_re.match(info['Ciao scan list']['@Sens. DeflSens']) + assert match != None, 'Bad regexp for %s/%s, %s' \ + % ('Ciao scan list', '@Sens. DeflSens', info['Ciao scan list']['@Sens. DeflSens']) ret['deflection sensitivity (m/V)'] = float(match.group(1))*1e-9 match = volt_re.match(info['Ciao force list']['@Z scan start']) + assert match != None, 'Bad regexp for %s/%s, %s' \ + % ('Ciao force list', '@Z scan start', info['Ciao force list']['@Z scan start']) ret['z piezo scan (V/bit)'] = float(match.group(2)) ret['z piezo scan start (V)'] = float(match.group(3)) match = volt_re.match(info['Ciao force list']['@Z scan size']) + assert match != None, 'Bad regexp for %s/%s, %s' \ + % ('Ciao force list', '@Z scan size', info['Ciao force list']['@Z scan size']) ret['z piezo scan size (V)'] = float(match.group(3)) const_re = re.compile('C \[([:\w\s]*)\] ([.0-9]*)') match = const_re.match(z_piezo_info['@Z magnify']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@Z magnify', info['@Z magnify']) assert match.group(1) == '4:Z scale', match.group(1) ret['z piezo gain'] = float(match.group(2)) - match = volt_re.match(z_piezo_info['@4:Z scale']) - assert match.group(1) == 'ZSensorSens', match.group(1) - ret['z piezo sensitivity (V/bit)'] = float(match.group(2)) - ret['z piezo range (V)'] = float(match.group(3)) + if version in ['0x06120002', '0x06130001']: + match = volt_re.match(z_piezo_info['@4:Z scale']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@4:Z scale', info['@4:Z scale']) + assert match.group(1) == 'ZSensorSens', match.group(1) + ret['z piezo sensitivity (V/bit)'] = float(match.group(2)) + ret['z piezo range (V)'] = float(match.group(3)) + else: + assert version == '0x07200000', version + pass match = volt_re.match(z_piezo_info['@4:Ramp size']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@4:Ramp size', info['@4:Ramp size']) assert match.group(1) == 'Zsens', match.group(1) ret['z piezo ramp size (V/bit)'] = float(match.group(2)) ret['z piezo ramp size (V)'] = float(match.group(3)) match = volt_re.match(z_piezo_info['@4:Ramp offset']) + assert match != None, 'Bad regexp for %s, %s' \ + % ('@4:Ramp offset', info['@4:Ramp offset']) assert match.group(1) == 'Zsens', match.group(1) ret['z piezo ramp offset (V/bit)'] = float(match.group(2)) ret['z piezo ramp offset (V)'] = float(match.group(3)) diff --git a/test/picoforce_driver.py b/test/picoforce_driver.py new file mode 100644 index 0000000..d1345e1 --- /dev/null +++ b/test/picoforce_driver.py @@ -0,0 +1,69 @@ +# Copyright (C) 2010 W. Trevor King +# +# This file is part of Hooke. +# +# Hooke is free software: you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation, either +# version 3 of the License, or (at your option) any later version. +# +# Hooke 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with Hooke. If not, see +# . + +""" +>>> from hooke.hooke import Hooke, HookeRunner +>>> h = Hooke() +>>> r = HookeRunner() +>>> h = r.run_lines(h, ['load_playlist test/data/vclamp_picoforce/playlist']) + +Success + +>>> h = r.run_lines(h, ['curve_info']) # doctest: +ELLIPSIS, +REPORT_UDIFF +name: 20071120a_i27_t33.100 +path: test/data/vclamp_picoforce/20071120a_i27_t33.100 +experiment: +driver: +filetype: picoforce +note: +blocks: 2 +block sizes: [(2048, 2), (2048, 2)] +Success + + +Also checkout the newer versions we have available. + +>>> h = r.run_lines(h, ['previous_curve']) +Success + +>>> h = r.run_lines(h, ['curve_info']) # doctest: +ELLIPSIS, +REPORT_UDIFF +name: 0x07200000 +path: test/data/vclamp_picoforce/0x07200000 +experiment: +driver: +filetype: picoforce +note: +blocks: 2 +block sizes: [(512, 2), (512, 2)] +Success + +>>> h = r.run_lines(h, ['previous_curve']) +Success + +>>> h = r.run_lines(h, ['curve_info']) # doctest: +ELLIPSIS, +REPORT_UDIFF +name: 0x06130001 +path: test/data/vclamp_picoforce/0x06130001 +experiment: +driver: +filetype: picoforce +note: +blocks: 2 +block sizes: [(2048, 2), (2048, 2)] +Success + +"""