示波器文件-ISF文件-读取说明
function data = isfread (pattern)
%ISFREAD Read a Tektronix ISF file.
% DATA = ISFREAD(FILENAME) reads the Tektronix ISF file given by FILENAME
% and returns a structure containg the data and the header.
%
% DATA = ISFREAD(DIRECTORY) reads all files with the extension '.ISF' or
% '.isf' in the specified directory and returns a structure array
% containing the data and the headers. If n files are read, the structure
% array will have size 1xn.
%
% DATA = ISFREAD(PATTERN) reads the files matched by the specified
% PATTERN. PATTERN can be a wildcard, such as '*.ISF'. Itreturns a
% structure array containing the data and the headers. There is one
% element for each file read. If n files are read, the structure array
% will have size 1xn.
%
% ISF is the name of an internal data format used by Tektronix
% oscilloscopes. The files consist of a short text header followed by
% binary data.
%
% This function was written to read data saved by a model TDS 360
% oscilloscope, but is likely to work with other models that use the ISF
% format. It was tested by saving the same waveform on the oscilloscope
% in both comma-separated values (CSV) format and ISF, then comparing CSV
% data to that returned by ISFREAD.
%
% The DATA structure contains the following fields:
% filename
% datetime
% header
% x
% y
%
% The field datetime is file's modification date and time. This date and
% time may originate from the oscilloscope's internal clock, or from a
% computer subsequently used to copy the files. The value will be
% locale-dependent.
%
% EXAMPLES:
% 1. data = isfread('TEK00000.ISF');
% plot(data.x,data.y);
%
% 3. data = isfread('*.ISF');
% plot([data.x], [data.y]);
% legend([data.datetime]);
%
% This function is based on <a
% href="matlab:web('http://www.mathworks.com/matlabcentral/fileexchange/6247')">isfread</a> by John Lipp.
%
% See also
% Programmer Manual for Tektronix TDS 340A, TDS 360 and TDS 380 Digital
% Real-Time Oscilloscopes (070-9442-02).
%
% Iain Robinson, School of Geosciences, University of Edinburgh.
% 2012-09-08
%ISFREAD 读取 Tektronix ISF 文件。
% DATA = ISFREAD(FILENAME) 读取由 FILENAME 指定的 Tektronix ISF 文件
% 并返回一个包含数据和头信息的结构体。
%
% DATA = ISFREAD(DIRECTORY) 读取指定目录中所有扩展名为 '.ISF' 或
% '.isf' 的文件,并返回一个包含数据和头信息的结构体数组。如果读取了 n 个文件,结构体
% 数组的大小将为 1xn。
%
% DATA = ISFREAD(PATTERN) 读取与指定 PATTERN 匹配的文件。
% PATTERN 可以是一个通配符,例如 '*.ISF'。它返回一个包含数据和头信息的结构体数组。
% 每读取一个文件就有一个元素。如果读取了 n 个文件,结构体数组的大小将为 1xn。
%
% ISF 是 Tektronix 示波器使用的一种内部数据格式的名称。
% 这些文件由一个短文本头和随后的二进制数据组成。
%
% 该函数编写是为了读取由 TDS 360 示波器保存的数据,但可能适用于使用 ISF 格式的其他型号。
% 通过在示波器上以逗号分隔值 (CSV) 格式和 ISF 格式保存相同的波形,然后比较 CSV
% 数据和 ISFREAD 返回的数据来测试此函数。
%
% DATA 结构体包含以下字段:
% filename
% datetime
% header
% x
% y
%
% datetime 字段是文件的修改日期和时间。这个日期和时间可能来源于示波器的内部时钟,或者是
% 后来用于复制文件的计算机。该值将依赖于地区设置。
%
% 示例:
% 1. data = isfread('TEK00000.ISF');
% plot(data.x,data.y);
%
% 3. data = isfread('*.ISF');
% plot([data.x], [data.y]);
% legend([data.datetime]);
%
% 该函数基于 John Lipp 的 <a
% href="matlab:web('http://www.mathworks.com/matlabcentral/fileexchange/6247')">isfread</a>。
%
% 另见
% Tektronix TDS 340A, TDS 360 和 TDS 380 数字实时示波器程序员手册 (070-9442-02)。
%
% Iain Robinson, 地球科学学院,爱丁堡大学。
% 2024-04-12 年 wifiaa 翻译 修正
if ~exist('pattern', 'var')
error('No file name, directory or pattern was specified.');
end
% Check whether pattern is a folder.
if( exist(pattern, 'dir') )
folder = pattern;
% Get a list of all files that have the extension '.isf' or '.ISF'.
files = [ dir(fullfile(folder, '*.ISF')); dir(fullfile(folder, '*.isf')) ];
else
% The pattern is not a folder, so must be a file name or a pattern with
% wildcards (such as 'Traces/TEK0*.ISF').
[folder, ~, ~] = fileparts(pattern);
% Get a list of all files and folders which match the pattern...
filesAndFolders = dir(pattern);
% ...then exclude the folders, to get just a list of files.
files = filesAndFolders(~[filesAndFolders.isdir]);
end
% Get the file names (without folders), and modification datetimes.
fileNames = {files.name};
datetimes = datestr([files.datenum]);
if numel(fileNames)==0
error('The pattern did not match any file or files: %s', pattern);
end
for s=1:numel(fileNames)
fileName = fileNames{s};
fullFileName = fullfile(folder, fileName);
% Check the file exists.
if( ~exist(fullFileName, 'file') )
error('The file does not exist: %s', fullFileName);
end
% Open the file.
fileID = fopen( fullfile(folder, fileName), 'r');
if (fileID == -1)
error('The file exists, but could not be opened: %s', fullFileName);
end
% Read the text header into a variable called 'h'. The loop reads the
% file character-by-character into h until h finishes with the
% characters ":CURVE #".
h = [];
%while( (numel(h) < 7) || ~strcmp('CURVE #', h(end-6:end)) )
while( (numel(h) < 7) || ~strcmp('CURV #', h(end-5:end)) )
% If the end of the file has been reached something is wrong.
if( feof(fileID) )
error('The end of the file %s was reached whilst still reading the header. This suggests that it is not a Tektronix ISF file.', fileName);
end
c = char( fread(fileID, 1, 'char') );
h = [h, c];
end
% Parse the header
header.BYT_NR = str2double( regexp(h, 'BYT_N\s+(\d+)', 'once', 'tokens') ); % 二进制字段数据的宽度
header.BIT_NR = str2double( regexp(h, 'BIT_N\s+(\d+)', 'once', 'tokens') ); % 每个二进制波形点的位数
header.ENCDG = char( regexp(h, 'ENC\s+(.*?)\s*[;:]', 'once', 'tokens') ); % 波形数据的编码类型
header.BN_FMT = char( regexp(h, 'BN_F\s+(.*?)\s*[;:]', 'once', 'tokens') ); % 二进制数据的格式
header.BYT_OR = char( regexp(h, 'BYT_O\s+(.*?)\s*[;:]', 'once', 'tokens') ); % 二进制数据的字节顺序
header.WFID = char(regexp(h, 'WFI\s+"*\s*(.*?)\s*"*[;:]', 'once', 'tokens') ); % 波形标识符
header.NR_PT = str2double( regexp(h, 'NR_P\s+(\d+)', 'once', 'tokens') ); % 波形点的数量
header.PT_FMT = char( regexp(h, 'PT_F\s+(.*?)\s*[;:]', 'once', 'tokens') ); % 点格式,例如 'ENV' 表示信封对,'Y' 表示普通数据点
header.XUNIT = char( regexp(h, 'XUN\s+"*(.*?)"*[;:]', 'once', 'tokens')); % 水平单位
header.XINCR = str2double( regexp(h, 'XIN\s+([-\+\d\.eE]+)', 'once', 'tokens') ); % 水平采样间隔
header.PT_OFF = str2double( regexp(h, 'PT_O\s+([-\+\d\.eE]+)', 'once', 'tokens') ); % 波形记录中的触发点
header.YUNIT = char( regexp(h, 'YUN\s+"*(.*?)"*[;:]', 'once', 'tokens') ); % 波形数据的垂直单位
header.YMULT = str2double( regexp(h, 'YMU\s+([-\+\d\.eE]+)', 'once', 'tokens') ); % 垂直比例因子
header.YOFF = str2double( regexp(h, 'YOF\s+([-\+\d\.eE]+)', 'once', 'tokens') ); % 垂直分量的偏移量
header.YZERO = str2double( regexp(h, 'YZE\s+([-\+\d\.eE]+)', 'once', 'tokens') ); % 偏移量
% In addition, some header fields are described in the Programmer
% Manual, but do not seem to appear in any of my files: XMULT, XOFF,
% XZERO, ZMULT, ZOFF, ZUNIT and ZZERO.
% Check that at least some part of the header was parsed.
if isempty(header.BYT_NR)
warning('Failed to read some part of, or possibly all of, the header in the file %s.', fileName);
end
% The next few characters in the file give the number of bytes in the
% waveform data. The first digit, referred to as 'x' on page 2-60 of
% the Programmer Manual, gives the number of bytes that immediately
% follow giving the value 'y', where 'y' is the number of bytes in the
% waveform. The manual explains it better than I can.
xBytes = str2double( char( fread(fileID, 1, 'char') ) );
yBytes = str2double( char( fread(fileID, xBytes, 'char') ) );
% For some reason there is an offset of 1 byte in reading the data
% files. I don't know why, but I found I could fix it by moving the
% file position back by one byte.
fseek(fileID, -1, 'cof');
% Read the waveform.
% For some oscilloscopes it may be necessary to add 'ieee-be' to the
% fread statement below. See the comments here:
% http://www.mathworks.co.uk/matlabcentral/fileexchange/6247-isfread
% [binaryData, count] = fread(fileID, yBytes/2, 'int16');
[binaryData, count] = fread(fileID, yBytes, 'int8');
% Check that the expected number of points have been read.
if(count ~= header.NR_PT)
error('According to the header, the file %s contains %d points, but only %d were read.', fileName, header.NR_PT, count);
end
% Check that there is no leftover data. I found that there generally
% is.
if( ~feof(fileID) )
warning('All expected data was read from %s, but there still appears to be data remaining.', fileName);
end
% Calculate the horizontal (x) and vertical (y) values. These equations
% are given on page 2-171 of the Programmer Manual.
n = (1:header.NR_PT)';
x = header.XINCR * (n - header.PT_OFF);
y = header.YZERO + header.YMULT * (binaryData - header.YOFF);
% Close the file.
fclose(fileID);
% Copy the data into a structure.
data(s).filename = fileNames{s};
data(s).datetime = datetimes(s,:);
data(s).header = header;
data(s).x = x;
data(s).y = y;
end
end