Home > database > ensemble_concat_datastruct.m

ensemble_concat_datastruct

PURPOSE ^

Concatenates a cell array of structs into a single struct.

SYNOPSIS ^

function result_st = ensemble_concat_datastruct(data_st,params)

DESCRIPTION ^

 Concatenates a cell array of structs into a single struct.
 result_st = ensemble_concat_datastruct(data_st,params);

 Concatenates a cell array of data structures in data_st and returns a single
 data structure.  The function checks to make sure that the variables and
 their orders match exactly across the different data structures.

 If params.type_as_var is true, then data structures are organized by type,
 such that each type, e.g. response_data becomes a single variable in the
 resulting structure. Note that multiple data structure types are accommodated
 in this way in a single call to ensemble_concat_datastruct.  It is
 recommended that this variable is set to true, but it is currently set to
 false by default for purposes of backward compatibility.

 See also ensemble_combine_datastructs() for more possibilities of
 combining datastructs with heterogeneous sets of variables.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function result_st = ensemble_concat_datastruct(data_st,params)
0002 % Concatenates a cell array of structs into a single struct.
0003 % result_st = ensemble_concat_datastruct(data_st,params);
0004 %
0005 % Concatenates a cell array of data structures in data_st and returns a single
0006 % data structure.  The function checks to make sure that the variables and
0007 % their orders match exactly across the different data structures.
0008 %
0009 % If params.type_as_var is true, then data structures are organized by type,
0010 % such that each type, e.g. response_data becomes a single variable in the
0011 % resulting structure. Note that multiple data structure types are accommodated
0012 % in this way in a single call to ensemble_concat_datastruct.  It is
0013 % recommended that this variable is set to true, but it is currently set to
0014 % false by default for purposes of backward compatibility.
0015 %
0016 % See also ensemble_combine_datastructs() for more possibilities of
0017 % combining datastructs with heterogeneous sets of variables.
0018 
0019 % 05/08/07 Petr Janata
0020 % 03/12/08 Petr Janata
0021 % 08/28/08 Fred Barrett - convert data_st from struct to cell array of
0022 % structs, if isstruct(data_st)
0023 % 01/07/09 Fred Barrett - if data_st{1} == struct('name','return_outdir'),
0024 % returns an empty string in result_st - makes compatible with
0025 % ensemble_jobman_parallel.m, which queries functions for default directories
0026 % within which to save job_struct data
0027 % 31Aug2014 PJ - Added checking/conversion of strings to cells to handle
0028 %                cases where there is only 1 row per data structure and
0029 %                strings are not enclosed in cells
0030 % 30Dec2014 PJ - added initialization of empty params struct in the event
0031 %                that none was passed in
0032 % 29Aug2015 PJ - made the appending of _concat to the name of the
0033 %                concatenated variable optional
0034 
0035 % return '' if data_st{1} == struct('name','return_outdir')
0036 if (iscell(data_st) && ~isempty(data_st) && isfield(data_st{1},'task') && ...
0037     ~isempty(strmatch('return_outdir',data_st{1}.task))) || ...
0038     (isstruct(data_st) && isfield(data_st,'task') && ...
0039     ~isempty(strmatch('return_outdir',data_st.task)))
0040   result_st = '';
0041   return
0042 end
0043 
0044 if nargin < 2
0045   params = struct;
0046 end
0047 
0048 result_st = ensemble_init_data_struct;
0049 if isfield(params,'outDataName')
0050   result_st.name=params.outDataName;
0051 else
0052   result_st.name='concat_datastruct';
0053 end
0054 
0055 if isfield(params,'outDataType')
0056   result_st.type=params.outDataType;
0057 else
0058   result_st.type='concat_datastruct';
0059 end
0060 
0061 nstruct = length(data_st);
0062 
0063 % ensemble_jobman will collect requries and present them as a
0064 % multi-dimensional struct. this script expects a cell array of structs, so
0065 % the following few lines converts isstruct(data_st) into iscell(data_st)
0066 if isstruct(data_st)
0067   old_data = data_st;
0068   data_st = {};
0069   for id=1:nstruct
0070     data_st{id} = old_data(id);
0071   end
0072 end
0073 
0074 % See if we want to group the input data structures by their type. If we do,
0075 % then the type becomes the type of the returning data structure (result_st).
0076 
0077 if isfield(params,'type_as_var')
0078   type_as_var = params.type_as_var; 
0079 else
0080   type_as_var = false; 
0081 end
0082 
0083 if isfield(params,'append_concat_to_name')
0084   append_concat_to_name = params.append_concat_to_name;
0085 else
0086   append_concat_to_name = true;
0087 end
0088 
0089 % Original versions of this script did not operate based on type
0090 if ~type_as_var
0091   
0092   % Copy the variables from the first data struct
0093   vars = data_st{1}.vars;
0094   nvars = length(vars);
0095   
0096   result_st.vars = vars;
0097   result_st.data = data_st{1}.data;
0098   
0099   if nstruct < 2
0100     return
0101   end
0102   
0103   for istruct = 2:nstruct
0104     for ivar = 1:nvars
0105       if ~strcmp(data_st{istruct}.vars{ivar},vars{ivar})
0106         fprintf('%s: variable mismatch: Found %s, expected %s\n', mfilename, ...
0107           data_st{istruct}.vars{ivar}, vars{ivar});
0108         result_st = ensemble_init_data_struct;
0109         return
0110       else
0111         if isempty(data_st{istruct}.data{ivar})
0112           error('Trying to concatenate empty data')
0113         end
0114         result_st.data{ivar} = [result_st.data{ivar}; data_st{istruct}.data{ivar}];
0115       end
0116     end % for ivar
0117   end % for istruct
0118   
0119 else
0120   % Get a list of unique datastruct types
0121   struct_types = cellfun(@getfield,data_st, ...
0122     ... %repmat({'name'},size(data_st)),'UniformOutput',false); % PJ 07Dec2010 - I think this is supposed to be type instead of name
0123     repmat({'type'},size(data_st)),'UniformOutput',false);
0124   
0125   unique_types = unique(struct_types);
0126   num_types = length(unique_types);
0127   
0128   result_st.vars = unique_types;
0129   for itype = 1:num_types
0130     curr_type = unique_types{itype};
0131     
0132     % Initialize a data struct for this particular data type
0133     curr_st = ensemble_init_data_struct;
0134     if append_concat_to_name
0135       curr_st.name = sprintf('%s_concat', curr_type);
0136     else
0137       curr_st.name = sprintf('%s', curr_type);      
0138     end
0139     curr_st.type = curr_type;
0140     
0141     % Find all of the instances in the input data structures that match this type
0142     st_idxs = strmatch(curr_type, struct_types);
0143     
0144     % Copy the variable names and data from the first instance
0145     vars = data_st{st_idxs(1)}.vars;
0146     nvars = length(vars);
0147     curr_st.vars = vars;
0148     
0149     curr_st.data = sanitize_char_data(data_st{st_idxs(1)}.data);
0150     
0151     % Match the variables and copy the data for the remaining structures
0152     for istruct = 2:length(st_idxs)
0153       for ivar = 1:nvars
0154         if ~strcmp(data_st{st_idxs(istruct)}.vars{ivar}, vars{ivar})
0155           fprintf('%s: variable mismatch: Found %s, expected %s\n', mfilename, ...
0156             data_st{st_idxs(istruct)}.vars{ivar}, vars{ivar});
0157           result_st = ensemble_init_data_struct;
0158           return
0159         else
0160           curr_st.data{ivar} = [curr_st.data{ivar}; ...
0161             sanitize_char_data(data_st{st_idxs(istruct)}.data{ivar})];
0162         end
0163       end
0164     end % for istruct=
0165     
0166     result_st.data{itype} = curr_st;
0167   end % for itype
0168 end % if type_as_var
0169 end % ensemble_concat_datastruct
0170 
0171 function data = sanitize_char_data(data)
0172   % Make sure that strings are in cells
0173   if iscell(data)
0174     nvars = length(data);
0175   else
0176     nvars = 1;
0177   end
0178   for ivar = 1:nvars
0179     if iscell(data) && ischar(data(ivar))
0180       data{ivar} = {data(ivar)};
0181     elseif ischar(data)
0182       data = {data};
0183     end
0184   end
0185 end

Generated on Wed 20-Sep-2023 04:00:50 by m2html © 2003