Files
nappMATLAB-toolbox/import/issFlowImportData.m
T

105 lines
4.5 KiB
Matlab

function tbl = issFlowImportData(fullFileName)
%FLOWIMPORTDATA Import the MFC flow-log channels from a new-format LabView file.
%
% tbl = flowImportData(fullFileName) reads the mid-2026 LabView chamber log
% (tab-delimited, 2 header lines, ISO-8859-1) and returns a table of the
% 7 MFC flow channels:
% datetime - absolute time (date + time columns)
% MFC4 .. MFC10 - one column per mass-flow controller, named by its
% physical MFC number (as on the gas panel).
% MFC4 [l/min] - cryo cooling flow (the old "flow cryo" channel)
% MFC5..MFC10 [sccm] - dosing/carrier gas flows (the old flow1..flow6)
%
% MFC <-> COLUMN MAPPING
% The file's header line 1 names 7 controllers in order (MFC4..MFC10,
% with a gas type each), and the data columns log 7 flow channels in the
% same order (flow-cryo, then flow1..flow6). This function maps them
% 1:1 by that shared order:
% MFC4 <- "flow cryo (l/min)" (col 9)
% MFC5 <- "flow1 (sccm)" (col 11)
% MFC6 <- "flow2 (sccm)" (col 12)
% MFC7 <- "flow3 (sccm)" (col 13)
% MFC8 <- "flow4 (sccm)" (col 14)
% MFC9 <- "flow5 (sccm)" (col 15)
% MFC10 <- "flow6 (sccm)" (col 16)
% This is an ORDER-MATCH inference (the file does not literally print
% "flow3 = MFC7"), so double-check it once against the gas panel /
% LabView front panel if in doubt. The parsed gas type per MFC (from the
% header) is stored in tbl.Properties.UserData.mfcMap for that check.
%
% OUTPUT
% tbl.Properties.UserData.mfcMap - table with MFC, SourceColumn, Gas,
% Unit, MfcVarName for all 7 channels
% (for verification and lookup)
%
% EXAMPLE
% tbl = flowImportData('01-07-2026_11-28datafile.txt');
% tbl.Properties.UserData.mfcMap % inspect / verify the mapping
% ax = plotFlowData(tbl, [4 7 10]); % plot by MFC number
% ax = plotFlowData(tbl, 'flow3'); % or by the raw logged tag
%
% See also PLOTFLOWDATA, LABVIEW_IMPORTDATA
lines = readlines(fullFileName, 'Encoding', 'ISO-8859-1');
lines = lines(strlength(lines) > 0); % drop trailing blank from final CRLF
if numel(lines) < 3
error('flowImportData:tooShort', 'File does not look like a valid log.');
end
hdr1 = lines(1); % gas name line
hdr2 = lines(2); % column names
data = lines(3:end);
if ~contains(hdr2, 'pressure_cell') && ~contains(hdr1, 'gas name')
error('flowImportData:wrongFormat', ...
'This does not look like the new-format LabView file (no "gas name"/"pressure_cell" header found).');
end
%--- Parse gas names/types from header line 1: "gas name MFCn:Gas" ---
tok = regexp(hdr1, 'gas name (MFC\d+):(\S+)', 'tokens');
mfcNum = cellfun(@(t) str2double(erase(t{1},'MFC')), tok);
gasType = cellfun(@(t) string(t{2}), tok);
[mfcNum, order] = sort(mfcNum);
gasType = gasType(order);
if numel(mfcNum) ~= 7
warning('flowImportData:unexpectedMfcCount', ...
'Expected 7 named MFCs in the header, found %d. Mapping may be wrong.', numel(mfcNum));
end
%--- Parse the data rows ---
parts = split(data, sprintf('\t'));
if size(parts, 2) < 16
error('flowImportData:tooFewColumns', 'Fewer columns than expected in data rows.');
end
dateStr = parts(:,1);
timeStr = parts(:,2);
dt = datetime(strcat(dateStr, timeStr), 'InputFormat', 'dd.MM.yyyyHH:mm:ss');
flowCryo = str2double(parts(:,9)); % "flow cryo (l/min)"
flowN = str2double(parts(:,11:16)); % flow1..flow6 (sccm)
%--- Order-matched MFC <-> column mapping ---
columnData = [{flowCryo}, num2cell(flowN,1)]; % 1x7 cell of column vectors
columnNames = {'flowCryo','flow1','flow2','flow3','flow4','flow5','flow6'};
columnUnits = [{'l/min'}, repmat({'sccm'}, 1, 6)];
tbl = table(dt, 'VariableNames', {'datetime'});
nCh = min(7, numel(mfcNum));
mfcVarNames = strings(1, nCh);
for k = 1:nCh
varName = sprintf('MFC%d', mfcNum(k));
tbl.(varName) = columnData{k};
mfcVarNames(k) = varName;
end
mfcMap = table(mfcNum(1:nCh)', columnNames(1:nCh)', gasType(1:nCh)', columnUnits(1:nCh)', ...
'VariableNames', {'MFC','SourceColumn','Gas','Unit'});
mfcMap.MfcVarName = cellstr(mfcVarNames(:));
tbl.Properties.VariableUnits = [{''}, columnUnits(1:nCh)];
tbl.Properties.UserData = struct('mfcMap', mfcMap);
end