sglogengmerge

PURPOSE ^

SGLOGENGMERGE Merge data from combined Seaglider log and eng data sets into a single data set.

SYNOPSIS ^

function [meta, data] = sglogengmerge(meta_log, data_log, meta_eng, data_eng, varargin)

DESCRIPTION ^

SGLOGENGMERGE  Merge data from combined Seaglider log and eng data sets into a single data set.

  Syntax:
    [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG)
    [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG, OPTIONS)
    [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG, OPT1, VAL1, ...) 

  Description:
    [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG) 
    merges the data sets described by metadata structs META_LOG and META_ENG,
    and data arrays or structs DATA_LOG and DATA_ENG into a single data set
    described by metadata struct META and data array or struct DATA 
    (see format option described below). Input metadata and data should be 
    in the format returned by the functions SGLOGCAT and SGENGCAT.
    Log data referenced to the dive start time (GC, STATE and SM_CCo fields)
    is merged with eng data. See note on merging.

    META is a struct array combining the information in META_LOG and META_ENG.
    It has the following fields:
      LOGHEADERS: struct array of log headers.
        These are the log data headers in META_LOG. Entries corresponding
        to unmatched eng headers have all fields empty.
      ENGHEADERS: struct array of eng headers.
        These are the eng data headers from META_ENG. Entries corresponding
        to unmatched log headers have all fields empty.
      START_SECS: number with the reference time for timestamped data lines. 
        This is the minimum of the START_SECS field in META_LOGG and META_ENG: 
        start time of first dive as seconds since 1970 Janyuay 01 00:00:00 UTC.
      COLUMNS: string cell array with the names of the columns in output data.
        This are the column names in META_ENG. See note on data merging.
      PARAMS: struct with the names of the fields of non-scalar parameters.
        This is the PARAMS field in META_LOG.
      GCHEAD: string cell array with the names of the fields for the GC lines.
        This is the GCHEAD field in META_LOG.
      DEVICES: string cell array with the names of the fields for device lines.
        This is the DEVICES field in META_LOG.
      SENSORS: string cell array with the names of the fields for sensor lines.
        This is the SENSORS field in META_LIST.
      SOURCES: string cell array with the name of the source files.
        This is the concatenation the SOURCES field in META_LOG and META_ENG.

  [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG, OPTIONS) and
  [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG, 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 the following fields:
          LOG: array with log parameters in the column order specified by
            PARAMS metadata field.
          ENG: array or cell array with the eng columns and GC and SM_CCo
            log parameter columns in the column order specified by COLUMNS
            metadata field.
          GPSFIX: array or cell array with the GPS log columns in the order
            specified by the GPSFIX metadata field.
          See note on array format.
        'merged': DATA is a struct with a column vector field for each
          parameter in log or gps data, and for each column in eng data.
        'struct': DATA is a struct with a column vector field for each column
          in eng data and gps data, and for each scalar parameter in log data; 
          and with a struct field for each non-scalar parameter in log data.
      Default value: 'array'
    PARAMS: log parameter filtering list.
      String cell array with the names of the log parameters of interest. 
      If given, only parameters present in both the input data sets 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. 'FINISH_dens'). 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 log parameter filtering).
    COLUMNS: eng column filtering list.
      String cell array with the names of the eng data columns of interest. 
      If given, only columns present in both the input data sets and this list
      will be present in output. The string 'all' may also be given,
      in which case column filtering is not performed and all columns
      in the list will be present in output.
      Default value: 'all' (do not perform eng column filtering).

  Notes:
    This function should be used to merge data from log and eng files
    concatenated by SGLOGCAT and SGENGCAT respectively.

    The log parameters GC, STATE and SM_CCo contain values produced during the
    dive and timestamped according to the start of it. Hence, they are merged 
    with the data collected in the eng files. To avoid name clashes and
    duplications, the following fields of the log parameters are renamed:
      - 'st_secs' field of 'GC'/'STATE'/'SM_CCo' parameter maps to 'elaps_t'
      - 'depth'   field of 'GC' parameter maps to 'GC_depth'
      - 'gcphase' field of 'GC' parameter maps to 'GC_phase'
    STATE lines ususally do not have a unique timestamp (the timestamp of 
    consecutive end-begin lines is the same) and in that case only the last 
    line appears in the output.ç

    Depth in 'GC' log lines and in eng columns is not merged because they come
    in different units (m and cm). Also, there seems to be some time mismatch.

    Output in 'array' format when there are both textual and numeric columns
    might require a large amount of memory because of the storage in a cell
    array.

  Examples:
    [meta, data] = sglogengmerge(meta_log, data_log, meta_eng, data_eng)

  See also:
    SGLOG2MAT
    SGLOGCAT
    SGENGCAT

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

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

DOWNLOAD ^

sglogengmerge.m

SOURCE CODE ^

0001 function [meta, data] = sglogengmerge(meta_log, data_log, meta_eng, data_eng, varargin)
0002 %SGLOGENGMERGE  Merge data from combined Seaglider log and eng data sets into a single data set.
0003 %
0004 %  Syntax:
0005 %    [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG)
0006 %    [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG, OPTIONS)
0007 %    [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG, OPT1, VAL1, ...)
0008 %
0009 %  Description:
0010 %    [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG)
0011 %    merges the data sets described by metadata structs META_LOG and META_ENG,
0012 %    and data arrays or structs DATA_LOG and DATA_ENG into a single data set
0013 %    described by metadata struct META and data array or struct DATA
0014 %    (see format option described below). Input metadata and data should be
0015 %    in the format returned by the functions SGLOGCAT and SGENGCAT.
0016 %    Log data referenced to the dive start time (GC, STATE and SM_CCo fields)
0017 %    is merged with eng data. See note on merging.
0018 %
0019 %    META is a struct array combining the information in META_LOG and META_ENG.
0020 %    It has the following fields:
0021 %      LOGHEADERS: struct array of log headers.
0022 %        These are the log data headers in META_LOG. Entries corresponding
0023 %        to unmatched eng headers have all fields empty.
0024 %      ENGHEADERS: struct array of eng headers.
0025 %        These are the eng data headers from META_ENG. Entries corresponding
0026 %        to unmatched log headers have all fields empty.
0027 %      START_SECS: number with the reference time for timestamped data lines.
0028 %        This is the minimum of the START_SECS field in META_LOGG and META_ENG:
0029 %        start time of first dive as seconds since 1970 Janyuay 01 00:00:00 UTC.
0030 %      COLUMNS: string cell array with the names of the columns in output data.
0031 %        This are the column names in META_ENG. See note on data merging.
0032 %      PARAMS: struct with the names of the fields of non-scalar parameters.
0033 %        This is the PARAMS field in META_LOG.
0034 %      GCHEAD: string cell array with the names of the fields for the GC lines.
0035 %        This is the GCHEAD field in META_LOG.
0036 %      DEVICES: string cell array with the names of the fields for device lines.
0037 %        This is the DEVICES field in META_LOG.
0038 %      SENSORS: string cell array with the names of the fields for sensor lines.
0039 %        This is the SENSORS field in META_LIST.
0040 %      SOURCES: string cell array with the name of the source files.
0041 %        This is the concatenation the SOURCES field in META_LOG and META_ENG.
0042 %
0043 %  [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG, OPTIONS) and
0044 %  [META, DATA] = SGLOGENGMERGE(META_LOG, DATA_LOG, META_ENG, DATA_ENG, OPT1, VAL1, ...)
0045 %  accept the following options given in key-value pairs OPT1, VAL1...
0046 %  or in a struct OPTIONS with field names as option keys and field values
0047 %  as option values:
0048 %    FORMAT: data output format.
0049 %      String setting the format of the output DATA. Valid values are:
0050 %        'array': DATA is a struct with the following fields:
0051 %          LOG: array with log parameters in the column order specified by
0052 %            PARAMS metadata field.
0053 %          ENG: array or cell array with the eng columns and GC and SM_CCo
0054 %            log parameter columns in the column order specified by COLUMNS
0055 %            metadata field.
0056 %          GPSFIX: array or cell array with the GPS log columns in the order
0057 %            specified by the GPSFIX metadata field.
0058 %          See note on array format.
0059 %        'merged': DATA is a struct with a column vector field for each
0060 %          parameter in log or gps data, and for each column in eng data.
0061 %        'struct': DATA is a struct with a column vector field for each column
0062 %          in eng data and gps data, and for each scalar parameter in log data;
0063 %          and with a struct field for each non-scalar parameter in log data.
0064 %      Default value: 'array'
0065 %    PARAMS: log parameter filtering list.
0066 %      String cell array with the names of the log parameters of interest.
0067 %      If given, only parameters present in both the input data sets and this
0068 %      list will be present in output. For non-scalar parameters, the name
0069 %      of the identifier as it appears in the log line specifies including
0070 %      all of its fields. Individual parameter fields are selected
0071 %      with the identifier and the name of the field separated by underscore
0072 %      (e.g. 'FINISH_dens'). The string 'all' may also be given, in which case
0073 %      parameter filtering is not performed and all parameters in input list
0074 %      will be present in output.
0075 %      Default value: 'all' (do not perform log parameter filtering).
0076 %    COLUMNS: eng column filtering list.
0077 %      String cell array with the names of the eng data columns of interest.
0078 %      If given, only columns present in both the input data sets and this list
0079 %      will be present in output. The string 'all' may also be given,
0080 %      in which case column filtering is not performed and all columns
0081 %      in the list will be present in output.
0082 %      Default value: 'all' (do not perform eng column filtering).
0083 %
0084 %  Notes:
0085 %    This function should be used to merge data from log and eng files
0086 %    concatenated by SGLOGCAT and SGENGCAT respectively.
0087 %
0088 %    The log parameters GC, STATE and SM_CCo contain values produced during the
0089 %    dive and timestamped according to the start of it. Hence, they are merged
0090 %    with the data collected in the eng files. To avoid name clashes and
0091 %    duplications, the following fields of the log parameters are renamed:
0092 %      - 'st_secs' field of 'GC'/'STATE'/'SM_CCo' parameter maps to 'elaps_t'
0093 %      - 'depth'   field of 'GC' parameter maps to 'GC_depth'
0094 %      - 'gcphase' field of 'GC' parameter maps to 'GC_phase'
0095 %    STATE lines ususally do not have a unique timestamp (the timestamp of
0096 %    consecutive end-begin lines is the same) and in that case only the last
0097 %    line appears in the output.ç
0098 %
0099 %    Depth in 'GC' log lines and in eng columns is not merged because they come
0100 %    in different units (m and cm). Also, there seems to be some time mismatch.
0101 %
0102 %    Output in 'array' format when there are both textual and numeric columns
0103 %    might require a large amount of memory because of the storage in a cell
0104 %    array.
0105 %
0106 %  Examples:
0107 %    [meta, data] = sglogengmerge(meta_log, data_log, meta_eng, data_eng)
0108 %
0109 %  See also:
0110 %    SGLOG2MAT
0111 %    SGLOGCAT
0112 %    SGENGCAT
0113 %
0114 %  Authors:
0115 %    Joan Pau Beltran  <joanpau.beltran@socib.cat>
0116 
0117 %  Copyright (C) 2013-2016
0118 %  ICTS SOCIB - Servei d'observacio i prediccio costaner de les Illes Balears
0119 %  <http://www.socib.es>
0120 %
0121 %  This program is free software: you can redistribute it and/or modify
0122 %  it under the terms of the GNU General Public License as published by
0123 %  the Free Software Foundation, either version 3 of the License, or
0124 %  (at your option) any later version.
0125 %
0126 %  This program is distributed in the hope that it will be useful,
0127 %  but WITHOUT ANY WARRANTY; without even the implied warranty of
0128 %  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0129 %  GNU General Public License for more details.
0130 %
0131 %  You should have received a copy of the GNU General Public License
0132 %  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0133 
0134   error(nargchk(4, 14, nargin, 'struct'));
0135   
0136   
0137   %% Set options and default values.
0138   options.format = 'array';
0139   options.params = 'all';
0140   options.columns = 'all';
0141   options.period = 'all';
0142   
0143   
0144   %% Parse optional arguments.
0145   % Get option key-value pairs in any accepted call signature.
0146   argopts = varargin;
0147   if isscalar(argopts) && isstruct(argopts{1})
0148     % Options passed as a single option struct argument:
0149     % field names are option keys and field values are option values.
0150     opt_key_list = fieldnames(argopts{1});
0151     opt_val_list = struct2cell(argopts{1});
0152   elseif mod(numel(argopts), 2) == 0
0153     % Options passed as key-value argument pairs.
0154     opt_key_list = argopts(1:2:end);
0155     opt_val_list = argopts(2:2:end);
0156   else
0157     error('glider_toolbox:sglogengmerge:InvalidOptions', ...
0158           'Invalid optional arguments (neither key-value pairs nor struct).');
0159   end
0160   % Overwrite default options with values given in extra arguments.
0161   for opt_idx = 1:numel(opt_key_list)
0162     opt = lower(opt_key_list{opt_idx});
0163     val = opt_val_list{opt_idx};
0164     if isfield(options, opt)
0165       options.(opt) = val;
0166     else
0167       error('glider_toolbox:sglogengmerge:InvalidOption', ...
0168             'Invalid option: %s.', opt);
0169     end
0170   end
0171   
0172   
0173   %% Set option flags and values.
0174   output_format = options.format;
0175   param_filter = true;
0176   param_filter_list = cellstr(options.params);
0177   column_filter = true;
0178   column_filter_list = cellstr(options.columns);
0179   if ischar(options.params) && strcmp(options.params, 'all')
0180     param_filter = false;
0181   end
0182   if ischar(options.columns) && strcmp(options.columns, 'all')
0183     column_filter = false;
0184   end
0185   
0186   
0187   %% GPS data goes on its own.
0188   % However, it is described in the PARAMS metadata field.
0189   
0190   
0191   %% Eng data merged with numeric timestamped log data.
0192   % Precompute timestamp column and column names,
0193   % and convert eng, GC and SM_CCo data to array if needed.
0194   min_start_secs = min([meta_log.start_secs; meta_eng.start_secs]);
0195   % Eng data:
0196   eng = data_eng;
0197   if isstruct(eng)
0198     eng = cell2mat(struct2cell(eng)');
0199   end
0200   eng_column_list = meta_eng.columns;
0201   eng_secs_offset = meta_eng.start_secs - min_start_secs;
0202   eng_secs_select = strcmp('elaps_t', eng_column_list);
0203   eng(:, eng_secs_select) = eng(:, eng_secs_select) + eng_secs_offset;
0204   eng_secs = eng(:, eng_secs_select);
0205   if column_filter
0206     eng_column_filtering = ismember(eng_column_list, column_filter_list);
0207     eng_column_list = eng_column_list(eng_column_filtering);
0208     eng = eng(:, eng_column_filtering);
0209     if ~any(eng_column_filtering)
0210       eng_secs = zeros(0, 1);
0211       eng = [];
0212     end
0213   end
0214   % Log data to be merged with eng data:
0215   logeng_param_list = {'GC' 'SM_CCo' 'STATE'}';
0216   logeng_param_numeric_list = [true true false]';
0217   logeng_member_map = {
0218     'st_secs' 'elaps_t'
0219     'gcphase' 'GC_phase'
0220     'depth'   'GC_depth'
0221   };
0222   logeng_param_list = ...
0223     intersect(fieldnames(meta_log.params), logeng_param_list);
0224   logeng_secs_offset = meta_log.start_secs - min_start_secs;
0225   logeng_stsecs_list = repmat({zeros(0, 1)}, size(logeng_param_list));
0226   logeng_column_list = repmat({cell(0,1)}, size(logeng_param_list));
0227   logeng_values_list = cell(size(logeng_param_list));
0228   for logeng_param_idx = 1:numel(logeng_param_list)
0229     logeng_param = logeng_param_list{logeng_param_idx};
0230     logeng_param_numeric = logeng_param_numeric_list(logeng_param_idx);
0231     logeng_members = meta_log.params.(logeng_param);
0232     logeng_columns = strcat(logeng_param, '_', logeng_members);
0233     if ~isfield(data_log, logeng_param)
0234       logeng_values = ...
0235         cellfun(@(f)(data_log.(f)), logeng_columns, 'UniformOutput', false);
0236       if ~logeng_param_numeric
0237         logeng_values_numeric = cellfun(@isnumeric, logeng_values);
0238         logeng_values(logeng_values_numeric) = ...
0239           cellfun(@num2cell, logeng_values(logeng_values_numeric), ...
0240                   'UniformOutput', false);
0241       end
0242       logeng_values = horzcat(logeng_values{:});
0243     elseif isstruct(data_log.(logeng_param))
0244       logeng_values = struct2cell(data_log.(logeng_param))';
0245       if logeng_param_numeric
0246         logeng_values = cell2mat(logeng_values);
0247       end
0248     else
0249       logeng_values = data_log.(logeng_param);
0250     end
0251     logeng_stsecs_column = strcmp('st_secs', logeng_members);
0252     if logeng_param_numeric
0253       logeng_stsecs = logeng_values(:, logeng_stsecs_column);
0254       logeng_stsecs = logeng_stsecs + logeng_secs_offset;
0255       logeng_values(:, logeng_stsecs_column) = logeng_stsecs;
0256     else
0257       logeng_stsecs = cell2mat(logeng_values(:, logeng_stsecs_column));
0258       logeng_stsecs = logeng_stsecs + logeng_secs_offset;
0259       logeng_values(:, logeng_stsecs_column) = num2cell(logeng_stsecs);
0260     end
0261     [logeng_column_renaming, logeng_column_map] = ...
0262       ismember(logeng_members, logeng_member_map(:,1));
0263     logeng_columns(logeng_column_renaming) = ...
0264       logeng_member_map(logeng_column_map(logeng_column_renaming), 2);
0265     logeng_member_filtering = true(size(logeng_members));
0266     if param_filter && ~any(strcmp(logeng_param, param_filter_list))
0267       logeng_member_filtering = ismember(logeng_members, param_filter_list);
0268     end
0269     if any(logeng_member_filtering)
0270       logeng_column_list{logeng_param_idx} = ...
0271         logeng_columns(logeng_member_filtering);
0272       logeng_values_list{logeng_param_idx} = ...
0273         logeng_values(:, logeng_member_filtering);
0274       logeng_stsecs_list{logeng_param_idx} = logeng_stsecs;
0275     end
0276   end
0277   % Merge timestamped data.
0278   logeng_data_list = vertcat({eng}, logeng_values_list(:));
0279   logeng_secs_list = vertcat(eng_secs, logeng_stsecs_list{:});
0280   logeng_cols_list = vertcat(eng_column_list, logeng_column_list{:});
0281   column_list = unique(logeng_cols_list);
0282   [logeng_cols_present_list, logeng_cols_indices_list] = ...
0283     ismember(logeng_cols_list, column_list);
0284   [logeng_secs, ~, logeng_rows_indices_list] = unique(logeng_secs_list);
0285   [logeng_num_rows_list, logeng_num_cols_list] = ...
0286     cellfun(@size, logeng_data_list);
0287   logeng_rows_final_list = cumsum(logeng_num_rows_list);
0288   logeng_rows_start_list = 1 + [0; logeng_rows_final_list(1:end-1)];
0289   logeng_cols_final_list = cumsum(logeng_num_cols_list);
0290   logeng_cols_start_list = 1 + [0; logeng_cols_final_list(1:end-1)];
0291   logeng = struct();
0292   logeng_rows_total = numel(logeng_secs);
0293   % logeng_cols_total = numel(column_list);
0294   % logeng = nan(logeng_rows_total, logeng_cols_total);
0295   for data_idx = 1:numel(logeng_data_list)
0296     logeng_rows_range = ...
0297       logeng_rows_start_list(data_idx):logeng_rows_final_list(data_idx);
0298     logeng_rows_indices = logeng_rows_indices_list(logeng_rows_range);
0299     logeng_cols_range = ...
0300       logeng_cols_start_list(data_idx):logeng_cols_final_list(data_idx);
0301     logeng_cols_present = logeng_cols_present_list(logeng_cols_range);
0302     logeng_cols_indices = logeng_cols_indices_list(logeng_cols_range);
0303     for logeng_col_idx = find(logeng_cols_present(:)')
0304       column_index = logeng_cols_indices(logeng_col_idx);
0305       column = column_list{column_index};
0306       value = logeng_data_list{data_idx}(:,logeng_col_idx);
0307       if iscell(value) && ~iscellstr(value)
0308         value = cell2mat(value);
0309       end
0310       if ~isfield(logeng, column)
0311         if isnumeric(value)
0312           logeng.(column) = nan(logeng_rows_total, 1);
0313         else
0314           logeng.(column) = repmat({''}, logeng_rows_total, 1);
0315         end
0316       end
0317       logeng.(column)(logeng_rows_indices) = value;
0318     end
0319   end
0320   
0321   
0322   %% Log parameter data.
0323   log = struct();
0324   param_list = struct();
0325   log_param_list = setdiff(fieldnames(meta_log.params), logeng_param_list);
0326   log_param_filtering = true(size(log_param_list));
0327   if param_filter
0328     log_param_filtering = ismember(log_param_list, param_filter_list);
0329   end
0330   for log_param_idx = 1:numel(log_param_list)
0331     log_field = log_param_list{log_param_idx};
0332     log_member_list = meta_log.params.(log_field);
0333     log_field_member_list = strcat(log_field, '_', log_member_list);
0334     log_member_filtering = ismember(log_field_member_list, param_filter_list);
0335     log_values = [];
0336     if ~isfield(data_log, log_field)
0337       for log_member_idx = numel(log_field_member_list):-1:1
0338         log_field_member = log_field_member_list{log_member_idx};
0339         if iscell(log_values) && isnumeric(data_log.(log_field_member))
0340           log_values(:,log_member_idx) = num2cell(data_log.(log_field_member));
0341         elseif isnumeric(log_values) && iscell(data_log.(log_field_member))
0342           log_values = num2cell(log_values);
0343           log_values(:,log_member_idx) = data_log.(log_field_member);  
0344         else
0345           log_values(:,log_member_idx) = data_log.(log_field_member);  
0346         end
0347       end
0348     elseif isstruct(data_log.(log_field))
0349       log_values = struct2cell(data_log.(log_field))';
0350       if ~iscellstr(log_values)
0351         log_values = cell2mat(log_values);
0352       end
0353     else
0354       log_values = data_log.(log_field);
0355     end
0356     if log_param_filtering(log_param_idx)
0357       param_list.(log_field) = log_member_list;
0358       log.(log_field) = log_values;
0359     elseif any(log_member_filtering)
0360       param_list.(log_field) = log_member_list(log_member_filtering);
0361       log.(log_field) = log_values(:, log_member_filtering);
0362     end
0363   end
0364   
0365   
0366   %% Merge metadata.
0367   % Sort according mission and dive number (using a virtual rank index).
0368   num_log_headers = numel(meta_log.headers);
0369   num_eng_headers = numel(meta_eng.headers);
0370   all_miss_nums = vertcat(meta_log.headers.mission, meta_eng.headers.mission);
0371   all_dive_nums = vertcat(meta_log.headers.dive, meta_eng.headers.dive);
0372   [~, ~, miss_dive_sorting] = ...
0373     unique(  (all_dive_nums - min(all_dive_nums)) ...
0374            + (all_miss_nums - min(all_miss_nums)) ...
0375              * (max(all_dive_nums) - min(all_dive_nums) + 1));
0376   meta = struct();
0377   meta.logheaders(miss_dive_sorting(1:num_log_headers)) = meta_log.headers;
0378   meta.engheaders(miss_dive_sorting(num_log_headers + (1:num_eng_headers))) = ...
0379     meta_eng.headers;
0380   meta.sources = vertcat(meta_log.sources, meta_eng.sources);
0381   meta.start_secs = min_start_secs;
0382   meta.GCHEAD = meta_log.GCHEAD;
0383   meta.SENSORS = meta_log.SENSORS;
0384   meta.DEVICES = meta_log.DEVICES;
0385   meta.params = param_list;
0386   meta.columns = column_list;
0387   
0388   
0389   %% Convert output data to struct format if needed.
0390   switch output_format
0391     case 'array'
0392       data = struct();
0393       gps_field_list = {'GPSFIX'}';
0394       odd_field_list = {'RECOV_CODE' 'RESTART_TIME'}';
0395       field_list = intersect(fieldnames(meta.params), ...
0396                              vertcat(gps_field_list, odd_field_list));
0397       for field_idx = 1:numel(field_list)
0398         field = field_list{field_idx};
0399         value_list = log.(field);
0400         data.(field) = value_list;
0401       end
0402       log = struct2cell(rmfield(log, vertcat(gps_field_list, odd_field_list)));
0403       log_num = cellfun(@isnumeric, log);
0404       if any(log_num) && ~all(log_num)
0405         log(log_num) = cellfun(@num2cell, log(log_num), 'UniformOutput', false);
0406       end
0407       log = horzcat(log{:});
0408       data.log = log;
0409       logeng = struct2cell(logeng);
0410       logeng_num = cellfun(@isnumeric, logeng);
0411       if any(logeng_num) && ~all(logeng_num)
0412         logeng(logeng_num) = ...
0413           cellfun(@num2cell, logeng(logeng_num), 'UniformOutput', false);
0414       end
0415       logeng = horzcat(logeng{:});
0416       data.eng = logeng;
0417     case 'merged'
0418       data = struct();
0419       field_list = fieldnames(meta.params);
0420       for field_idx = 1:numel(field_list)
0421         field = field_list{field_idx};
0422         member_list = meta.params.(field);
0423         value_list = log.(field);
0424         if isempty(member_list)
0425           data.(field) = value_list;
0426         else
0427           for member_idx = 1:numel(member_list)
0428             member = member_list{member_idx};
0429             field_member = [field '_' member];
0430             value = value_list(:, member_idx);
0431             if iscell(value) && ~iscellstr(value)
0432               value = vertcat(value{:});
0433             end
0434             data.(field_member) = value;
0435           end
0436         end
0437       end
0438       field_list = meta.columns;
0439       for field_idx = 1:numel(field_list)
0440         field = field_list{field_idx};
0441         value = logeng.(field);
0442         if iscell(value) && ~iscellstr(value)
0443           value = vertcat(value{:});
0444         end
0445         data.(field) = value;
0446       end
0447     case 'struct'
0448       data = struct();
0449       field_list = fieldnames(meta.params);
0450       for field_idx = 1:numel(field_list)
0451         field = field_list{field_idx};
0452         member_list = meta.params.(field);
0453         value_list = log.(field);
0454         if isempty(member_list)
0455           data.(field) = value_list;
0456         else
0457           if isnumeric(value_list)
0458             value_list = num2cell(value_list);
0459           end
0460           data.(field) = cell2struct(value_list, member_list, 2);
0461         end
0462       end
0463       field_list = meta.columns;
0464       for field_idx = 1:numel(field_list)
0465         field = field_list{field_idx};
0466         value = logeng.(field);
0467         if iscell(value) && ~iscellstr(value)
0468           value = vertcat(value{:});
0469         end
0470         data.(field) = value;
0471       end
0472     otherwise
0473       error('glider_toolbox:sglogengmerge:InvalidFormat', ...
0474             'Invalid output format: %s.', output_format)
0475   end
0476 
0477 end

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