跟进分析示波器二进制数据。我为Tektronix的内部文件格式.isf编写了一个简单的解析器。我将代码修改如下:
import numpy as np
import os.path
def parse_curve(isf_file):
"""
Reads one tektronix .isf file and returns a dictionary containing
all tags as keys. The actual data is stored in the key "data".
"""
extensions = set([".isf"])
if os.path.splitext(isf_file)[-1].lower() not in extensions:
raise ValueError("File type unkown.")
with open(isf_file, 'rb') as ifile:
# read header
header = {}
while True:
name = _read_chunk(ifile, " ")
if name != ":CURVE":
value = _read_chunk(ifile, ";")
assert name not in header
header[name] = value
else:
# ":CURVE " is the last tag of the header, followed by
# '#XYYY' with X being the number of bytes of YYY.
# YYY is the length of the datastream following in bytes.
value = ifile.read(2)
y_str = ifile.read(int(value[-1]))
value += y_str
# the number of bytes might be present with or without the
# preceding header ":WFMPRE:"
nobytes = header.get("BYT_NR",
header.get(":WFMPRE:BYT_NR", "0")
)
assert int(y_str) == int(header["NR_PT"]) * int(nobytes)
header[name] = value
currentposition = ifile.tell()
break
assert header["ENCDG"] == "BINARY"
# read data as numpy array
header["data"] = _read_data(ifile, currentposition, header)
return header
def _read_chunk(headerfile, delimiter):
"""
Reads one chunk of header data. Based on delimiter, this may be a tag
(ended by " ") or the value of a tag (ended by ";").
"""
prior_delimiter = None
chunk = []
while True:
c = headerfile.read(1)
if c != delimiter:
chunk.append(c)
if c == '"':
# switch delimiter to make sure to parse the whole string
# enclosed in '"'.
delimiter, prior_delimiter = c, delimiter
elif prior_delimiter:
# switch back delimiter
chunk.append(c)
delimiter, prior_delimiter = prior_delimiter, None
else:
return "".join(chunk)
def _read_data(bfile, position, header):
"""
Reads in the binary data as numpy array.
Apparently, there are only 1d-signals stored in .isf files, so a 1d-array
is read.
"""
# determine the datatype from header tags
datatype = ">" if header["BYT_OR"] == "MSB" else "<"
if header["BN_FMT"] == "RI":
datatype += "i"
else:
datatype += "u"
# BYT_NR might be present with preceding header ":WFMPRE:BYT_NR"
nobytes = header.get("BYT_NR",
header.get(":WFMPRE:BYT_NR", "")
)
datatype += nobytes
assert len(datatype) >= 3
bfile.seek(position)
data = np.fromfile(bfile, datatype)
assert data.size == int(header["NR_PT"])
# calculate true values
data = data * float(header["YMULT"]) + float(header["YZERO"])
return data在最初的问题中,_read_data做了更多的工作,这个部分现在被移到了另一个模块。
我仍然关心的一个问题是,在读取“:曲线”标签时,assert部分是否是最佳解决方案:
nobytes = header.get("BYT_NR",
header.get(":WFMPRE:BYT_NR", "0")
)
assert int(y_str) == int(header["NR_PT"]) * int(nobytes)发布于 2015-05-18 23:06:17
总的来说,在我看来很好;只有小的nits:
您希望从断言转移到抛出适当的、信息丰富的异常--例如,显示预期值和实际值。
在if name != ":CURVE":的末尾,您可以只发出一个continue,而不是一个else块--帮助进行缩进。
与其将chunk列为一个列表,然后在最后执行一个join,您还可以将其设置为一个字符串并附加字符串。
https://codereview.stackexchange.com/questions/91032
复制相似问题