ISS 2.0 ready
This commit is contained in:
1 parent
9d6d271461
commit
3ad96b3890
7 files changed
+609
-202
No files matched your search
@@ -1,7 +1,7 @@
|
||||
function LabView = LabView_importData(fullFileName,varargin)
|
||||
%
|
||||
% LabView_importData reads data log ASCII files stored by LabView into
|
||||
% a Matlab time series.
|
||||
% a Matlab time series.
|
||||
%
|
||||
% LabView = LabView_importData(A) imports file A
|
||||
% and stores its content as time series in a structure called "LabView".
|
||||
@@ -77,6 +77,64 @@ addOptional(p,'appendToStructure',defaultAppendToStructure,@isstruct);
|
||||
% Parse the inputs.
|
||||
parse(p,fullFileName,varargin{:})
|
||||
|
||||
%% =====================================================================
|
||||
% NEW FILE FORMAT (added 2026-07-02)
|
||||
% ---------------------------------------------------------------------
|
||||
% Detect the mid-2026 LabView format from its header and import it here,
|
||||
% then return early so none of the older-format logic below is touched.
|
||||
% New file: ISO-8859-1 encoded, 2 header lines, tab-delimited, 16 data
|
||||
% columns + trailing tab, CRLF. The temperature column is written
|
||||
% corrupted as "<int>NaN" (e.g. "-8NaN"); the leading integer is the real
|
||||
% ice-sample temperature. Channels no longer logged are filled with NaN so
|
||||
% the output keeps the same 13-column ts.Data layout, field naming and
|
||||
% .Name as older files.
|
||||
% col 3 pressure_cell (hPa) -> ts.Data:4 col 4 temperature -> ts.Data:1
|
||||
% col 5-7 x/y/z (mm) -> ts.Data:10-12 col 8 Tsealing -> ts.Data:13
|
||||
% col 9 flow cryo (l/min) -> ts.Data:7
|
||||
% =====================================================================
|
||||
keepTemperatureInteger = true; % true: use leading integer of "-8NaN"; false: NaN
|
||||
|
||||
if isstruct(p.Results.appendToStructure)
|
||||
LabView = p.Results.appendToStructure;
|
||||
end
|
||||
|
||||
fidChk = fopen(p.Results.fullFileName,'r','n','ISO-8859-1');
|
||||
hdrLine1 = fgetl(fidChk);
|
||||
hdrLine2 = fgetl(fidChk);
|
||||
fclose(fidChk);
|
||||
|
||||
if (ischar(hdrLine2) && contains(hdrLine2,'pressure_cell')) || ...
|
||||
(ischar(hdrLine1) && contains(hdrLine1,'gas name'))
|
||||
|
||||
fid = fopen(p.Results.fullFileName,'r','n','ISO-8859-1');
|
||||
data = textscan(fid, ...
|
||||
'%s %s %f %s %f %f %f %f %f %f %f %f %f %f %f %f %*s', ...
|
||||
'HeaderLines', 2, 'Delimiter', '\t', 'EndOfLine', '\r\n');
|
||||
fclose(fid);
|
||||
|
||||
if keepTemperatureInteger
|
||||
temperature = cellfun(@(s) str2double(regexp(s,'^-?\d+','match','once')), data{4});
|
||||
else
|
||||
temperature = nan(numel(data{4}),1);
|
||||
end
|
||||
|
||||
nanCol = nan(numel(data{3}),1);
|
||||
|
||||
tsName = ['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})], ...
|
||||
'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')];
|
||||
|
||||
LabView.(tsName) = timeseries( ...
|
||||
[ temperature nanCol nanCol data{3} nanCol nanCol data{9} ...
|
||||
nanCol nanCol data{5} data{6} data{7} data{8} ], ...
|
||||
datestr(datenum([char(data{1}), char(data{2})],'dd.mm.yyyyHH:MM:SS'),0));
|
||||
LabView.(tsName).Name = 'Readout Napp Chamber raw signal';
|
||||
|
||||
clearvars fid data temperature nanCol tsName hdrLine1 hdrLine2 fidChk ...
|
||||
keepTemperatureInteger
|
||||
return
|
||||
end
|
||||
%% =====================================================================
|
||||
|
||||
%%
|
||||
% get filedate
|
||||
[~,name,~] = fileparts(p.Results.fullFileName);
|
||||
@@ -93,7 +151,7 @@ if isstruct(p.Results.appendToStructure)
|
||||
end
|
||||
%%
|
||||
if datenum(filedate) <= datenum('04-Mar-2019 13:30:00')
|
||||
|
||||
|
||||
fid = fopen(p.Results.fullFileName);
|
||||
data = textscan(fid, ...
|
||||
'%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
@@ -109,49 +167,73 @@ if datenum(filedate) <= datenum('04-Mar-2019 13:30:00')
|
||||
= 'Readout Napp Chamber raw signal';
|
||||
clear fid ans formatOut nans t x
|
||||
|
||||
elseif datenum(filedate) >= datenum('15-Sep-2021 01:00:00')
|
||||
|
||||
elseif datenum(filedate) >= datenum('15-Sep-2021 01:00:00') && datenum(filedate) <= datenum('01-Apr-2023 01:00:00')
|
||||
% during this time, date and time were in american format.
|
||||
fid = fopen(p.Results.fullFileName);
|
||||
data = textscan(fid, ...
|
||||
'%s %s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
'HeaderLines',1); %
|
||||
|
||||
'HeaderLines',1); %
|
||||
|
||||
fclose(fid);
|
||||
% the date formating in the dat file is really messed up. Try to make
|
||||
% it consitent with MATLAB. The problem is that MATLAB does not
|
||||
% understand 1 digit month and hours.
|
||||
%
|
||||
%
|
||||
%
|
||||
% Split the date in column 1 into year,month,day
|
||||
newDateSplit = cellfun(@(x) split(char(x),'/'),data{1},'UniformOutput', false);
|
||||
% Split the time in column 2 into hours, minutes, seconds
|
||||
newTimeSplit = cellfun(@(x) split(char(x),':'),data{2},'UniformOutput', false);
|
||||
% combine both with the am/pm string in column 3 to a new datestring
|
||||
customDateStr = cellfun(@(x,y,z) [datestr(datenum([str2double(x{3}),str2double(x{1}),str2double(x{2}),str2double(y{1}),str2double(y{2}),str2double(y{3})])), ' ', char(z)], newDateSplit,newTimeSplit,data{3}, 'uniformOutput',false) ;
|
||||
% define time series
|
||||
|
||||
% define time series
|
||||
LabView.(['ts_' datestr(customDateStr{1},'YYYYmmdd_HHMM')]) ...
|
||||
= timeseries([data{10} data{4} data{5} data{6} data{12} ...
|
||||
data{13} data{14} data{7} data{8} data{17} data{18} data{19} data{21}], ...
|
||||
data{13} data{14} data{7} data{8} data{17} data{18} data{19} data{21}], ...
|
||||
customDateStr);
|
||||
LabView.(['ts_' datestr(customDateStr{1},'YYYYmmdd_HHMM')]).Name ...
|
||||
= 'Readout Napp Chamber raw signal';
|
||||
clearvars fid ans formatOut nans t x new* custom*
|
||||
|
||||
|
||||
elseif datenum(filedate) >= datenum('01-Apr-2023 02:00:00')
|
||||
|
||||
fid = fopen(p.Results.fullFileName);
|
||||
data = textscan(fid, ...
|
||||
'%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
'HeaderLines',1);
|
||||
% data file has 2 text columns, followed by 18 numeric columns (THE AM
|
||||
% PM IS MISSING and some changes to the LabView file. Confirm with Luca....)
|
||||
fclose(fid);
|
||||
% define time series
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
= timeseries([data{9} data{3} data{4} data{5} data{11} ...
|
||||
data{12} data{20} data{6} data{7} data{15} data{16} data{17} data{19}] , ...
|
||||
datestr(datenum([char(data{1}), char(data{2})],...
|
||||
'dd.mm.yyyyHH:MM:SS'),0));
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]).Name ...
|
||||
= 'Readout Napp Chamber raw signal';
|
||||
clear fid ans formatOut nans t x
|
||||
|
||||
else
|
||||
fid = fopen(p.Results.fullFileName);
|
||||
data = textscan(fid, ...
|
||||
'%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
'HeaderLines',1); % data file has 2 text columns, followed by 16 numeric columns
|
||||
'HeaderLines',1); % data file has 2 text columns, followed by 14 numeric columns
|
||||
fclose(fid);
|
||||
% define time series
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
= timeseries([data{9} data{3} data{4} data{5} data{11} ...
|
||||
data{12} data{13} data{6} data{7} data{16} data{17} data{18} data{20}] , ...
|
||||
datestr(datenum([char(data{1}), char(data{2})],...
|
||||
'dd.mm.yyyyHH:MM:SS'),0));
|
||||
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
= timeseries([data{9} data{3} data{4} data{5} data{11} ...
|
||||
data{12} data{13} data{6} data{7} data{16} data{17} data{18} data{20}] , ...
|
||||
datestr(datenum([char(data{1}), char(data{2})],...
|
||||
'dd.mm.yyyyHH:MM:SS'),0));
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]).Name ...
|
||||
= 'Readout Napp Chamber raw signal';
|
||||
clear fid ans formatOut nans t x
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -29,7 +29,7 @@ function createBeamtimeFolder(projectName)
|
||||
|
||||
% List of subfolders to create
|
||||
subFolders = {'Analysis', 'Images', 'LabBook', 'NEXAFS', ...
|
||||
'Photos', 'pressure', 'PShell', 'RGA', 'SES'};
|
||||
'Photos', 'Pressure', 'PShell', 'RGA', 'SES'};
|
||||
|
||||
% Create main project folder
|
||||
if ~exist(projectRoot, 'dir')
|
||||
|
||||
@@ -140,7 +140,7 @@ tmpFitParameters.backgroundRange = [12 6]; % <- selects fit range aro
|
||||
% Bounds for background
|
||||
tmpFitParameters.bkgrd = [0 0];
|
||||
tmpFitParameters.pbkgrdLowerBound = [0 0];
|
||||
tmpFitParameters.bkgrdUpperBound = [0 0];
|
||||
tmpFitParameters.bkgrdUpperBound = [0 0];
|
||||
|
||||
FitList = nappFitGaussXps(FitList,tmpFitParameters,tmpDataSelection,...
|
||||
'tableVariable','spectrum_countsNorm','energyScale','kinetic',...
|
||||
@@ -283,6 +283,63 @@ tmpFitParameters.backgroundRange = [12 6];
|
||||
FitList = nappFitGaussXps(FitList,tmpFitParameters,tmpDataSelection,...
|
||||
'tableVariable','spectrum_counts','energyScale','binding',...
|
||||
'mode','unconstrained','backgroundMode','linear','showFigures','on');
|
||||
|
||||
%% TEST 1.5.3: Split unconstrained binding Gauss linear
|
||||
% Gaussian + Linear, individual area/width/position per peak
|
||||
|
||||
|
||||
% peak #1 -> Write into FitList
|
||||
clearvars tmpFitParameters;
|
||||
clc
|
||||
tmpFitParameters.peakArea = 1e5;
|
||||
tmpFitParameters.peakWidth = 1.6;
|
||||
tmpFitParameters.peakPos = 38;
|
||||
% Bounds for areas (lower and upper)
|
||||
tmpFitParameters.peakAreaLowerBound = 0.01;
|
||||
tmpFitParameters.peakAreaUpperBound = Inf;
|
||||
% Bounds for widths
|
||||
tmpFitParameters.peakWidthLowerBound = 0.2;
|
||||
tmpFitParameters.peakWidthUpperBound = 2.0;
|
||||
% Bounds for positions
|
||||
tmpFitParameters.peakPosLowerBound = 37;
|
||||
tmpFitParameters.peakPosUpperBound = 39;
|
||||
% fit range
|
||||
tmpFitParameters.backgroundRange = [1 5];
|
||||
% fit
|
||||
FitList = nappFitGaussXps(FitList,tmpFitParameters,tmpDataSelection,...
|
||||
'tableVariable','spectrum_counts','energyScale','binding',... % <- process binding energy
|
||||
'mode','unconstrained','backgroundMode','linear','showFigures','on');
|
||||
% peak #2 -> Write into new list, then copy to FitList
|
||||
clearvars tmpFitParameters;
|
||||
clc
|
||||
tmpFitParameters.peakArea = 1e5;
|
||||
tmpFitParameters.peakWidth = 1.6;
|
||||
tmpFitParameters.peakPos = 36;
|
||||
% Bounds for areas (lower and upper)
|
||||
tmpFitParameters.peakAreaLowerBound = 0.01;
|
||||
tmpFitParameters.peakAreaUpperBound = Inf;
|
||||
% Bounds for widths
|
||||
tmpFitParameters.peakWidthLowerBound = 0.2;
|
||||
tmpFitParameters.peakWidthUpperBound = 2.0;
|
||||
% Bounds for positions
|
||||
tmpFitParameters.peakPosLowerBound = 35;
|
||||
tmpFitParameters.peakPosUpperBound = 37;
|
||||
% fit range
|
||||
tmpFitParameters.backgroundRange = [5 1];
|
||||
% fit
|
||||
FitListTmp = nappFitGaussXps(FitList,tmpFitParameters,tmpDataSelection,...
|
||||
'tableVariable','spectrum_counts','energyScale','binding',... % <- process binding energy
|
||||
'mode','unconstrained','backgroundMode','linear','showFigures','on');
|
||||
|
||||
% merge fit results
|
||||
disp(FitList(tmpDataSelection,{'name','peakPosition'}))
|
||||
disp(FitListTmp(tmpDataSelection,{'name','peakPosition'}))
|
||||
FitList(tmpDataSelection,:).peakPosition(2) = FitListTmp(tmpDataSelection,:).peakPosition(1);
|
||||
FitList(tmpDataSelection,:).peakArea(2) = FitListTmp(tmpDataSelection,:).peakArea(1);
|
||||
FitList(tmpDataSelection,:).peakFWHM(2) = FitListTmp(tmpDataSelection,:).peakFWHM(1);
|
||||
clearvars FitListTmp
|
||||
disp(FitList(tmpDataSelection,{'name','peakPosition'}))
|
||||
|
||||
%% TEST 1.6: Unconstrained binding PV linear
|
||||
% Pseudo-Voigt + Linear, individual area/width/eta/position per peak
|
||||
|
||||
|
||||
+191
-182
@@ -1281,7 +1281,16 @@ if matches(p.Results.importLabView,'on')
|
||||
|
||||
try
|
||||
% Get list of all files in that folder
|
||||
TmpFileList = dir([dataPath_LabView filesep '**' filesep 'logfile*.txt']);
|
||||
TmpFileList = [ ...
|
||||
dir([dataPath_LabView filesep '**' filesep 'logfile*.txt']); ...
|
||||
dir([dataPath_LabView filesep '**' filesep '*datafile.txt'])];
|
||||
if ~isempty(TmpFileList)
|
||||
keep = ~startsWith({TmpFileList.name}, {'.','~'}) & ...
|
||||
~startsWith({TmpFileList.name}, 'LabView_T_RH', 'IgnoreCase', true);
|
||||
TmpFileList = TmpFileList(keep);
|
||||
[~, iu] = unique(fullfile({TmpFileList.folder}, {TmpFileList.name}), 'stable');
|
||||
TmpFileList = TmpFileList(iu);
|
||||
end
|
||||
|
||||
% import LabView data
|
||||
LabView = LabView_importData(fullfile(TmpFileList(1).folder,TmpFileList(1).name)); % Overwrite LabView data in workspace, if this is the first import
|
||||
@@ -1509,187 +1518,187 @@ disp('*************************************************')
|
||||
|
||||
end
|
||||
|
||||
function LabView = LabView_importData(fullFileName,varargin)
|
||||
%
|
||||
% LabView_importData reads data log ASCII files stored by LabView into
|
||||
% a Matlab time series.
|
||||
%
|
||||
% LabView = LabView_importData(A) imports file A
|
||||
% and stores its content as time series in a structure called "LabView".
|
||||
%
|
||||
% LabView = LabView_importData(A,LabView) imports file A
|
||||
% and appends its content as time series to the LabView structure.
|
||||
%
|
||||
%
|
||||
% Example
|
||||
% LabView = LabView_importData('exmpl.dat',LabView)
|
||||
%
|
||||
% Input
|
||||
% * Napp_chamber_file: Complete and absolute path to the Napp chamber log file.
|
||||
% * LabView: name of output structure. Always call this'LabView'
|
||||
%
|
||||
% Output
|
||||
% * LabView: time series, the name starting with "ts"
|
||||
% followed by date and time the recording started.
|
||||
%
|
||||
% See also LABVIEW_COMBINE, LABVIEW_PLOT, LABVIEW_CUTDATA
|
||||
%
|
||||
%% Data Structure
|
||||
%
|
||||
% Data structure before 4.3.2019
|
||||
% col 1: Date
|
||||
% col 2: Time
|
||||
% col 3: Reservoir "Pressure 1" - Unit "1 water" - mbar -> ts.Data:2
|
||||
% col 4: Reservoir "Pressure 2" - Unit "2 other" - mbar -> ts.Data:3
|
||||
% col 5: Baratron 1 - cell - 1mbar max - mbar -> ts.Data:4
|
||||
% col 6: Baratron 2 - cell - 10mbar max - mbar -> ts.Data:8
|
||||
% col 7: Baratron 3 - cell - 0.05mbar max - mbar -> ts.Data:9
|
||||
% col 8: Baratron 4 - - mbar
|
||||
% col 9: Temp.Ice Sample - °C -> ts.Data:1
|
||||
% col 10: Temp.Heated Sample
|
||||
% col 11: none
|
||||
% col 12: Temp. Reservoir "Cooler 1" - °C -> ts.Data:5
|
||||
% col 13: Temp. Reservoir "Cooler 2" - °C -> ts.Data:6
|
||||
% col 14: Flow He(cryoholder) - l/min -> ts.Data:7
|
||||
% col 15: none
|
||||
% col 16: none
|
||||
%
|
||||
% Data structure after 4.3.2019
|
||||
% col 1: Date
|
||||
% col 2: Time
|
||||
% col 3: Reservoir "Pressure 1" - Unit "1 water" - mbar -> ts.Data:2
|
||||
% col 4: Reservoir "Pressure 2" - Unit "2 other" - mbar -> ts.Data:3
|
||||
% col 5: Baratron 1 - cell - 1mbar max - mbar -> ts.Data:4
|
||||
% col 6: Baratron 2 - cell - 10mbar max - mbar -> ts.Data:8
|
||||
% col 7: Baratron 3 - cell - 0.05mbar max - mbar -> ts.Data:9
|
||||
% col 8: Baratron 4 - - mbar
|
||||
% col 9: Temp.Ice Sample - °C -> ts.Data:1
|
||||
% col 10: Temp.Heated Sample
|
||||
% col 11: Temp. Reservoir "Cooler 1" - °C -> ts.Data:5
|
||||
% col 12: Temp. Reservoir "Cooler 2" - °C -> ts.Data:6
|
||||
% col 13: Flow He(cryoholder) - l/min -> ts.Data:7
|
||||
% col 14: Flow gas 1
|
||||
% col 15: Pressure chamber - mbar
|
||||
% col 16: x-position of cryoholder - mm -> ts.Data:10
|
||||
% col 17: y-position of cryoholder - mm -> ts.Data:11
|
||||
% col 18: z-position of cryoholder - mm -> ts.Data:12
|
||||
% col 19: nothing
|
||||
% col 20: Temp.Sealing - °C -> ts.Data:13
|
||||
|
||||
|
||||
%%
|
||||
|
||||
% Create an InputParser object
|
||||
p = inputParser;
|
||||
% Add inputs to the scheme.
|
||||
defaultAppendToStructure = 0;
|
||||
addRequired(p,'fullFileName',@isfile);
|
||||
addOptional(p,'appendToStructure',defaultAppendToStructure,@isstruct);
|
||||
% Parse the inputs.
|
||||
parse(p,fullFileName,varargin{:})
|
||||
|
||||
%%
|
||||
% get filedate
|
||||
[~,name,~] = fileparts(p.Results.fullFileName);
|
||||
tmp = strsplit(name,'_PC');
|
||||
filedate = datenum(tmp{1},'yyyy-mm-dd_HH.MM.SS');
|
||||
|
||||
clearvars name tmp
|
||||
|
||||
%%
|
||||
% parse structure to append to
|
||||
|
||||
if isstruct(p.Results.appendToStructure)
|
||||
LabView = p.Results.appendToStructure;
|
||||
end
|
||||
%%
|
||||
if datenum(filedate) <= datenum('04-Mar-2019 13:30:00')
|
||||
|
||||
fid = fopen(p.Results.fullFileName);
|
||||
data = textscan(fid, ...
|
||||
'%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
'HeaderLines',1); % data file has 2 text columns, followed by 14 numeric columns
|
||||
fclose(fid);
|
||||
% define time series
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
= timeseries([data{9} data{3} data{4} data{5} data{12} ...
|
||||
data{13} data{14} data{6} data{7}] , ...
|
||||
datestr(datenum([char(data{1}), char(data{2})],...
|
||||
'dd.mm.yyyyHH:MM:SS'),0));
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]).Name ...
|
||||
= 'Readout Napp Chamber raw signal';
|
||||
clear fid ans formatOut nans t x
|
||||
|
||||
elseif datenum(filedate) >= datenum('15-Sep-2021 01:00:00') && datenum(filedate) <= datenum('01-Apr-2023 01:00:00')
|
||||
% during this time, date and time were in american format.
|
||||
fid = fopen(p.Results.fullFileName);
|
||||
data = textscan(fid, ...
|
||||
'%s %s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
'HeaderLines',1); %
|
||||
|
||||
fclose(fid);
|
||||
% the date formating in the dat file is really messed up. Try to make
|
||||
% it consitent with MATLAB. The problem is that MATLAB does not
|
||||
% understand 1 digit month and hours.
|
||||
%
|
||||
%
|
||||
% Split the date in column 1 into year,month,day
|
||||
newDateSplit = cellfun(@(x) split(char(x),'/'),data{1},'UniformOutput', false);
|
||||
% Split the time in column 2 into hours, minutes, seconds
|
||||
newTimeSplit = cellfun(@(x) split(char(x),':'),data{2},'UniformOutput', false);
|
||||
% combine both with the am/pm string in column 3 to a new datestring
|
||||
customDateStr = cellfun(@(x,y,z) [datestr(datenum([str2double(x{3}),str2double(x{1}),str2double(x{2}),str2double(y{1}),str2double(y{2}),str2double(y{3})])), ' ', char(z)], newDateSplit,newTimeSplit,data{3}, 'uniformOutput',false) ;
|
||||
|
||||
% define time series
|
||||
LabView.(['ts_' datestr(customDateStr{1},'YYYYmmdd_HHMM')]) ...
|
||||
= timeseries([data{10} data{4} data{5} data{6} data{12} ...
|
||||
data{13} data{14} data{7} data{8} data{17} data{18} data{19} data{21}], ...
|
||||
customDateStr);
|
||||
LabView.(['ts_' datestr(customDateStr{1},'YYYYmmdd_HHMM')]).Name ...
|
||||
= 'Readout Napp Chamber raw signal';
|
||||
clearvars fid ans formatOut nans t x new* custom*
|
||||
|
||||
|
||||
elseif datenum(filedate) >= datenum('01-Apr-2023 02:00:00')
|
||||
|
||||
fid = fopen(p.Results.fullFileName);
|
||||
data = textscan(fid, ...
|
||||
'%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
'HeaderLines',1);
|
||||
% data file has 2 text columns, followed by 18 numeric columns (THE AM
|
||||
% PM IS MISSING and some changes to the LabView file. Confirm with Luca....)
|
||||
fclose(fid);
|
||||
% define time series
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
= timeseries([data{9} data{3} data{4} data{5} data{11} ...
|
||||
data{12} data{20} data{6} data{7} data{15} data{16} data{17} data{19}] , ...
|
||||
datestr(datenum([char(data{1}), char(data{2})],...
|
||||
'dd.mm.yyyyHH:MM:SS'),0));
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]).Name ...
|
||||
= 'Readout Napp Chamber raw signal';
|
||||
clear fid ans formatOut nans t x
|
||||
|
||||
else
|
||||
fid = fopen(p.Results.fullFileName);
|
||||
data = textscan(fid, ...
|
||||
'%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
'HeaderLines',1); % data file has 2 text columns, followed by 14 numeric columns
|
||||
fclose(fid);
|
||||
% define time series
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
= timeseries([data{9} data{3} data{4} data{5} data{11} ...
|
||||
data{12} data{13} data{6} data{7} data{16} data{17} data{18} data{20}] , ...
|
||||
datestr(datenum([char(data{1}), char(data{2})],...
|
||||
'dd.mm.yyyyHH:MM:SS'),0));
|
||||
|
||||
LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]).Name ...
|
||||
= 'Readout Napp Chamber raw signal';
|
||||
clear fid ans formatOut nans t x
|
||||
end
|
||||
end
|
||||
% function LabView = LabView_importData(fullFileName,varargin)
|
||||
% %
|
||||
% % LabView_importData reads data log ASCII files stored by LabView into
|
||||
% % a Matlab time series.
|
||||
% %
|
||||
% % LabView = LabView_importData(A) imports file A
|
||||
% % and stores its content as time series in a structure called "LabView".
|
||||
% %
|
||||
% % LabView = LabView_importData(A,LabView) imports file A
|
||||
% % and appends its content as time series to the LabView structure.
|
||||
% %
|
||||
% %
|
||||
% % Example
|
||||
% % LabView = LabView_importData('exmpl.dat',LabView)
|
||||
% %
|
||||
% % Input
|
||||
% % * Napp_chamber_file: Complete and absolute path to the Napp chamber log file.
|
||||
% % * LabView: name of output structure. Always call this'LabView'
|
||||
% %
|
||||
% % Output
|
||||
% % * LabView: time series, the name starting with "ts"
|
||||
% % followed by date and time the recording started.
|
||||
% %
|
||||
% % See also LABVIEW_COMBINE, LABVIEW_PLOT, LABVIEW_CUTDATA
|
||||
% %
|
||||
% %% Data Structure
|
||||
% %
|
||||
% % Data structure before 4.3.2019
|
||||
% % col 1: Date
|
||||
% % col 2: Time
|
||||
% % col 3: Reservoir "Pressure 1" - Unit "1 water" - mbar -> ts.Data:2
|
||||
% % col 4: Reservoir "Pressure 2" - Unit "2 other" - mbar -> ts.Data:3
|
||||
% % col 5: Baratron 1 - cell - 1mbar max - mbar -> ts.Data:4
|
||||
% % col 6: Baratron 2 - cell - 10mbar max - mbar -> ts.Data:8
|
||||
% % col 7: Baratron 3 - cell - 0.05mbar max - mbar -> ts.Data:9
|
||||
% % col 8: Baratron 4 - - mbar
|
||||
% % col 9: Temp.Ice Sample - °C -> ts.Data:1
|
||||
% % col 10: Temp.Heated Sample
|
||||
% % col 11: none
|
||||
% % col 12: Temp. Reservoir "Cooler 1" - °C -> ts.Data:5
|
||||
% % col 13: Temp. Reservoir "Cooler 2" - °C -> ts.Data:6
|
||||
% % col 14: Flow He(cryoholder) - l/min -> ts.Data:7
|
||||
% % col 15: none
|
||||
% % col 16: none
|
||||
% %
|
||||
% % Data structure after 4.3.2019
|
||||
% % col 1: Date
|
||||
% % col 2: Time
|
||||
% % col 3: Reservoir "Pressure 1" - Unit "1 water" - mbar -> ts.Data:2
|
||||
% % col 4: Reservoir "Pressure 2" - Unit "2 other" - mbar -> ts.Data:3
|
||||
% % col 5: Baratron 1 - cell - 1mbar max - mbar -> ts.Data:4
|
||||
% % col 6: Baratron 2 - cell - 10mbar max - mbar -> ts.Data:8
|
||||
% % col 7: Baratron 3 - cell - 0.05mbar max - mbar -> ts.Data:9
|
||||
% % col 8: Baratron 4 - - mbar
|
||||
% % col 9: Temp.Ice Sample - °C -> ts.Data:1
|
||||
% % col 10: Temp.Heated Sample
|
||||
% % col 11: Temp. Reservoir "Cooler 1" - °C -> ts.Data:5
|
||||
% % col 12: Temp. Reservoir "Cooler 2" - °C -> ts.Data:6
|
||||
% % col 13: Flow He(cryoholder) - l/min -> ts.Data:7
|
||||
% % col 14: Flow gas 1
|
||||
% % col 15: Pressure chamber - mbar
|
||||
% % col 16: x-position of cryoholder - mm -> ts.Data:10
|
||||
% % col 17: y-position of cryoholder - mm -> ts.Data:11
|
||||
% % col 18: z-position of cryoholder - mm -> ts.Data:12
|
||||
% % col 19: nothing
|
||||
% % col 20: Temp.Sealing - °C -> ts.Data:13
|
||||
%
|
||||
%
|
||||
% %%
|
||||
%
|
||||
% % Create an InputParser object
|
||||
% p = inputParser;
|
||||
% % Add inputs to the scheme.
|
||||
% defaultAppendToStructure = 0;
|
||||
% addRequired(p,'fullFileName',@isfile);
|
||||
% addOptional(p,'appendToStructure',defaultAppendToStructure,@isstruct);
|
||||
% % Parse the inputs.
|
||||
% parse(p,fullFileName,varargin{:})
|
||||
%
|
||||
% %%
|
||||
% % get filedate
|
||||
% [~,name,~] = fileparts(p.Results.fullFileName);
|
||||
% tmp = strsplit(name,'_PC');
|
||||
% filedate = datenum(tmp{1},'yyyy-mm-dd_HH.MM.SS');
|
||||
%
|
||||
% clearvars name tmp
|
||||
%
|
||||
% %%
|
||||
% % parse structure to append to
|
||||
%
|
||||
% if isstruct(p.Results.appendToStructure)
|
||||
% LabView = p.Results.appendToStructure;
|
||||
% end
|
||||
% %%
|
||||
% if datenum(filedate) <= datenum('04-Mar-2019 13:30:00')
|
||||
%
|
||||
% fid = fopen(p.Results.fullFileName);
|
||||
% data = textscan(fid, ...
|
||||
% '%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
% 'HeaderLines',1); % data file has 2 text columns, followed by 14 numeric columns
|
||||
% fclose(fid);
|
||||
% % define time series
|
||||
% LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
% = timeseries([data{9} data{3} data{4} data{5} data{12} ...
|
||||
% data{13} data{14} data{6} data{7}] , ...
|
||||
% datestr(datenum([char(data{1}), char(data{2})],...
|
||||
% 'dd.mm.yyyyHH:MM:SS'),0));
|
||||
% LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]).Name ...
|
||||
% = 'Readout Napp Chamber raw signal';
|
||||
% clear fid ans formatOut nans t x
|
||||
%
|
||||
% elseif datenum(filedate) >= datenum('15-Sep-2021 01:00:00') && datenum(filedate) <= datenum('01-Apr-2023 01:00:00')
|
||||
% % during this time, date and time were in american format.
|
||||
% fid = fopen(p.Results.fullFileName);
|
||||
% data = textscan(fid, ...
|
||||
% '%s %s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
% 'HeaderLines',1); %
|
||||
%
|
||||
% fclose(fid);
|
||||
% % the date formating in the dat file is really messed up. Try to make
|
||||
% % it consitent with MATLAB. The problem is that MATLAB does not
|
||||
% % understand 1 digit month and hours.
|
||||
% %
|
||||
% %
|
||||
% % Split the date in column 1 into year,month,day
|
||||
% newDateSplit = cellfun(@(x) split(char(x),'/'),data{1},'UniformOutput', false);
|
||||
% % Split the time in column 2 into hours, minutes, seconds
|
||||
% newTimeSplit = cellfun(@(x) split(char(x),':'),data{2},'UniformOutput', false);
|
||||
% % combine both with the am/pm string in column 3 to a new datestring
|
||||
% customDateStr = cellfun(@(x,y,z) [datestr(datenum([str2double(x{3}),str2double(x{1}),str2double(x{2}),str2double(y{1}),str2double(y{2}),str2double(y{3})])), ' ', char(z)], newDateSplit,newTimeSplit,data{3}, 'uniformOutput',false) ;
|
||||
%
|
||||
% % define time series
|
||||
% LabView.(['ts_' datestr(customDateStr{1},'YYYYmmdd_HHMM')]) ...
|
||||
% = timeseries([data{10} data{4} data{5} data{6} data{12} ...
|
||||
% data{13} data{14} data{7} data{8} data{17} data{18} data{19} data{21}], ...
|
||||
% customDateStr);
|
||||
% LabView.(['ts_' datestr(customDateStr{1},'YYYYmmdd_HHMM')]).Name ...
|
||||
% = 'Readout Napp Chamber raw signal';
|
||||
% clearvars fid ans formatOut nans t x new* custom*
|
||||
%
|
||||
%
|
||||
% elseif datenum(filedate) >= datenum('01-Apr-2023 02:00:00')
|
||||
%
|
||||
% fid = fopen(p.Results.fullFileName);
|
||||
% data = textscan(fid, ...
|
||||
% '%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
% 'HeaderLines',1);
|
||||
% % data file has 2 text columns, followed by 18 numeric columns (THE AM
|
||||
% % PM IS MISSING and some changes to the LabView file. Confirm with Luca....)
|
||||
% fclose(fid);
|
||||
% % define time series
|
||||
%
|
||||
% LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
% = timeseries([data{9} data{3} data{4} data{5} data{11} ...
|
||||
% data{12} data{20} data{6} data{7} data{15} data{16} data{17} data{19}] , ...
|
||||
% datestr(datenum([char(data{1}), char(data{2})],...
|
||||
% 'dd.mm.yyyyHH:MM:SS'),0));
|
||||
%
|
||||
% LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]).Name ...
|
||||
% = 'Readout Napp Chamber raw signal';
|
||||
% clear fid ans formatOut nans t x
|
||||
%
|
||||
% else
|
||||
% fid = fopen(p.Results.fullFileName);
|
||||
% data = textscan(fid, ...
|
||||
% '%s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f',...
|
||||
% 'HeaderLines',1); % data file has 2 text columns, followed by 14 numeric columns
|
||||
% fclose(fid);
|
||||
% % define time series
|
||||
%
|
||||
% LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]) ...
|
||||
% = timeseries([data{9} data{3} data{4} data{5} data{11} ...
|
||||
% data{12} data{13} data{6} data{7} data{16} data{17} data{18} data{20}] , ...
|
||||
% datestr(datenum([char(data{1}), char(data{2})],...
|
||||
% 'dd.mm.yyyyHH:MM:SS'),0));
|
||||
%
|
||||
% LabView.(['ts_' datestr(datenum([char(data{1}{1}), char(data{2}{1})],'dd.mm.yyyyHH:MM:SS'),'YYYYmmdd_HHMM')]).Name ...
|
||||
% = 'Readout Napp Chamber raw signal';
|
||||
% clear fid ans formatOut nans t x
|
||||
% end
|
||||
% end
|
||||
|
||||
function data_structure = LabView_combine(data_structure)
|
||||
% LabView_combine can be used to merge time series into one.
|
||||
|
||||
@@ -3,6 +3,18 @@ function ax = plotCryoData(tbl, tStart, tEnd)
|
||||
%
|
||||
% [ax] = plotCryoData(tbl, tStart, tEnd)
|
||||
% Returns struct with handles to the 3 axes for easy limit modification.
|
||||
%
|
||||
% The first input may be EITHER:
|
||||
% * a table with the columns datetime, pressure_cell_hPa_,
|
||||
% temperature__C_, x_mm_, y_mm_, z_mm_, flowCryo_l_min_, OR
|
||||
% * a LabView structure produced by LabView_importData (optionally
|
||||
% combined with LabView_combine). In that case it is converted to the
|
||||
% required table on the fly (see the local function labviewToTable).
|
||||
|
||||
%--- Accept a LabView timeseries structure and convert it to a table ---
|
||||
if isstruct(tbl)
|
||||
tbl = labviewToTable(tbl);
|
||||
end
|
||||
|
||||
%--- Extract datetime column ---
|
||||
dt = tbl.datetime;
|
||||
@@ -67,3 +79,86 @@ function ax = plotCryoData(tbl, tStart, tEnd)
|
||||
% Improve datetime formatting on x-axis
|
||||
ax.flow.XAxis.TickLabelFormat = 'dd-MMM HH:mm';
|
||||
end
|
||||
|
||||
|
||||
% =========================================================================
|
||||
% LOCAL FUNCTIONS
|
||||
% =========================================================================
|
||||
|
||||
function tbl = labviewToTable(LabView, tsName)
|
||||
%LABVIEWTOTABLE Convert a LabView cryo-log timeseries into a plotCryoData table.
|
||||
%
|
||||
% Uses LabView.merge if present (created by LabView_combine); otherwise the
|
||||
% timeseries field named tsName, or the first timeseries in the structure.
|
||||
% The mapping uses the FIXED ts.Data column order that LabView_importData
|
||||
% produces for every file format:
|
||||
% [IceTemp, ResP1, ResP2, cell/Baratron1, Cooler1, Cooler2, FlowHe, ...
|
||||
% Baratron2, Baratron3, x, y, z, Tsealing]
|
||||
% so it works for old and new files alike. Channels a given file does not
|
||||
% contain (e.g. x/y/z in pre-2019 logs) are returned as NaN.
|
||||
|
||||
%--- Select which timeseries to convert ---
|
||||
if nargin >= 2 && ~isempty(tsName)
|
||||
if ~isfield(LabView, tsName)
|
||||
error('plotCryoData:noSuchField', ...
|
||||
'LabView has no timeseries field "%s".', tsName);
|
||||
end
|
||||
ts = LabView.(tsName);
|
||||
elseif isfield(LabView, 'merge')
|
||||
ts = LabView.merge; % combined log (preferred)
|
||||
else
|
||||
fn = fieldnames(LabView);
|
||||
if isempty(fn)
|
||||
error('plotCryoData:emptyStruct', ...
|
||||
'LabView structure contains no timeseries.');
|
||||
end
|
||||
ts = LabView.(fn{1}); % single-file case
|
||||
end
|
||||
|
||||
%--- Absolute time as a datetime column ---
|
||||
try
|
||||
dt = datetime(getabstime(ts));
|
||||
catch
|
||||
dt = datetime(ts.TimeInfo.StartDate) + ...
|
||||
seconds(ts.Time * unitToSeconds(ts.TimeInfo.Units));
|
||||
end
|
||||
dt = dt(:);
|
||||
|
||||
%--- Pull channels by their fixed ts.Data column index ---
|
||||
D = ts.Data;
|
||||
|
||||
tbl = table( ...
|
||||
dt, ...
|
||||
getCol(D, 4), ... % pressure_cell (hPa) <- cell / Baratron-1 slot
|
||||
getCol(D, 1), ... % temperature (degC) <- ice sample
|
||||
getCol(D, 10), ... % x (mm)
|
||||
getCol(D, 11), ... % y (mm)
|
||||
getCol(D, 12), ... % z (mm)
|
||||
getCol(D, 7), ... % flow cryo (l/min) <- He cryoholder
|
||||
'VariableNames', {'datetime', 'pressure_cell_hPa_', 'temperature__C_', ...
|
||||
'x_mm_', 'y_mm_', 'z_mm_', 'flowCryo_l_min_'});
|
||||
end
|
||||
|
||||
|
||||
function c = getCol(D, k)
|
||||
% Return column k of D, or a NaN column if that channel is absent
|
||||
% (e.g. pre-2019 logs have only 9 columns, so no x/y/z).
|
||||
if size(D, 2) >= k
|
||||
c = D(:, k);
|
||||
else
|
||||
c = nan(size(D, 1), 1);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function s = unitToSeconds(u)
|
||||
% Convert timeseries TimeInfo.Units to seconds (fallback path only).
|
||||
switch lower(u)
|
||||
case 'seconds', s = 1;
|
||||
case 'minutes', s = 60;
|
||||
case 'hours', s = 3600;
|
||||
case 'days', s = 86400;
|
||||
case 'milliseconds', s = 1e-3;
|
||||
otherwise, s = 1; % assume seconds
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,67 @@
|
||||
function ax = plotRgaData(tbl, tStart, tEnd)
|
||||
%PLOTRGADATA Plot RGA partial pressures vs time (companion to plotCryoData).
|
||||
%
|
||||
% ax = plotRgaData(tbl, tStart, tEnd)
|
||||
% Plots every channel column of an rgaImportData table against its shared
|
||||
% datetime axis. tStart/tEnd (datetime) optionally subset the range, just
|
||||
% like plotCryoData. Returns a struct with the axes handle.
|
||||
%
|
||||
% By default the y-axis is linear (RGA scans contain small near-noise
|
||||
% negatives that a log axis cannot show). To switch to the classic
|
||||
% semilog view afterwards:
|
||||
% set(ax.partial, 'YScale', 'log');
|
||||
% (values <= 0 are simply not drawn on a log axis).
|
||||
%
|
||||
% EXAMPLE
|
||||
% tbl = rgaImportData('rga1_Jul_01_2026_08-23-06_AM.txt');
|
||||
% ax = plotRgaData(tbl);
|
||||
% ax = plotRgaData(tbl, t1, t2); % zoom to a window
|
||||
%
|
||||
% See also RGAIMPORTDATA, PLOTCRYODATA
|
||||
|
||||
%--- Extract datetime column ---
|
||||
dt = tbl.datetime;
|
||||
|
||||
%--- If start/stop provided, subset the table ---
|
||||
if nargin >= 3 && ~isempty(tStart) && ~isempty(tEnd)
|
||||
mask = dt >= tStart & dt <= tEnd;
|
||||
tbl = tbl(mask, :);
|
||||
dt = dt(mask);
|
||||
end
|
||||
|
||||
%--- Channel columns = everything except datetime & time_s ---
|
||||
chVars = setdiff(tbl.Properties.VariableNames, {'datetime','time_s'}, 'stable');
|
||||
|
||||
units = 'a.u.';
|
||||
if isfield(tbl.Properties.UserData, 'units')
|
||||
units = tbl.Properties.UserData.units;
|
||||
end
|
||||
|
||||
%--- Plot ---
|
||||
figure;
|
||||
tl = tiledlayout(1, 1);
|
||||
tl.TileSpacing = 'compact';
|
||||
tl.Padding = 'compact';
|
||||
|
||||
ax.partial = nexttile;
|
||||
hold on;
|
||||
for k = 1:numel(chVars)
|
||||
plot(dt, tbl.(chVars{k}), '-', 'LineWidth', 1, ...
|
||||
'DisplayName', prettyName(chVars{k}));
|
||||
end
|
||||
grid on;
|
||||
ylabel(sprintf('Partial pressure [%s]', units));
|
||||
xlabel('Date & Time');
|
||||
title('RGA partial pressures');
|
||||
legend('Location', 'best', 'Interpreter', 'none');
|
||||
|
||||
% Match plotCryoData's datetime tick style
|
||||
ax.partial.XAxis.TickLabelFormat = 'dd-MMM HH:mm';
|
||||
end
|
||||
|
||||
% -------------------------------------------------------------------------
|
||||
function s = prettyName(v)
|
||||
% "Water_m18" -> "Water (m18)"
|
||||
s = regexprep(v, '_m(\d+)$', ' (m$1)');
|
||||
s = strrep(s, '_', ' ');
|
||||
end
|
||||
@@ -0,0 +1,97 @@
|
||||
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
|
||||
Reference in new issue
Block a user