98 lines
3.7 KiB
Matlab
98 lines
3.7 KiB
Matlab
function tbl = rgaImportData(fullFileName)
|
|
%RGAIMPORTDATA Import an SRS RGA "Pressure vs Time" scan (.txt) into a table.
|
|
%
|
|
% tbl = rgaImportData(fullFileName) reads an RGA ASCII log and returns a
|
|
% table ready for plotRgaData, with:
|
|
% datetime - absolute time (start time + Time(s))
|
|
% time_s - elapsed scan time in seconds
|
|
% one column per active channel, named <Name>_m<mass> (e.g. Water_m18),
|
|
% holding the partial pressure in the file's units (usually Torr).
|
|
%
|
|
% The scan units and channel metadata are stored in
|
|
% tbl.Properties.VariableUnits and tbl.Properties.UserData.
|
|
%
|
|
% Two quirks of this file format are handled:
|
|
% * multi-word species names in the channel table (e.g. "Carbn dio")
|
|
% * adjacent negative values in the data run together with no space
|
|
% (e.g. "-2.8663e-010-2.3529e-010"); values are recovered by matching
|
|
% scientific-notation tokens rather than by splitting on whitespace.
|
|
%
|
|
% EXAMPLE
|
|
% tbl = rgaImportData('rga1_Jul_01_2026_08-23-06_AM.txt');
|
|
% ax = plotRgaData(tbl);
|
|
%
|
|
% See also PLOTRGADATA, PLOTCRYODATA
|
|
|
|
lines = readlines(fullFileName); % string array, keeps blanks
|
|
|
|
%--- Locate the data block header "Time(s) Channel#1 ..." ---
|
|
iData = find(startsWith(strip(lines),'Time(s)'), 1);
|
|
if isempty(iData)
|
|
error('rgaImportData:noData','Could not find the "Time(s)" data header.');
|
|
end
|
|
header = lines(1:iData-1); % metadata + channel table
|
|
|
|
%--- Start time (absolute) ---
|
|
iStart = find(startsWith(strip(header),'Start time,'), 1);
|
|
if isempty(iStart)
|
|
startStr = strip(header(1)); % fall back to first line
|
|
else
|
|
startStr = strip(extractAfter(header(iStart),','));
|
|
end
|
|
startStr = regexprep(startStr,'\s+',' '); % collapse the double space
|
|
startTime = datetime(startStr, ...
|
|
'InputFormat','MMM d, yyyy h:mm:ss a', 'Locale','en_US');
|
|
|
|
%--- Units ---
|
|
units = 'a.u.';
|
|
iu = find(startsWith(strip(header),'Units,'), 1);
|
|
if ~isempty(iu)
|
|
p = strip(split(header(iu),','));
|
|
units = char(p(end));
|
|
end
|
|
|
|
%--- Channel definitions (e.g. "1 28.00 Nitrogen 1.00 3 OFF") ---
|
|
chanPat = '^\s*(\d+)\s+([\d.]+)\s+(.+?)\s+[\d.]+\s+\d+\s+\w+\s*$';
|
|
tok = regexp(header, chanPat, 'tokens', 'once');
|
|
tok = tok(~cellfun(@isempty, tok));
|
|
nCh = numel(tok);
|
|
if nCh == 0
|
|
error('rgaImportData:noChannels','No channel definitions found.');
|
|
end
|
|
chMass = zeros(nCh,1); chName = strings(nCh,1);
|
|
for k = 1:nCh
|
|
chMass(k) = str2double(tok{k}{2});
|
|
chName(k) = strip(string(tok{k}{3}));
|
|
end
|
|
|
|
%--- Data: time before the comma + N scientific-notation values ---
|
|
dataLines = lines(iData+1:end);
|
|
dataLines = dataLines(strlength(strip(dataLines)) > 0);
|
|
n = numel(dataLines);
|
|
|
|
time_s = str2double(extractBefore(dataLines, ','));
|
|
matches = regexp(dataLines, '[-+]?\d+\.\d+[eE][-+]?\d+', 'match');
|
|
|
|
vals = nan(n, nCh);
|
|
for r = 1:n
|
|
v = str2double(matches{r});
|
|
nn = min(numel(v), nCh);
|
|
vals(r,1:nn) = v(1:nn);
|
|
end
|
|
|
|
%--- Assemble table ---
|
|
dt = startTime + seconds(time_s);
|
|
varNames = arrayfun(@(k) matlab.lang.makeValidName( ...
|
|
sprintf('%s_m%d', chName(k), round(chMass(k)))), 1:nCh, 'UniformOutput', false);
|
|
|
|
tbl = table(dt, time_s, 'VariableNames', {'datetime','time_s'});
|
|
for k = 1:nCh
|
|
tbl.(varNames{k}) = vals(:,k);
|
|
end
|
|
|
|
tbl.Properties.VariableUnits = [{'', 's'}, repmat({char(units)}, 1, nCh)];
|
|
tbl.Properties.UserData = struct( ...
|
|
'units', char(units), 'startTime', startTime, ...
|
|
'channelName', chName, 'channelMass', chMass);
|
|
end
|