prints the contents of a data struct to screen and/or to file outdata = ensemble_print_datast(indata,defs) This simple script prints the contents of a given ensemble data structure to screen and/or to file. Given a single ensemble data structure, it will use "indata.vars" as the column names, and "indata.data" as the rows, and will print first the column names, then the rows, delimited by commas (default), or some other character (as defined by "defs"). Given nested ensemble data structures, or a cell array of data structures, it will iterate through each data structure and print the contents of each data structure. In this case, the function will recurse upon itself. NOTE: if there are semi-nested data structures, such that in a given data structure there are some columns that are not nested data structures, and some that are, this funciton will not output the data in that particular structure. NOTE: this function doesn't know how to deal with nested cells within indata.data columns. Currently, these are output as "MxN cell" REQUIRES indata.vars indata.data indata.name - if present, this will be used to identify data structure output, especially in the case of nested data structures. if no .name is found, but .type is found, .type will be used. indata.parent_name - if the function is given nested data structures, upon recursion, it will add this name to the resulting indata structure, and the contents of this name will be used to identify output at the given sub-struct level. indata.parent_name will be defined thus: sprintf('%s.%s',parent_indata_name,child_indata_name) defs.delim (default: comma) - the character or set of characters that will be used to delimit the output values defs.fid - if nested data structures are provided as input, the file id from the first iteration will be saved, passed on to recursive calls to this function, and used for output over defs.export. defs.export - parameters for ensemble_init_fid. if present, they will be used to try to print data to file. .print, .write2file, .fname, .filemode defs.print2screen (default: 1) - print data to the screen (stdout)? RETURNS indata - in the form it was provided
0001 function outdata = ensemble_print_datast(indata,defs) 0002 0003 % prints the contents of a data struct to screen and/or to file 0004 % 0005 % outdata = ensemble_print_datast(indata,defs) 0006 % 0007 % This simple script prints the contents of a given ensemble data structure 0008 % to screen and/or to file. Given a single ensemble data structure, it will 0009 % use "indata.vars" as the column names, and "indata.data" as the rows, and 0010 % will print first the column names, then the rows, delimited by commas 0011 % (default), or some other character (as defined by "defs"). 0012 % 0013 % Given nested ensemble data structures, or a cell array of data 0014 % structures, it will iterate through each data structure and print the 0015 % contents of each data structure. In this case, the function will recurse 0016 % upon itself. 0017 % 0018 % NOTE: if there are semi-nested data structures, such that in a given data 0019 % structure there are some columns that are not nested data structures, and 0020 % some that are, this funciton will not output the data in that particular 0021 % structure. 0022 % 0023 % NOTE: this function doesn't know how to deal with nested cells within 0024 % indata.data columns. Currently, these are output as "MxN cell" 0025 % 0026 % REQUIRES 0027 % indata.vars 0028 % indata.data 0029 % indata.name - if present, this will be used to identify data structure 0030 % output, especially in the case of nested data structures. if no 0031 % .name is found, but .type is found, .type will be used. 0032 % indata.parent_name - if the function is given nested data structures, 0033 % upon recursion, it will add this name to the resulting indata 0034 % structure, and the contents of this name will be used to identify 0035 % output at the given sub-struct level. indata.parent_name will be 0036 % defined thus: 0037 % 0038 % sprintf('%s.%s',parent_indata_name,child_indata_name) 0039 % 0040 % defs.delim (default: comma) - the character or set of characters that 0041 % will be used to delimit the output values 0042 % defs.fid - if nested data structures are provided as input, the file id 0043 % from the first iteration will be saved, passed on to recursive 0044 % calls to this function, and used for output over defs.export. 0045 % defs.export - parameters for ensemble_init_fid. if present, they will 0046 % be used to try to print data to file. 0047 % .print, .write2file, .fname, .filemode 0048 % defs.print2screen (default: 1) - print data to the screen (stdout)? 0049 % 0050 % RETURNS 0051 % indata - in the form it was provided 0052 0053 % FB <fbarrett@ucdavis.edu> 2010.10.18 0054 % 24Jul2013 - Petr Janata - added handling of logicals as well as standar 0055 % filtering 0056 % 25Jan2015 - added option of enclosing strings containing commas in 0057 % quotes. This is now the default behavior when comma-delimited 0058 % 29Aug2016 - PJ added optional output of datatype row and handling for R 0059 0060 %% set variables 0061 outdata = indata; 0062 ic = set_var_col_const(indata.vars); 0063 nc = length(indata.vars); 0064 0065 if nargin < 2 0066 defs = struct; 0067 end 0068 0069 try delim = defs.delim; catch delim = ','; end 0070 try print2screen = defs.print2screen; catch print2screen = 1; end 0071 0072 name = ''; 0073 if isfield(indata,'name') 0074 name = indata.name; 0075 elseif isfield(indata,'type') 0076 name = indata.type; 0077 elseif isfield(defs,'name') 0078 name = defs.name; 0079 end 0080 if ~isempty(name) && isfield(indata,'parent_name') 0081 name = sprintf('%s.%s',indata.parent_name,name); 0082 end 0083 0084 parent = 0; 0085 fid = 0; 0086 if isfield(defs,'fid') 0087 fid = defs.fid; 0088 elseif isfield(defs,'export') 0089 fid = ensemble_init_fid(defs.export); 0090 defs.fid = fid; 0091 parent = 1; 0092 end 0093 0094 if isfield(defs,'print2screen') 0095 print2screen = defs.print2screen; 0096 else 0097 print2screen = 1; 0098 end 0099 0100 if isfield(defs, 'outputType') 0101 outputType = defs.outputType; 0102 else 0103 outputType = 'SAS'; 0104 end 0105 0106 0107 % Add quotes around field contents if they contain a comma? 0108 if isfield(defs,'enclose_commas') 0109 encloseCommas = defs.enclose_commas; 0110 else 0111 if strcmp(delim,',') 0112 encloseCommas = 1; 0113 else 0114 encloseCommas = 0; 0115 end 0116 end 0117 0118 if ~fid && ~print2screen, error('no output specified'); end 0119 0120 %% check to see if there are nested data structures 0121 nested = zeros(1,nc); 0122 for k=1:nc 0123 if isstruct(indata.data{k}) 0124 if isfield(indata.data{k},'data') && isfield(indata.data{k},'vars') 0125 % nested data structure is found 0126 nested(k) = 1; 0127 0128 % recurse 0129 recdata = indata.data{k}; 0130 if ~isempty(name), recdata.parent_name = name; end 0131 ensemble_print_datast(recdata,defs); 0132 else 0133 nested(k) = -1; 0134 msg = 'bad input structure found'; 0135 if ~isempty(name), msg = sprintf('%s in %s',msg,name); end 0136 msg = sprintf('%s, SKIPPING',msg); 0137 warning(msg); 0138 end 0139 end % end if isstruct(indata.data{k 0140 end % for k=1:nc 0141 0142 if any(nested) && ~all(nested) 0143 msg = 'some, but not all, nested data structures found'; 0144 if ~isempty(name), msg = sprintf('%s in %s',msg,name); end 0145 msg = sprintf('%s, SKIPPING non-nested structures',msg); 0146 warning(msg); 0147 return 0148 elseif all(nested) 0149 return 0150 end 0151 0152 %% Perform filtering 0153 if isfield(defs, 'filt') && ~isempty(defs.filt) 0154 indata = ensemble_filter(indata, defs.filt); 0155 end 0156 0157 %% Check to see if there are multiple columns within any given variable 0158 for ivar = 1:nc 0159 dims = size(indata.data{ivar}); 0160 if dims(2) > 1 0161 warning('Variable <%s> contains %d columns. Only using values in first column', indata.vars{ivar}, dims(2)); 0162 end 0163 end 0164 0165 %% non-nested data structure, so print it out 0166 % print header lines 0167 if ~isempty(name) && isfield(defs, 'print_header') && defs.print_header 0168 if print2screen, fprintf(1,'----------\nSource: %s\n----------\n\n',name); end 0169 if fid, fprintf(fid,'----------\nSource: %s\n----------\n\n',name); end 0170 end 0171 0172 % print variable names 0173 varstr = cell2str(indata.vars,delim); 0174 if print2screen, fprintf(1,'%s\n',varstr); end 0175 if fid, fprintf(fid,'%s\n',varstr); end 0176 0177 % Check whether we are also writing a line of datatypes 0178 haveDatatypeInfo = 0; 0179 if isfield(defs, 'write_datatype') && defs.write_datatype 0180 % Make sure we have a datatype field in the input data and that it 0181 % matches vars in length 0182 if isfield(indata, 'datatype') && (length(indata.datatype) == length(indata.vars)) 0183 haveDatatypeInfo = 1; 0184 0185 if strcmp(outputType,'R') 0186 datatype = strrep(indata.datatype,'n','numeric'); 0187 datatype = strrep(datatype,'l','logical'); 0188 datatype = strrep(datatype,'s','character'); 0189 end 0190 datatypestr = cell2str(datatype,','); 0191 0192 if print2screen, fprintf(1,'%s\n', dataypestr); end 0193 if fid, fprintf(fid,'%s\n', datatypestr); end 0194 end 0195 end % if isfield(params, 'write_datatype') 0196 0197 % iterate over rows, print data 0198 for k=1:size(indata.data{1},1) 0199 % generate data string for the given row 0200 inputstr = ''; 0201 for l=1:nc 0202 data = indata.data{l}(k); 0203 if iscell(data) 0204 if iscell(data{1}) 0205 data = sprintf('%dx%d cell',size(data,1),size(data,2)); 0206 else 0207 data = data{1}; 0208 end 0209 end 0210 0211 if isnan(data) 0212 if strcmp(outputType,'R') 0213 data = 'NA'; 0214 end 0215 0216 elseif isnumeric(data) 0217 % Check whether we have datatype info and this is actually a logical 0218 if haveDatatypeInfo && strcmp(outputType,'R') && strcmp(datatype{l},'logical') 0219 if data 0220 data = 'TRUE'; 0221 else 0222 data = 'FALSE'; 0223 end 0224 else 0225 data = num2str(data); 0226 end 0227 0228 elseif islogical(data) 0229 if strcmp(outputType,'R') 0230 if ~data 0231 data = 'FALSE'; 0232 else 0233 data = 'TRUE'; 0234 end 0235 else 0236 data = num2str(data); 0237 end 0238 end 0239 0240 if l > 1, inputstr = [inputstr delim]; end 0241 0242 if encloseCommas && any(data == ',') 0243 data = sprintf('"%s"',data); 0244 end 0245 0246 inputstr = [inputstr data]; 0247 end 0248 0249 % print to screen and/or file 0250 if print2screen, fprintf(1,'%s\n',inputstr); end 0251 if fid, fprintf(fid,'%s\n',inputstr); end 0252 end % for k=1:length(indata.data{1 0253 0254 %% clean up? 0255 % print a few extra line endings 0256 if print2screen, fprintf(1,'\n\n'); end 0257 if fid, fprintf(1,'\n\n'); end 0258 0259 % if this call opened a file id, we should close it 0260 if parent, fclose(fid); end