Skip to content

Commit

Permalink
refactor: signatureParse
Browse files Browse the repository at this point in the history
1. moved functions in +Nortek/ including tests
and description
2. Fix regex in read_header_key.m linked to #758
3. Include Signature100 case and include error message
when the SIgnature is not supported
4. updated signatureParse description as it can read
both .ad2cp and .mat
  • Loading branch information
evacougnon committed May 10, 2022
1 parent bcb41c7 commit b9858dd
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 128 deletions.
58 changes: 58 additions & 0 deletions Parser/+Nortek/read_nortek_header_key.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
function [value] = read_nortek_header_key(hstr,mode,key,vtype)
% function value = read_nortek_header_key(hstr,mode,key,vtype)
%
% Read a nortek value from a `key` name
% within a `mode` line from the header string `hstr`.
% The type of the variable is defined by `vtype`.
% See example.
%
% Inputs:
%
% hstr - the header string
% mode- the name of the mode or the first string in the line
% key - the name of the key
% vtype - the textscan type of the value [Optional]
% - default: 'float'
%
%
% Outputs:
%
% value - a single value
%
% Example:
%
% hstr = 'GETAVG1,ABC="CBA",MIAVG=600,ERR=0.00e-10';
% [value] = read_nortek_header_key(hstr,'GETAVG1','MIAVG','int');
% assert(value==600)
% [value] = read_nortek_header_key(hstr,'GETAVG1','ABC','str');
% assert(value=='CBA')
% [value] = read_nortek_header_key(hstr,'GETAVG1','ERR','float');
% assert(value==0.00e-10)
%
% author: [email protected]
%
narginchk(4,4)

if strcmpi(vtype,'float')
mtype = '-?[\d.]+(?:[eE][-?+?\d+]\d+)?';
mfun = @str2double;
elseif strcmpi(vtype,'integer') || strcmpi(vtype,'int')
mtype = '\d+';
mfun = @str2double;
else
mtype = '".*?"';
mfun = @(x) strrep(x,'"','');
end

%header lines always start with command,key0=value0,key1=value1,...
re_match = ['(?<mode>(' mode '))' '(.*?)' key '={1}' '(?<value>(' mtype '))'];
data = regexpi(hstr,re_match,'names');

if ~isempty(data)
value = mfun(data.value);
else
error('Could not find key %s with type %s',key,vtype);
end

end

43 changes: 43 additions & 0 deletions Parser/+Nortek/transfer_matrix.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
function [Beam2xyz] = transfer_matrix(iA0_Header)
% function [Beam2xyz] = transfer_matrix(iA0_Header)
%
% get transfer function from adcp config command GETXFAVG
%
% Input:
% iA0_Header - the header string
%
% Output:
% Beam2xyz - transfer matrix to use to convert between ENU and beam
%
% Example
%
%
%

narginchk(1,1)

r = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','ROWS','int');
Beam2xyz = zeros(r,r);

Beam2xyz(1,1) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M11','float');
Beam2xyz(1,2) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M12','float');
Beam2xyz(1,3) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M13','float');
Beam2xyz(2,1) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M21','float');
Beam2xyz(2,2) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M22','float');
Beam2xyz(2,3) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M23','float');
Beam2xyz(3,1) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M31','float');
Beam2xyz(3,2) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M32','float');
Beam2xyz(3,3) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M33','float');

if r==4
Beam2xyz(1,4) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M14','float');
Beam2xyz(2,4) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M24','float');
Beam2xyz(3,4) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M34','float');
Beam2xyz(4,1) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M41','float');
Beam2xyz(4,2) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M42','float');
Beam2xyz(4,3) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M43','float');
Beam2xyz(4,4) = Nortek.read_nortek_header_key(iA0_Header,'GETXFAVG','M44','float');
end

end

142 changes: 14 additions & 128 deletions Parser/signatureParse.m
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
function sample_data = signatureParse( filename, tMode )
%SIGNATUREPARSE Parses ADCP data from a raw Nortek Signature
% binary (.ad2cp) file.
% binary (.ad2cp) file or a .mat that has extracted from the
% Nortek instrument software(faster).
%
%
% Inputs:
% filename - Cell array containing the name of the raw signature
% file to parse.
% file to parse (either .ad2cp or .mat).
% tMode - Toolbox data type mode.
%
% Outputs:
Expand Down Expand Up @@ -60,9 +61,9 @@
% this is a string data record
if structures.(acquisitionMode{iA0}).Data.Id == 16 || structures.(acquisitionMode{iA0}).Data.Id == 18
iA0_Header = structures.(acquisitionMode{iA0}).Data.String;
instrumentModel = read_header_key(iA0_Header,'ID','STR','string');
magDec = read_header_key(iA0_Header,'GETUSER','DECL','float');
Beam2xyz = TransferMatrix(iA0_Header);
instrumentModel = Nortek.read_nortek_header_key(iA0_Header,'ID','STR','string');
magDec = Nortek.read_nortek_header_key(iA0_Header,'GETUSER','DECL','float');
Beam2xyz = Nortek.transfer_matrix(iA0_Header);
structures = rmfield(structures, acquisitionMode{iA0});
acquisitionMode(iA0) = [];
end
Expand Down Expand Up @@ -342,7 +343,7 @@

data = struct;
nDataset = size(acquisitionMode, 2);
nBeams = 4; % default
nBeams = 4; % default -- WHY IS THIS NEEDED - I don't think it is needed due to l.354 nBeams = blah
for i=1:nDataset
data.(acquisitionMode{1, i}).Time = structures.Data.([acquisitionMode{1, i} 'Time']);

Expand Down Expand Up @@ -634,7 +635,6 @@

diffTimeInSec = diff(data.(acquisitionMode{i}).Time*24*3600);


% look for most frequents modes
Ms = unique(round(diffTimeInSec*100)/100); % unique() sorts in order of most frequent

Expand Down Expand Up @@ -665,8 +665,14 @@
sample_data{i}.meta.beam_angle = 20;
case 'Signature55'
sample_data{i}.meta.beam_angle = 20;
otherwise % Signature500 and Signature1000
case 'Signature100'
sample_data{i}.meta.beam_angle = 20;
case 'Signature500'
sample_data{i}.meta.beam_angle = 25;
case 'Signature1000'
sample_data{i}.meta.beam_angle = 25;
otherwise % send error message
error('Signature not supported');
end
if data.(acquisitionMode{i}).isVelocityData
switch lower(ext)
Expand Down Expand Up @@ -873,123 +879,3 @@
end


%-----------------------------------------------------------------
% get transfer function from adcp config command GETXFAVG
% regexp doesn't like the last parameter on the line as it runs into the
% next line.
% ie M33=-0.3547GETUSER,POFF=9.50,..
%------------------------------------------------------------------
function [Beam2xyz] = TransferMatrix(iA0_Header)
r = read_header_key(iA0_Header,'GETXFAVG','ROWS','int');
Beam2xyz = zeros(r,r);

Beam2xyz(1,1) = read_header_key(iA0_Header,'GETXFAVG','M11','float');
Beam2xyz(1,2) = read_header_key(iA0_Header,'GETXFAVG','M12','float');
Beam2xyz(1,3) = read_header_key(iA0_Header,'GETXFAVG','M13','float');
Beam2xyz(2,1) = read_header_key(iA0_Header,'GETXFAVG','M21','float');
Beam2xyz(2,2) = read_header_key(iA0_Header,'GETXFAVG','M22','float');
Beam2xyz(2,3) = read_header_key(iA0_Header,'GETXFAVG','M23','float');
Beam2xyz(3,1) = read_header_key(iA0_Header,'GETXFAVG','M31','float');
Beam2xyz(3,2) = read_header_key(iA0_Header,'GETXFAVG','M32','float');
if r==3
Beam2xyz(3,3) = read_header_key2(iA0_Header,'M33');
else
Beam2xyz(3,3) = read_header_key(iA0_Header,'GETXFAVG','M33','float');
end

if r==4
Beam2xyz(1,4) = read_header_key(iA0_Header,'GETXFAVG','M14','float');
Beam2xyz(2,4) = read_header_key(iA0_Header,'GETXFAVG','M24','float');
Beam2xyz(3,4) = read_header_key(iA0_Header,'GETXFAVG','M34','float');

Beam2xyz(4,1) = read_header_key(iA0_Header,'GETXFAVG','M41','float');
Beam2xyz(4,2) = read_header_key(iA0_Header,'GETXFAVG','M42','float');
Beam2xyz(4,3) = read_header_key(iA0_Header,'GETXFAVG','M43','float');
Beam2xyz(4,4) = read_header_key2(iA0_Header,'M44');
end
end

%--------------------------------------------------------------
function [x] = read_header_key2(header,key)

mode='GETXFAVG';

mtype = '-?[\d.^\D]+';
re_match = ['(?<mode>(' mode '))' '(.*?)' key '={1}' '(?<value>(' mtype ')),'];
data = regexpi(header,re_match,'names');

% '-0.3547GETUSER,POFF=9.50'
aa = strsplit(data.value, ',');
s = char(aa(1));
ss = '';
for i=1:length(s)
c = s(i);
if c=='-' || c=='.' || ~isempty(str2num(c))
ss = [ss c];
end
end

x = str2double(ss);
end



%----------------------------------------------------------------
function [value] = read_header_key(hstr,mode,key,vtype)
% function value = read_header_key(hstr,mode,key,vtype)
%
% Read a nortek value from a `key` name
% within a `mode` line from the header string `hstr`.
% The type of the variable is defined by `vtype`.
% See example.
%
% Inputs:
%
% hstr - the header string
% mode- the name of the mode or the first string in the line
% key - the name of the key
% vtype - the textscan type of the value [Optional]
% - default: 'float'
%
%
% Outputs:
%
% value - a single value
%
% Example:
%
% hstr = 'GETAVG1,ABC="CBA",MIAVG=600,ERR=0.00e-10';
% [value] = read_nortek_key(hstr,'GETAVG1','MIAVG','int');
% assert(value==600)
% [value] = read_nortek_key(hstr,'GETAVG1','ABC','str');
% assert(value==600)
% [value] = read_nortek_key(hstr,'GETAVG1','ERR','float');
% assert(value==600)
%
% author: [email protected]
%
narginchk(4,4)

if strcmpi(vtype,'float')
mtype = '-?[\d.]+(?:[eE][-?+?\d+]\d+)?';
mfun = @str2double;
elseif strcmpi(vtype,'integer') || strcmpi(vtype,'int')
mtype = '\d+';
mfun = @str2double;
else
mtype = '".*?"';
mfun = @(x) strrep(x,'"','');
end

%header lines always start with command,key0=value0,key1=value1,...
re_match = ['(?<mode>(' mode '))' '(.*?)' key '={1}' '(?<value>(' mtype ')),'];
data = regexpi(hstr,re_match,'names');

if ~isempty(data)
value = mfun(data.value);
else
error('Could not find key %s with type %s',key,vtype);
end

end

8 changes: 8 additions & 0 deletions test/Parser/testSignature.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

properties (TestParameter)
mode = {'timeSeries'};
% s55_file = files2namestruct(rdir([toolboxRootPath 'data/testfiles/Nortek/signature_55/v000']));
s250_file = files2namestruct(rdir([toolboxRootPath 'data/testfiles/Nortek/signature_250/v000']));
s500_file = files2namestruct(rdir([toolboxRootPath 'data/testfiles/Nortek/signature_500/v000']));
s1000_file = files2namestruct(rdir([toolboxRootPath 'data/testfiles/Nortek/signature_1000/v000']));
Expand All @@ -16,6 +17,13 @@

methods (Test)

% function testReadSignature250(~, s55_file, mode)
% data = signatureParse({s55_file},mode);
% assert(strcmp(data{1}.meta.instrument_model,'Signature55'));
% assert(strcmp(data{1}.meta.instrument_make,'Nortek'));
% assert(data{1}.meta.beam_angle==20);
% end

function testReadSignature250(~, s250_file, mode)
data = signatureParse({s250_file},mode);
assert(strcmp(data{1}.meta.instrument_model,'Signature250'));
Expand Down

0 comments on commit b9858dd

Please sign in to comment.