ILWDREAD Load an ILWD (Internal LightWeight Data) formatted XML file. ILWDREAD(FILENAME) returns a MATLAB struct representation of the ILWD file given by FILENAME. Each element of the ILWD is a MATLAB struct with field "tag" storing the element type, and additional fields storing the values of the attributes of the element. If the element is an array (such as real_8) a field named after the element ("real_8") stores the array data in MATLAB format. If the element is a container (such as ilwd) the member elements are stored as fields m1, m2, ... ILWDREAD(FILENAME, VERBOSE) turns on verbose output if VERBOSE is true (nonzero). This consists of a formatted representation of the structure but not the content of the ILWD (i.e. the tags and fields but not the data). The structure of ILWD files is often complex and this is reflected in the complicated structs produced by ILWDREAD. The struct can be navigated by typing the element names on the command line to see the available fields. >>>> ilwd = ilwdread('results.ilwd') ilwd = tag: 'ilwd' comment: 'ilwdread example' name: 'ligo:ldas:file' m1: [1x1 struct] >>>> ilwd.m1 ans = tag: 'int_4s' dims: 2 name: 'one two' int_4s: [2x1 double] >>>> ilwd.m1.int_4s ans = 1 2 It may be convenient to copy the data to a concisely named variable. >>>> a = ilwd.m1.int_4s; The member structs fields of a struct must be name-mangled (m1, m2, ...) rather than subscripted (m(1), m(2), ...) to allow them to represent different structures. The EVAL command can be used to simulate subscripting, replacing "data.m(i)" with "eval(['data.m' i])". The array fields are MATLAB vectors containing numerical data. The values are preserved but the format is not (for example, int types are converted to double). Complex types are also unpacked to construct complex vectors. ILWDREAD accepts only uncompressed ASCII ILWD files. Any non-standard attributes should be correctly parsed to a string (but will issue a warning). Any non-standard tags will cause an error. Bugs and comments to Antony.Searle@anu.edu.au See also
0001 function data = ilwdread(filename, verbose) 0002 %ILWDREAD Load an ILWD (Internal LightWeight Data) formatted XML file. 0003 % ILWDREAD(FILENAME) returns a MATLAB struct representation of the ILWD file 0004 % given by FILENAME. Each element of the ILWD is a MATLAB struct with field 0005 % "tag" storing the element type, and additional fields storing the values of 0006 % the attributes of the element. If the element is an array (such as real_8) 0007 % a field named after the element ("real_8") stores the array data in MATLAB 0008 % format. If the element is a container (such as ilwd) the member elements 0009 % are stored as fields m1, m2, ... 0010 % 0011 % ILWDREAD(FILENAME, VERBOSE) turns on verbose output if VERBOSE is true 0012 % (nonzero). This consists of a formatted representation of the structure 0013 % but not the content of the ILWD (i.e. the tags and fields but not the 0014 % data). 0015 % 0016 % The structure of ILWD files is often complex and this is reflected in the 0017 % complicated structs produced by ILWDREAD. The struct can be navigated by 0018 % typing the element names on the command line to see the available fields. 0019 % 0020 % >>>> ilwd = ilwdread('results.ilwd') 0021 % 0022 % ilwd = 0023 % 0024 % tag: 'ilwd' 0025 % comment: 'ilwdread example' 0026 % name: 'ligo:ldas:file' 0027 % m1: [1x1 struct] 0028 % 0029 % >>>> ilwd.m1 0030 % 0031 % ans = 0032 % 0033 % tag: 'int_4s' 0034 % dims: 2 0035 % name: 'one two' 0036 % int_4s: [2x1 double] 0037 % 0038 % >>>> ilwd.m1.int_4s 0039 % 0040 % ans = 0041 % 0042 % 1 0043 % 2 0044 % 0045 % It may be convenient to copy the data to a concisely named variable. 0046 % 0047 % >>>> a = ilwd.m1.int_4s; 0048 % 0049 % The member structs fields of a struct must be name-mangled (m1, m2, ...) 0050 % rather than subscripted (m(1), m(2), ...) to allow them to represent 0051 % different structures. The EVAL command can be used to simulate 0052 % subscripting, replacing "data.m(i)" with "eval(['data.m' i])". 0053 % 0054 % The array fields are MATLAB vectors containing numerical data. The 0055 % values are preserved but the format is not (for example, int types are 0056 % converted to double). Complex types are also unpacked to construct 0057 % complex vectors. 0058 % 0059 % ILWDREAD accepts only uncompressed ASCII ILWD files. Any non-standard 0060 % attributes should be correctly parsed to a string (but will issue a 0061 % warning). Any non-standard tags will cause an error. Bugs and comments 0062 % to Antony.Searle@anu.edu.au 0063 % 0064 % See also 0065 0066 % Author : Antony C. Searle 0067 % Version: 0.2 0068 0069 fid = fopen(filename, 'rt'); % open the file 0070 if fid == -1 % check for errors 0071 error('open failed'); 0072 end 0073 header = fscanf(fid, '%c', 8); % read in the file header 0074 if nargin < 2 % check for a verbose argument 0075 verbose = 0; % no argument so set to default (quiet) 0076 end 0077 if header ~= '<?ilwd?>' % confirm we have an ilwd file 0078 error(['unhandled format ' header]); 0079 end 0080 if verbose 0081 disp(header); 0082 end 0083 data = parsetag(fid, '', verbose); % recursively parse the ilwd element 0084 fclose(fid); % close the file 0085 0086 % parsetag helper function 0087 0088 function data = parsetag(fid, indent, verbose); 0089 %PARSETAG Recursively parse ILWD tags for ILWDREAD 0090 % See also ILWDREAD 0091 0092 % Author : Antony C. Searle 0093 % Version: 0.2 0094 0095 c = fscanf(fid, '%c', 1); % find the tag start 0096 while c ~= '<' 0097 c = fscanf(fid, '%c', 1); 0098 end 0099 0100 [data.tag, terminator] = parseidentifier(fid); 0101 % read the tag 0102 0103 local_ndim = 1; % set default attribute values 0104 local_size = 1; 0105 local_dims = 1; 0106 0107 if verbose 0108 disp([indent '<' data.tag]); 0109 end 0110 0111 flag = 1; 0112 while flag % parse attributes 0113 if terminator ~= '>' % if not at the tag end, parse an 0114 % attribute 0115 [string, terminator] = parseidentifier(fid); 0116 end 0117 switch terminator % switch on identifier terminating 0118 % character 0119 case '=' % assigned attribute 0120 fscanf(fid, '%c', 1); % ignore opening quote 0121 switch string % switch on attribute name 0122 case 'size' 0123 data.size = fscanf(fid, '%d', 1); 0124 % read decimal integer 0125 local_size = data.size; 0126 fscanf(fid, '%c', 1); % ignore the closing quote 0127 if verbose 0128 disp([indent ' size=' num2str(data.size)]); 0129 end 0130 case 'ndim' 0131 data.ndim = fscanf(fid, '%d', 1); 0132 % read decimal integer 0133 local_ndim = data.ndim; 0134 fscanf(fid, '%c', 1); % ignore the closing quote 0135 if verbose 0136 disp([indent ' ndim=' num2str(data.ndim)]); 0137 end 0138 case 'dims' 0139 data.dims = 1; % touch the field 0140 for i = 1:local_ndim % loop over dimensions 0141 data.dims(i) = fscanf(fid, '%d', 1); 0142 % read in dimensions 0143 fscanf(fid, '%c', 1); % ignore the closing quote 0144 end 0145 local_dims = data.dims; 0146 if verbose 0147 disp([indent ' dims=' num2str(data.dims)]); 0148 end 0149 case 'comment' 0150 [data.comment, terminator] = parseattribute(fid); 0151 % read string 0152 if verbose 0153 disp([indent ' comment=' data.comment]); 0154 end 0155 case 'name' 0156 [data.name, terminator] = parseattribute(fid); 0157 % read string 0158 if verbose 0159 disp([indent ' name=' data.name]); 0160 end 0161 case 'units' 0162 [data.units, terminator] = parseattribute(fid); 0163 % read string 0164 if verbose 0165 disp([indent ' units=' data.units]); 0166 end 0167 case 'mdorder' 0168 [data.mdorder, terminator] = parseattribute(fid); 0169 % read string 0170 if verbose 0171 disp([indent ' mdorder=' data.mdorder]); 0172 end 0173 case 'nullmask' 0174 [data.nullmask, terminator] = parseattribute(fid); 0175 %read string 0176 if verbose 0177 disp([indent ' nullmask=' data.nullmask]); 0178 end 0179 case 'format' 0180 [data.format, terminator] = parseattribute(fid); 0181 % read string 0182 if verbose 0183 disp([indent ' format=' data.format]); 0184 end 0185 if data.format ~= 'ascii' % check format is ASCII 0186 error(['unhandled format: ' data.format]); 0187 end 0188 case 'compression' 0189 [data.compression, terminator] = parseattribute(fid); 0190 % read string 0191 if verbose 0192 disp([indent ' format=' data.format]); 0193 end 0194 if (data.compression ~= 'none') | (data.compression ~= 'gzip0'); 0195 % check data is uncompressed 0196 error(['unhandled compression: ' data.compression']); 0197 end 0198 case 'byteorder' 0199 error(['unhandled binary attribute: byteorder']); 0200 % implies unsupported binary format 0201 case 'bytes' 0202 error(['unhandled binary attribute: bytes']); 0203 % implies unsupported binary format 0204 case 'parser' 0205 [data.parser, terminator] = parseattribute(fid); 0206 % read string 0207 if verbose 0208 disp([indent ' parser=' data.parser]); 0209 end 0210 case 'metadata' 0211 [data.metadata, terminator] = parseattribute(fid); 0212 % read string 0213 if verbose 0214 disp([indent ' metadata=' data.metadata]); 0215 end 0216 case 'dataValueUnit' 0217 [data.dataValueUnit, terminator] = parseattribute(fid); 0218 % read string 0219 if verbose 0220 disp([indent ' dataValueUnit=' data.dataValueUnit]); 0221 end 0222 case 'dx' 0223 data.dx = fscanf(fid, '%f', 1); 0224 % read floating-point number 0225 fscanf(fid, '%c', 1); % ignore the closing quote 0226 if verbose 0227 disp([indent ' dx=' num2str(data.dx)]); 0228 end 0229 case 'startx' 0230 data.startx = fscanf(fid, '%f', 1); 0231 % read floating-point number 0232 fscanf(fid, '%c', 1); % ignore the closing quote 0233 if verbose 0234 disp([indent ' startx=' num2str(data.startx)]); 0235 end 0236 otherwise 0237 disp(['warning: nonstandard attribute ' string]); 0238 eval(['[data.' string ', terminator] = parseattribute(fid);']); 0239 % read string into nonstandard attribute 0240 end 0241 case '>' % end of the tag 0242 if verbose 0243 disp([indent ' >']); 0244 end 0245 flag = 0; % stop while loop 0246 otherwise 0247 error(['unhandled character ' terminator]); 0248 % unexpected character 0249 end 0250 end 0251 0252 switch data.tag % switch on tag type 0253 case 'ilwd' % container type 0254 indent2 = [' ' indent]; % set indentation level 0255 for i = 1:local_size % read in "size" elements 0256 eval(['data.m' num2str(i) ' = parsetag(fid, indent2, verbose);']); 0257 % construct the field name and parse 0258 % into it 0259 end 0260 case 'char' 0261 data.char = fscanf(fid, '%c', data.dims); 0262 % read in "dims" characters 0263 case 'char_u' 0264 buffer = fscanf(fid, '%c%d'); % read in as many character-separated 0265 % decimal integers as possible 0266 data.char_u = buffer(2:2:length(buffer)); 0267 % strip out the integers 0268 case 'char_s' 0269 buffer = fscanf(fid, '%c%d'); % read in as many character-separated 0270 % decimal integers as possible 0271 data.char_s = buffer(2:2:length(buffer)); 0272 % strip out the integers 0273 case 'int_2u' 0274 data.int_2u = fscanf(fid, '%d'); % read in as many decimal integers as 0275 % possible 0276 case 'int_4u' 0277 data.int_4u = fscanf(fid, '%d'); % read in as many decimal integers as 0278 % possible 0279 case 'int_8u' 0280 data.int_8u = fscanf(fid, '%d'); % read in as many decimal integers as 0281 % possible 0282 case 'int_2s' 0283 data.int_2s = fscanf(fid, '%d'); % read in as many decimal integers as 0284 % possible 0285 case 'int_4s' 0286 data.int_4s = fscanf(fid, '%d'); % read in as many decimal integers as 0287 % possible 0288 case 'int_8s' 0289 data.int_8s = fscanf(fid, '%d'); % read in as many decimal integers as 0290 % possible 0291 case 'real_4' 0292 data.real_4 = fscanf(fid, '%f'); % read in as many decimal integers as 0293 % possible 0294 case 'real_8' 0295 data.real_8 = fscanf(fid, '%f'); % read in as many decimal integers as 0296 % possible 0297 case 'complex_8' 0298 buffer = fscanf(fid, '%f'); % read in as many floating point 0299 % decimals as possible 0300 data.complex_8 = buffer(1:2:size(buffer)) + buffer(2:2:size(buffer)) * ... 0301 sqrt(-1); % unpack to a complex array 0302 case 'complex_16' 0303 buffer = fscanf(fid, '%f'); % read in as many floating point 0304 % decimals as possible 0305 data.complex_16 = buffer(1:2:size(buffer)) + buffer(2:2:size(buffer)) * ... 0306 sqrt(-1); % unpack to a complex array 0307 case 'lstring' 0308 data.lstring = fscanf(fid, '%c', local_size); 0309 % read "size" characters into a string 0310 case 'external' 0311 data.external = fscanf(fid, '%c', local_size); 0312 % read "size" characters into a string 0313 otherwise 0314 error(['unrecognised tag ' data.tag]); 0315 % tag is not supported 0316 end 0317 0318 [string, terminator] = parseidentifier(fid); 0319 % ignore the end tag 0320 if verbose 0321 disp([indent string terminator]); 0322 end 0323 0324 % parseattribute helper function 0325 0326 function [string, terminator] = parseattribute(fid); 0327 %PARSEATTRIBUTE Parse attributes for ILWDREAD 0328 % See also ILWDREAD 0329 0330 % Author : Antony C. Searle 0331 % Version: 0.2 0332 0333 string = ''; % empty output 0334 flag = 1; 0335 while flag; % read in characters 0336 terminator = fscanf(fid, '%c', 1); % get a character 0337 switch terminator % switch on the character 0338 case double(39) % single-quote terminates 0339 flag = 0; 0340 case double(34) % double-quote terminates 0341 flag = 0; 0342 otherwise % any other character 0343 string = [string terminator]; % is part of output 0344 end 0345 end 0346 0347 % parseidentifer 0348 0349 function [string, terminator] = parseidentifier(fid); 0350 %PARSEIDENTIFIER Parse identifiers for ILWDREAD 0351 % See also ILWDREAD 0352 0353 % Author : Antony C. Searle 0354 % Version: 0.2 0355 0356 string = ''; % empty output 0357 flag = 1; 0358 white = 1; % leading whitespace? 0359 while flag; % read in characters 0360 terminator = fscanf(fid, '%c', 1); % get a character 0361 switch terminator % switch on the character 0362 case '=' % equals terminates 0363 flag = 0; 0364 case '>' % right-angle terminates 0365 flag = 0; 0366 case double(39) % single-quote terminates 0367 flag = 0; 0368 case double(34) % double-quote terminates 0369 flag = 0; 0370 case double(10) % newline terminates unless 0371 % still leading whitespace 0372 flag = white; 0373 case ' ' % space terminates unless 0374 % still leading whitespace 0375 flag = white; 0376 otherwise % any other character 0377 white = 0; % terminates whitespace 0378 string = [string terminator]; % and is part of output 0379 end 0380 end 0381 0382 0383 0384 0385 0386 0387