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