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{:}) %% ===================================================================== % 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 "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: recover a value from corrupted "-8NaN"-style % entries (via the leading integer); false: NaN those out. % Clean values (e.g. "32.072") are ALWAYS parsed in full, % decimals included, regardless of this toggle -- it only % affects what happens to the corrupted "NaN" case. 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) parseTemperature(s), data{4}); else temperature = cellfun(@(s) parseTemperature(s, false), data{4}); 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); 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 % ========================================================================= % LOCAL FUNCTION % ========================================================================= function val = parseTemperature(s, recoverCorrupted) %PARSETEMPERATURE Parse one temperature field from the new-format file. % % Handles two cases seen in the "temperature (degC)" column across % different logging sessions: % * CLEAN value, e.g. "32.072" -> parsed in full, decimals included. % * CORRUPTED value, e.g. "-8NaN" (an integer immediately followed by % the literal text "NaN", from an older logger bug) -> if % recoverCorrupted is true (default), the leading integer is % recovered (e.g. -8); if false, this returns NaN instead. % * Legitimate "NaN" (a genuinely missing reading) -> always NaN. % % A field is only treated as "clean" if str2double can parse the WHOLE % string as a number, so this never accidentally truncates a valid % decimal reading -- it only engages the leading-integer fallback for % strings that fail a full numeric parse (the corrupted pattern). if nargin < 2 recoverCorrupted = true; end val = str2double(s); % succeeds for clean floats AND for 'NaN' itself if ~isnan(val) return % clean numeric value (decimals intact) -- done end if strcmpi(strtrim(s), 'NaN') return % genuinely missing reading -- stays NaN end % Anything else that failed a full parse is treated as the corrupted % "NaN" pattern. if recoverCorrupted val = str2double(regexp(s, '^-?\d+', 'match', 'once')); else val = NaN; end end