Source code for magni.afm.io._stream_conversion

"""
..
    Copyright (c) 2014-2017, Magni developers.
    All rights reserved.
    See LICENSE.rst for further information.

Module providing functionality for converting a file stream.

The reading of an .mi file is logically separated into four steps of which the
functionality provided by this module performs the first step.

Routine listings
----------------
convert_stream(stream)
    Convert a file stream to flat, basic variables.

"""

from __future__ import division

import numpy as np


[docs]def convert_stream(stream): """ Convert a file stream to flat, basic variables. The flat, basic variables are separated into header parameters and the data. The header parameters are name, value pairs whereas the data is a 1-dimensional numeric array. Parameters ---------- stream : str The file stream. Returns ------- params : tuple The header parameters. data : numpy.ndarray The data. See Also -------- magni.afm.io.read_mi_file : Function using the present function. Notes ----- This function splits the file stream into header and data, and splits the header into parameter name, value pairs. """ index = stream.find(b'data ') index = stream.find(b'\n', index) stream_params = stream[:index] stream_data = stream[index + 1:] params = stream_params.split(b'\n') params = [(str(param[:14].decode()), str(param[14:].decode())) for param in params] params = [(name.strip(), _convert_parameter_value(value)) for name, value in params] params = tuple(params) if params[0][0] != 'fileType': raise IOError("The file must have a 'fileType' header parameter.") if params[-1][0] != 'data': raise IOError("The file must have a 'data' header parameter.") if params[0][1].lower() == 'image': data = _convert_image_data(stream_data, params[-1][1]) elif params[0][1].lower() == 'spectroscopy': data = _convert_spectroscopy_data(stream_data, params[-1][1]) else: msg = 'The value of >>fileType<<, {!r}, must be in {!r}.' raise IOError(msg.format(params[0][1], ('Image', 'Spectroscopy'))) return params, data
[docs]def _convert_image_data(buffer_, data_type): """ Convert the file stream image data to a 1-dimensional numeric array. Parameters ---------- buffer_ : str The file stream image data. data_type : str The data type of the file stream image data. Returns ------- data : numpy.ndarray The data as a 1-dimensional numeric array. See Also -------- convert_stream : Function using the present function. """ if data_type.lower() == 'binary': data = np.frombuffer(buffer_, np.int16) data = np.float64(data) / 2**15 elif data_type.lower() == 'binary_32': data = np.frombuffer(buffer_, np.int32) data = np.float64(data) / 2**31 elif data_type.lower() == 'ascii': data = map(int, buffer_.strip().split()) data = np.float64(data) / 2**15 elif data_type.lower() == 'ascii_absolute': data = map(float, buffer_.strip().split()) data = np.float64(data) elif data_type.lower() == 'ascii_multicolumn': data = buffer_.strip().split() data = [map(float, row.split()) for row in data] data = np.float64(data).flatten('F') else: raise IOError('Unknown data type {!r}.'.format(data_type)) return data
[docs]def _convert_parameter_value(string): """ Convert a file stream parameter value to a basic python value. The converted value is either a boolean, string, floating point, or integer value or a list containing a mix of these. Parameters ---------- string : str The file stream parameter value. Returns ------- value : None The converted, basic python value. See Also -------- convert_stream : Function using the present function. """ parts = string.split() if len(parts) == 0: value = None elif len(parts) == 1: if string.lower() == 'true': value = True elif string.lower() == 'false': value = False else: try: value = string value = float(string) value = int(string) except ValueError: pass else: value = [_convert_parameter_value(part) for part in parts] value = tuple(value) if not isinstance(value[0], str) else string return value
[docs]def _convert_spectroscopy_data(buffer_, data_type): """ Convert the file stream spectroscopy data to a 1-dimensional numeric array. Parameters ---------- buffer_ : str The file stream spectroscopy data. data_type : str The data type of the file stream spectroscopy data. Returns ------- data : numpy.ndarray The data as a 1-dimensional numeric array. See Also -------- convert_stream : Function using the present function. """ if data_type.lower() == 'binary': data = np.frombuffer(buffer_, np.float32) data = np.float64(data) elif data_type.lower() == 'ascii_multicolumn': data = buffer_.strip().split()[1:] data = [map(float, row.split()[2:]) for row in data] data = np.float64(data).flatten('F') else: raise IOError('Unknown data type {!r}.'.format(data_type)) return data