sglogcat

PURPOSE ^

SGLOGCAT Combine data from several Seaglider log files.

SYNOPSIS ^

function [meta, data] = sglogcat(meta_list, data_list, varargin)

DESCRIPTION ^

SGLOGCAT  Combine data from several Seaglider log files.

  Syntax:
    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST)
    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST, OPTIONS)
    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST, OPT1, VAL1, ...)

  Description:
    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST) combines metadata in
    struct array META_LIST and data in cell or struct array DATA_LIST into
    a single data set with metadata in struct META and data in struct DATA.
    Respective elements in META_LIST and DATA_LIST should be in the format 
    returned by function SGLOG2MAT, but do not need to have the same parameters 
    or variables, and are sorted according to the mission number and the dive
    number. Outputs META and DATA are in the same format, too.

    META is a struct array combining the information in elements of META_LIST,
    ordered according to the mission number and the dive number.
    It has the following fields:
      HEADERS: struct array with all log headers.
        This is the concatenation of the HEADERS field of all elements
        in META_LIST.
      START_SECS: number with the reference time for timestamped lines (start
        time of first dive as seconds since 1970 January 01 00:00:00 UTC).
      PARAMS: struct with the names of the fields of non-scalar parameters.
        This is the union of the PARAMS field of all elements in META_LIST.
      GCHEAD: string cell array with the names of the fields for the GC lines.
        This is the concatenation of the GCHEAD field of all elements
        in META_LIST.
      DEVICES: string cell array with the names of the fields for device lines.
        This is the concatenation of the DEVICES field of all elements
        in META_LIST.
      SENSORS: string cell array with the names of the fields for sensor lines.
        This is the concatenation of the SENSORS field of all elements
        in META_LIST.
      SOURCES: string cell array with the name of the source files.
        This is the concatenation the SOURCES field of all elements
        in META_LIST.

    DATA is a struct combining the data in DATA_LIST, ordered according to
    the mission number and the dive number, and with the time fields
    of timestamed parameters (GC, STATE and SM_CCo) converted to
    seconds since the start time of the first dive.

    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST, OPTIONS) and 
    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST, OPT1, VAL1, ...) accept
    the following options given in key-value pairs OPT1, VAL1... or in a struct
    OPTIONS with field names as option keys and field values as option values:
      FORMAT: data output format.
        String setting the format of the output DATA. Valid values are:
          'array': DATA is a struct with a scalar field for each scalar 
            parameter and an array or cell array field for each non-scalar 
            parameter. Values of non-scalar parameters are in the column order 
            given by the corresponding field of the PARAMS metadata field.
          'merged': DATA is a struct with a scalar or column vector field for
            each scalar parameter or entry of a non-scalar parameter. 
            For scalar parameters, the field is named after the parameter,
            while for non-scalar parameters the field names are the parameter
            name and its field names, separated by underscore.
          'struct': DATA is a struct with a scalar field for each scalar 
            parameter and a struct array for each non-scalar parameter.
            The fields of the non-scalar parameters are given by
            the corresponding field of the PARAMS metadata field.
        Default value: 'array'
      PARAMS: parameter filtering list.
        String cell array with the names of the parameters of interest.
        If given, only parameters present in both the input list and this list
        will be present in output. For non-scalar parameters, the name 
        of the identifier as it appears in the log line specifies including
        all of its fields. Individual parameter fields are selected 
        with the identifier and the name of the field separated by underscore
        (e.g. 'GC_st_secs'). The string 'all' may also be given, in which case
        parameter filtering is not performed and all parameters in input list
        will be present in output.
        Default value: 'all' (do not perform parameter filtering).
      PERIOD: dive start time filtering boundaries.
        Two element numeric array with the start and the end of the period 
        of interest (seconds since 1970-01-01 00:00:00.00 UTC). If given, 
        only data from dives with start time within this period will be 
        present in output. The string 'all' may also be given, in which case 
        time filtering is not performed and data from all dives will be 
        present in output.
        Default value: 'all' (do not perform time filtering).

  Examples:
    [meta, data] = sglogcat(meta_list, data_list)

  See also:
    SGLOG2MAT
    SGENG2MAT
    SGENGCAT
    SGLOGENGMERGE

  Authors:
    Joan Pau Beltran  <joanpau.beltran@socib.cat>

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

DOWNLOAD ^

sglogcat.m

SOURCE CODE ^

0001 function [meta, data] = sglogcat(meta_list, data_list, varargin)
0002 %SGLOGCAT  Combine data from several Seaglider log files.
0003 %
0004 %  Syntax:
0005 %    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST)
0006 %    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST, OPTIONS)
0007 %    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST, OPT1, VAL1, ...)
0008 %
0009 %  Description:
0010 %    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST) combines metadata in
0011 %    struct array META_LIST and data in cell or struct array DATA_LIST into
0012 %    a single data set with metadata in struct META and data in struct DATA.
0013 %    Respective elements in META_LIST and DATA_LIST should be in the format
0014 %    returned by function SGLOG2MAT, but do not need to have the same parameters
0015 %    or variables, and are sorted according to the mission number and the dive
0016 %    number. Outputs META and DATA are in the same format, too.
0017 %
0018 %    META is a struct array combining the information in elements of META_LIST,
0019 %    ordered according to the mission number and the dive number.
0020 %    It has the following fields:
0021 %      HEADERS: struct array with all log headers.
0022 %        This is the concatenation of the HEADERS field of all elements
0023 %        in META_LIST.
0024 %      START_SECS: number with the reference time for timestamped lines (start
0025 %        time of first dive as seconds since 1970 January 01 00:00:00 UTC).
0026 %      PARAMS: struct with the names of the fields of non-scalar parameters.
0027 %        This is the union of the PARAMS field of all elements in META_LIST.
0028 %      GCHEAD: string cell array with the names of the fields for the GC lines.
0029 %        This is the concatenation of the GCHEAD field of all elements
0030 %        in META_LIST.
0031 %      DEVICES: string cell array with the names of the fields for device lines.
0032 %        This is the concatenation of the DEVICES field of all elements
0033 %        in META_LIST.
0034 %      SENSORS: string cell array with the names of the fields for sensor lines.
0035 %        This is the concatenation of the SENSORS field of all elements
0036 %        in META_LIST.
0037 %      SOURCES: string cell array with the name of the source files.
0038 %        This is the concatenation the SOURCES field of all elements
0039 %        in META_LIST.
0040 %
0041 %    DATA is a struct combining the data in DATA_LIST, ordered according to
0042 %    the mission number and the dive number, and with the time fields
0043 %    of timestamed parameters (GC, STATE and SM_CCo) converted to
0044 %    seconds since the start time of the first dive.
0045 %
0046 %    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST, OPTIONS) and
0047 %    [META, DATA] = SGLOGCAT(META_LIST, DATA_LIST, OPT1, VAL1, ...) accept
0048 %    the following options given in key-value pairs OPT1, VAL1... or in a struct
0049 %    OPTIONS with field names as option keys and field values as option values:
0050 %      FORMAT: data output format.
0051 %        String setting the format of the output DATA. Valid values are:
0052 %          'array': DATA is a struct with a scalar field for each scalar
0053 %            parameter and an array or cell array field for each non-scalar
0054 %            parameter. Values of non-scalar parameters are in the column order
0055 %            given by the corresponding field of the PARAMS metadata field.
0056 %          'merged': DATA is a struct with a scalar or column vector field for
0057 %            each scalar parameter or entry of a non-scalar parameter.
0058 %            For scalar parameters, the field is named after the parameter,
0059 %            while for non-scalar parameters the field names are the parameter
0060 %            name and its field names, separated by underscore.
0061 %          'struct': DATA is a struct with a scalar field for each scalar
0062 %            parameter and a struct array for each non-scalar parameter.
0063 %            The fields of the non-scalar parameters are given by
0064 %            the corresponding field of the PARAMS metadata field.
0065 %        Default value: 'array'
0066 %      PARAMS: parameter filtering list.
0067 %        String cell array with the names of the parameters of interest.
0068 %        If given, only parameters present in both the input list and this list
0069 %        will be present in output. For non-scalar parameters, the name
0070 %        of the identifier as it appears in the log line specifies including
0071 %        all of its fields. Individual parameter fields are selected
0072 %        with the identifier and the name of the field separated by underscore
0073 %        (e.g. 'GC_st_secs'). The string 'all' may also be given, in which case
0074 %        parameter filtering is not performed and all parameters in input list
0075 %        will be present in output.
0076 %        Default value: 'all' (do not perform parameter filtering).
0077 %      PERIOD: dive start time filtering boundaries.
0078 %        Two element numeric array with the start and the end of the period
0079 %        of interest (seconds since 1970-01-01 00:00:00.00 UTC). If given,
0080 %        only data from dives with start time within this period will be
0081 %        present in output. The string 'all' may also be given, in which case
0082 %        time filtering is not performed and data from all dives will be
0083 %        present in output.
0084 %        Default value: 'all' (do not perform time filtering).
0085 %
0086 %  Examples:
0087 %    [meta, data] = sglogcat(meta_list, data_list)
0088 %
0089 %  See also:
0090 %    SGLOG2MAT
0091 %    SGENG2MAT
0092 %    SGENGCAT
0093 %    SGLOGENGMERGE
0094 %
0095 %  Authors:
0096 %    Joan Pau Beltran  <joanpau.beltran@socib.cat>
0097 
0098 %  Copyright (C) 2013-2016
0099 %  ICTS SOCIB - Servei d'observacio i prediccio costaner de les Illes Balears
0100 %  <http://www.socib.es>
0101 %
0102 %  This program is free software: you can redistribute it and/or modify
0103 %  it under the terms of the GNU General Public License as published by
0104 %  the Free Software Foundation, either version 3 of the License, or
0105 %  (at your option) any later version.
0106 %
0107 %  This program is distributed in the hope that it will be useful,
0108 %  but WITHOUT ANY WARRANTY; without even the implied warranty of
0109 %  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0110 %  GNU General Public License for more details.
0111 %
0112 %  You should have received a copy of the GNU General Public License
0113 %  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0114 
0115   error(nargchk(2, 8, nargin, 'struct'));
0116   
0117   
0118   %% Set options and default values.
0119   options.format = 'array';
0120   options.params = 'all';
0121   options.period = 'all';
0122   
0123   
0124   %% Parse optional arguments.
0125   % Get option key-value pairs in any accepted call signature.
0126   argopts = varargin;
0127   if isscalar(argopts) && isstruct(argopts{1})
0128     % Options passed as a single option struct argument:
0129     % field names are option keys and field values are option values.
0130     opt_key_list = fieldnames(argopts{1});
0131     opt_val_list = struct2cell(argopts{1});
0132   elseif mod(numel(argopts), 2) == 0
0133     % Options passed as key-value argument pairs.
0134     opt_key_list = argopts(1:2:end);
0135     opt_val_list = argopts(2:2:end);
0136   else
0137     error('glider_toolbox:sglogcat:InvalidOptions', ...
0138           'Invalid optional arguments (neither key-value pairs nor struct).');
0139   end
0140   % Overwrite default options with values given in extra arguments.
0141   for opt_idx = 1:numel(opt_key_list)
0142     opt = lower(opt_key_list{opt_idx});
0143     val = opt_val_list{opt_idx};
0144     if isfield(options, opt)
0145       options.(opt) = val;
0146     else
0147       error('glider_toolbox:sglogcat:InvalidOption', ...
0148             'Invalid option: %s.', opt);
0149     end
0150   end
0151   
0152   
0153   %% Set option flags and values.
0154   output_format = lower(options.format);
0155   param_filter = true;
0156   param_list = cellstr(options.params);
0157   start_filter = true;
0158   start_range = options.period;
0159   if ischar(options.params) && strcmp(options.params, 'all')
0160     param_filter = false;
0161   end
0162   if ischar(options.period) && strcmp(options.period, 'all')
0163     start_filter = false;
0164   end
0165   
0166   
0167   %% Check input formats.
0168   % Be gentle and accept emtpy inputs and struct or cell arrays.
0169   % Also, ensure column layout.
0170   if isempty(meta_list)
0171     meta_list = struct();
0172     meta_list.sources = {};
0173     meta_list.headers =  struct('version', {}, 'glider', {}, ...
0174                                 'mission', {}, 'dive', {}, 'start', {});
0175     meta_list.params = struct();
0176     meta_list.start_secs = [];
0177     meta_list.GCHEAD = {};
0178     meta_list.DEVICES = {};
0179     meta_list.SENSORS = {};
0180   elseif iscell(meta_list)
0181     meta_list = vertcat(meta_list{:});
0182   end
0183   if isstruct(data_list)
0184     data_list = num2cell(data_list(:)); % struct array to cell array conversion.
0185   else
0186     data_list = data_list(:);
0187   end
0188   
0189   
0190   %% Filter and sort input data sets.
0191   % Inputs are filtered according to start time
0192   % and sorted according to mission number and to dive number.
0193   all_sources = vertcat(meta_list.sources);
0194   all_gcheads = {meta_list.GCHEAD}';
0195   all_devices = {meta_list.DEVICES}';
0196   all_sensors = {meta_list.SENSORS}';
0197   all_start_secs = vertcat(meta_list.start_secs);
0198   all_params = {meta_list.params}';
0199   all_headers = vertcat(meta_list.headers);
0200   % Sort according mission and dive number (using a virtual rank index).
0201   all_dive_nums = vertcat(all_headers.dive);
0202   all_miss_nums = vertcat(all_headers.mission);
0203   [~, miss_dive_sorting] = ...
0204     sort(  (all_dive_nums - min(all_dive_nums)) ...
0205          + (all_miss_nums - min(all_miss_nums)) ...
0206            * (max(all_dive_nums) - min(all_dive_nums) + 1));
0207   % Filter dives out of the period of interest.
0208   time_filtering = true(size(meta_list));
0209   if start_filter
0210     time_filtering = ...
0211       start_range(1) <= all_start_secs & all_start_secs <= start_range(2);
0212   end
0213   % Sort and filter at once.
0214   time_filtering_and_miss_dive_sorting = ...
0215     miss_dive_sorting(time_filtering(miss_dive_sorting));
0216   header_list = all_headers(time_filtering_and_miss_dive_sorting, :);
0217   source_list = all_sources(time_filtering_and_miss_dive_sorting, :);
0218   gchead_list = all_gcheads(time_filtering_and_miss_dive_sorting, :);
0219   device_list = all_devices(time_filtering_and_miss_dive_sorting, :);
0220   sensor_list = all_sensors(time_filtering_and_miss_dive_sorting, :);
0221   column_list = all_params(time_filtering_and_miss_dive_sorting, :);
0222   starts_list = all_start_secs(time_filtering_and_miss_dive_sorting, :);
0223   values_list = data_list(time_filtering_and_miss_dive_sorting, :);
0224   
0225   
0226   %% Compute data availability according to required output.
0227   % Compute some support variables useful for the rest of the code:
0228   % - The list of available fields is the union of the fields in each data set.
0229   % - A data set x field table setting whether j-th field is in i-th data set.
0230   % - A data set x field table setting whether j-th field is nested in i-th data set.
0231   % - A data set x field table setting whether j-th field is a struct in i-th data set.
0232   % - A struct setting the member availablity for non-scalar parameters:
0233   %   Each field is named after a non-scalar parameter and its value is a
0234   %   data set x member table setting whether k-th member is in corresponding
0235   %   field of i-th data set.
0236   % If parameter filtering is requested, ignore non-requested fields and members.
0237   field_list = cellfun(@fieldnames, column_list, 'UniformOutput', false);
0238   field_list = unique(vertcat(field_list{:}));
0239   field_present_list = ...
0240     cellfun(@(c)(isfield(c, field_list)), column_list, 'UniformOutput', false);
0241   field_present_list = horzcat(field_present_list{:})';
0242   field_nested_list = ...
0243     cellfun(@(d)(isfield(d, field_list)), values_list, 'UniformOutput', false);
0244   field_nested_list = horzcat(field_nested_list{:})';
0245   field_struct_list = false(size(field_nested_list));
0246   field_member_list = struct();
0247   field_member_present_list = struct();
0248   field_member_indices_list = struct();
0249   field_filtering = true(size(field_list));
0250   if param_filter
0251     field_filtering = ismember(field_list, param_list);
0252   end
0253   for field_idx = 1:numel(field_list);
0254     field = field_list{field_idx};
0255     field_present = field_present_list(:,field_idx);
0256     field_nested = field_nested_list(:,field_idx);
0257     field_struct = cellfun(@(d)(isstruct(d.(field))), ...
0258                            values_list(field_nested), 'UniformOutput', false);
0259     field_struct_list(field_nested, field_idx) = horzcat(field_struct{:})';
0260     member_list = cellfun(@(c)(c.(field)), ...
0261                          column_list(field_present), 'UniformOutput', false);
0262     member_list = unique(vertcat(member_list{:}));
0263     if ~field_filtering(field_idx)
0264       member_filtering = ...
0265         ismember(strcat(field, '_', member_list), param_list);
0266       member_list = member_list(member_filtering);
0267       field_filtering(field_idx) = any(member_filtering);
0268     end
0269     if field_filtering(field_idx)
0270       field_member_list.(field) = member_list;
0271       field_member_present_list.(field) = ...
0272         false(numel(column_list), numel(member_list));
0273       field_member_indices_list.(field) = ...
0274         zeros(numel(column_list), numel(member_list));
0275       if ~isempty(member_list)
0276         [member_present_list, member_indices_list] = ...
0277           cellfun(@(c)(ismember(member_list, c.(field))), ...
0278                        column_list(field_present), 'UniformOutput', false);
0279         field_member_present_list.(field)(field_present, :) = ...
0280           horzcat(member_present_list{:})';
0281         field_member_indices_list.(field)(field_present, :) = ...
0282           horzcat(member_indices_list{:})';
0283       end
0284     end
0285   end
0286   if param_filter
0287     field_list = field_list(field_filtering);
0288     field_present_list = field_present_list(:, field_filtering);
0289     field_nested_list = field_nested_list(:, field_filtering);
0290     field_struct_list = field_struct_list(:, field_filtering);
0291   end
0292   
0293   
0294   %% Cat metadata.
0295   meta = struct();
0296   meta.sources = source_list;
0297   meta.headers = header_list;
0298   meta.GCHEAD  = gchead_list;
0299   meta.DEVICES = device_list;
0300   meta.SENSORS = sensor_list;
0301   meta.start_secs = min(starts_list);
0302   meta.params = field_member_list;
0303     
0304     
0305   %% Cat ordinary data (one line in the log file).
0306   data = struct();
0307   spe_field_list = {'GC' 'STATE' 'SM_CCo'}';
0308   gps_field_list = {'GPSFIX'};
0309   bad_field_list = {'RECOV_CODE' 'RESTART_TIME'}'; 
0310   [~, field_index_list] = ...
0311     setdiff(field_list, vertcat(spe_field_list, gps_field_list, bad_field_list));
0312   for field_idx = field_index_list(:)'
0313     field = field_list{field_idx};
0314     field_present = field_present_list(:, field_idx);
0315     member_list = field_member_list.(field);
0316     if isempty(member_list)
0317       % Parameter is scalar, the same in all formats.
0318       % For consistency with non-scalar parameters, ensure column layout.
0319       field_value_list = ...
0320         cellfun(@(d)(d.(field)), values_list(field_present), ...
0321                 'UniformOutput', false);
0322       field_value = vertcat(field_value_list{:});
0323       data.(field)(field_present, 1) = field_value;
0324       if isnumeric(field_value)
0325         data.(field)(~field_present, 1) = nan;
0326       else
0327         data.(field)(~field_present, 1) = {''};
0328       end
0329     else
0330       field_nested = field_nested_list(:, field_idx);
0331       field_struct = field_struct_list(:, field_idx);
0332       member_list = field_member_list.(field);
0333       member_present_list = field_member_present_list.(field);
0334       member_indices_list = field_member_indices_list.(field);
0335       for member_idx = 1:numel(member_list)
0336         member = member_list{member_idx};
0337         field_member = [field '_' member];
0338         member_present = member_present_list(:, member_idx);
0339         member_indices = member_indices_list(:, member_idx);
0340         member_struct = member_present & field_struct;
0341         member_nested = member_present & field_nested & ~field_struct;
0342         member_merged = member_present & ~field_nested;
0343         member_value_list = cell(size(values_list));
0344         if any(member_struct)
0345           member_value_list(member_struct) = ...
0346             cellfun(@(d)(d.(field).(member)), values_list(member_struct), ...
0347                     'UniformOutput', false);
0348         end
0349         if any(member_nested)
0350           member_value_list(member_nested) = ...
0351             cellfun(@(d,c)(d.(field)(:,c)), values_list(member_nested), ...
0352                     num2cell(member_indices(member_nested)), ...
0353                     'UniformOutput', false);
0354         end
0355         if any(member_merged)
0356           member_value_list(member_merged) = ...
0357             cellfun(@(d)(d.(field_member)), values_list(member_merged), ...
0358                     'UniformOutput', false);
0359         end
0360         member_value = vertcat(member_value_list{member_present});
0361         data.(field)(member_present, member_idx) = member_value;
0362         if isnumeric(member_value)
0363           data.(field)(~member_present, member_idx) = nan;
0364         else
0365           data.(field)(~member_present, member_idx) = {''};
0366         end
0367       end
0368     end
0369   end
0370 
0371 
0372   %% Cat special data (several lines in the log file).
0373   dive_start_offset_list = starts_list - min(starts_list);
0374   [~, spe_field_index_list] = ...
0375     intersect(field_list, ...
0376               vertcat(spe_field_list, gps_field_list, bad_field_list));
0377   spe_field_numeric_list = {'GC' 'SM_CCo'}';
0378   for spe_field_index = spe_field_index_list(:)'
0379     spe_field = field_list{spe_field_index};
0380     spe_field_numeric = any(strcmp(spe_field, spe_field_numeric_list));
0381     spe_member_list = field_member_list.(spe_field);
0382     spe_member_secs = strcmp('st_secs', spe_member_list);  
0383     spe_data_list = cell(size(values_list));
0384     for data_idx = 1:numel(values_list)
0385       spe_member_present = field_member_present_list.(spe_field)(data_idx, :);
0386       spe_member_indices = field_member_indices_list.(spe_field)(data_idx, :);
0387       if field_struct_list(data_idx, spe_field_index)
0388         spe_data = struct2cell(values_list{data_idx}.(spe_field))';
0389         if spe_field_numeric
0390           spe_data = cell2mat(spe_data);
0391         end
0392       elseif field_nested_list(data_idx, spe_field_index)
0393         spe_data = values_list{data_idx}.(spe_field);
0394       else
0395         if spe_field_numeric
0396           spe_data = zeros(0,sum(spe_member_present));
0397         else
0398           spe_data = cell(0,sum(spe_member_present));
0399         end
0400         for spe_member_idx = find(spe_member_present(:)');
0401           spe_member = [spe_field '_' spe_member_list{spe_member_idx}];
0402           spe_member_index = spe_member_indices(spe_member_idx);
0403           spe_member_values = values_list{data_idx}.(spe_member);
0404           if spe_field_numeric || iscell(spe_member_values)
0405             spe_data(1:numel(spe_member_values), spe_member_index) = ...
0406               spe_member_values;
0407           else
0408             spe_data(1:numel(spe_member_values), spe_member_index) = ...
0409               num2cell(spe_member_values);
0410           end
0411         end
0412       end
0413       spe_data_list{data_idx}(:, spe_member_present) = ...
0414          spe_data(:, spe_member_indices(spe_member_present));
0415       if spe_field_numeric
0416         spe_data_list{data_idx}(1:end, ~spe_member_present) = nan;
0417         if size(spe_data_list{data_idx}, 1) > 0 && any(spe_member_secs)
0418           spe_data_list{data_idx}(:, spe_member_secs) = ...
0419             spe_data_list{data_idx}(:, spe_member_secs) ...
0420             + dive_start_offset_list(data_idx);
0421         end
0422       else
0423         spe_data_list{data_idx}(1:end, ~spe_member_present) = {''};
0424         if size(spe_data_list{data_idx}, 1) > 0 && any(spe_member_secs)
0425           spe_data_list{data_idx}(:, spe_member_secs) = ...
0426             num2cell(vertcat(spe_data_list{data_idx}{:, spe_member_secs}) ...
0427                      + dive_start_offset_list(data_idx));
0428         end
0429       end
0430     end
0431     data.(spe_field) = vertcat(spe_data_list{:});
0432     if iscell(data.(spe_field))
0433       for spe_member_idx = 1:numel(spe_member_list)
0434         if ~iscellstr(data.(spe_field)(:,spe_member_idx))
0435           data_field_member_undef = ...
0436             cellfun(@isempty, data.(spe_field)(:,spe_member_idx));
0437           data.(spe_field)(data_field_member_undef, spe_member_idx) = {nan};
0438         end
0439       end
0440     end
0441   end
0442   
0443   
0444   %% Convert data to desired format.
0445   switch output_format
0446     case 'array'
0447     case 'merged'
0448       field_list = fieldnames(data);
0449       for field_idx = 1:numel(field_list)
0450         field = field_list{field_idx};
0451         member_list = meta.params.(field);
0452         value_list = data.(field);
0453         if ~isempty(member_list)
0454           for member_idx = 1:numel(member_list)
0455             member = member_list{member_idx};
0456             field_member = [field '_' member];
0457             value = value_list(:, member_idx);
0458             if iscell(value) && ~iscellstr(value)
0459               value = vertcat(value{:});
0460             end
0461             data.(field_member) = value;
0462           end
0463           data = rmfield(data, field);
0464         end
0465       end
0466     case 'struct'
0467       field_list = fieldnames(data);
0468       for field_idx = 1:numel(field_list)
0469         field = field_list{field_idx};
0470         member_list = meta.params.(field);
0471         value_list = data.(field);
0472         if ~isempty(member_list)
0473           if isnumeric(value_list)
0474             value_list = num2cell(value_list);
0475           end
0476           data.(field) = cell2struct(value_list, member_list, 2);
0477         end
0478       end
0479     otherwise
0480       error('glider_toolbox:sglog2cat:InvalidFormat', ...
0481             'Invalid output format: %s.', output_format)
0482   end
0483 
0484 end

Generated on Fri 06-Oct-2017 10:47:42 by m2html © 2005