From 39c39640471ba3e5fd6317f3b177411a5e7d20d2 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 9 Sep 2010 07:37:03 -0400 Subject: [PATCH] Extent JPK driver to also read .jpk-data1D-file files. Also: * Lowercase most JPK exception messages. * Decode integer types to floats as specified by 'encoder'. * Give the path to the old file when suggeesting an `out2jpk-force` upgrade. --- hooke/driver/jpk.py | 64 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/hooke/driver/jpk.py b/hooke/driver/jpk.py index 71af831..6fe84f0 100644 --- a/hooke/driver/jpk.py +++ b/hooke/driver/jpk.py @@ -74,6 +74,12 @@ class JPKDriver (Driver): f.path = path zip_info = self._zip_info(f) version = zip_info['file-format-version'] + if zip_info['jpk-data-file'] == 'jpk-data1D-file': + return self._zip_read_1d( + f, path, info, zip_info, version) + elif zip_info['jpk-data-file'] != 'spm-forcefile': + raise ValueError('unrecognized JPK file type "%s"' + % zip_info['jpk-data-file']) segments = [] for i in range(len([p for p in f.namelist() if p.endswith('segment-header.properties')])): @@ -121,7 +127,7 @@ class JPKDriver (Driver): zipfile, index, chan, chan_info)) if channels[-1].shape != expected_shape: raise NotImplementedError( - 'Channel %d:%s in %s has strange shape %s != %s' + 'channel %d:%s in %s has strange shape %s != %s' % (index, chan, zipfile.path, channels[-1].shape, expected_shape)) if len(channels) > 0: @@ -145,11 +151,13 @@ class JPKDriver (Driver): 'segments', str(segment_index), chan_info['data']['file']['name']), 'r')) as f: assert chan_info['data']['file']['format'] == 'raw', \ - 'Non-raw data format:\n%s' % pprint.pformat(chan_info) + 'non-raw data format:\n%s' % pprint.pformat(chan_info) dtype = self._zip_channel_dtype(chan_info) data = numpy.frombuffer( buffer(f.read()), dtype=dtype,) + if dtype.kind in ['i', 'u']: + data = self._zip_channel_decode(data, chan_info) return data def _zip_calculate_channel(self, chan_info): @@ -168,7 +176,7 @@ class JPKDriver (Driver): step=step, dtype=numpy.float32) else: - raise ValueError('Unrecognized data format "%s"' % type_) + raise ValueError('unrecognized data format "%s"' % type_) def _zip_channel_dtype(self, chan_info): type_ = chan_info['data']['type'] @@ -181,7 +189,7 @@ class JPKDriver (Driver): elif encoder in ['unsignedinteger', 'unsignedinteger-limited']: dtype = numpy.dtype(numpy.uint32) else: - raise ValueError('Unrecognized encoder type "%s" for "%s" data' + raise ValueError('unrecognized encoder type "%s" for "%s" data' % (encoder, type_)) elif type_ in ['short-data', 'short', 'memory-short-data']: encoder = chan_info['data']['encoder']['type'] @@ -190,10 +198,10 @@ class JPKDriver (Driver): elif encoder in ['unsignedshort', 'unsignedshort-limited']: dtype = numpy.dtype(numpy.uint16) else: - raise ValueError('Unrecognized encoder type "%s" for "%s" data' + raise ValueError('unrecognized encoder type "%s" for "%s" data' % (encoder, type_)) else: - raise ValueError('Unrecognized data format "%s"' % type_) + raise ValueError('unrecognized data format "%s"' % type_) byte_order = '>' # '>' (big endian) byte order. # From version 0.3 of JPKForceSpec.txt in the "Binary data" section: @@ -206,6 +214,10 @@ class JPKDriver (Driver): # float (4 bytes, IEEE format). return dtype.newbyteorder(byte_order) + def _zip_channel_decode(self, data, encoder_info): + return self._zip_apply_channel_scaling( + data, encoder_info['data']['encoder']) + def _zip_translate_params(self, params, chan_info, version): info = { 'raw info':params, @@ -328,16 +340,20 @@ class JPKDriver (Driver): pass # Fall through to 'simple' conversion processing. else: assert conversion_info['type'] == 'simple', conversion_info['type'] + segment[:,channel] = self._zip_apply_channel_scaling( + segment[:,channel], conversion_info) + unit = self._zip_unit(conversion_info['scaling'], version) + segment.info['columns'][channel] = join_data_label(channel_name, unit) + return segment + + def _zip_apply_channel_scaling(self, channel_data, conversion_info): assert conversion_info['scaling']['type'] == 'linear', \ conversion_info['scaling']['type'] assert conversion_info['scaling']['style'] == 'offsetmultiplier', \ conversion_info['scaling']['style'] multiplier = float(conversion_info['scaling']['multiplier']) offset = float(conversion_info['scaling']['offset']) - unit = self._zip_unit(conversion_info['scaling'], version) - segment[:,channel] = segment[:,channel] * multiplier + offset - segment.info['columns'][channel] = join_data_label(channel_name, unit) - return segment + return channel_data * multiplier + offset def _zip_unit(self, conversion_info, version): if version in ['0.%d' % i for i in range(3)]: @@ -370,8 +386,34 @@ class JPKDriver (Driver): sub_info[setting[-1]] = fields[1] return info + def _zip_read_1d(self, zipfile, path, info, zip_info, version): + expected_shape = (int(zip_info['data']['num-points']),) + if zip_info['data']['type'] in ['constant-data', 'raster-data']: + return self._zip_calculate_channel(zip_info) + with Closing(zipfile.open( + zip_info['data']['file']['name'], 'r')) as f: + assert zip_info['data']['file']['format'] == 'raw', \ + 'non-raw data format:\n%s' % pprint.pformat(chan_info) + dtype = self._zip_channel_dtype(zip_info) + data = numpy.frombuffer( + buffer(f.read()), + dtype=dtype,) + if dtype.kind in ['i', 'u']: + data = self._zip_channel_decode(data, zip_info) + if data.shape != expected_shape: + raise NotImplementedError( + 'channel %s has strange shape %s != %s' + % (path, data.shape, expected_shape)) + d = curve.Data( + shape=data.shape, + dtype=data.dtype, + info=zip_info) + d[:] = data + return d + def _read_old(self, path, info): raise NotImplementedError( "Early JPK files (pre-zip) are not supported by Hooke. Please " "use JPK's `out2jpk-force` script to convert your old files " - "to a more recent format before loading them with Hooke.") + "(%s) to a more recent format before loading them with Hooke." + % path) -- 2.26.2