Ability to run the full experiment suite in unix
This commit is contained in:
parent
51f442a3e2
commit
1b13794a47
46 changed files with 5485 additions and 191 deletions
|
@ -0,0 +1,181 @@
|
||||||
|
|
||||||
|
% Function ParseSEMAINEAnnotations is intended to demonstrate example usage
|
||||||
|
% of SEMAINE Action Unit annotations made with ELAN annotation toolbox.
|
||||||
|
% This function loads the XML structure from an ELAN annotation file with
|
||||||
|
% ".eaf" extension, parses it and returns a numerical matrix called
|
||||||
|
% "activations" of size NUMBER OF FRAMES X NUMBER OF ACTION UNITS. The
|
||||||
|
% matrix holds binary activation status for each frame / AU combination.
|
||||||
|
% The matrix also has a row header showing which AU corresponds to which
|
||||||
|
% row as well as a column header displaying original frame indexes.
|
||||||
|
|
||||||
|
% The function takes 1 compulsory and 2 optional arguments:
|
||||||
|
|
||||||
|
% - "filepath" (compulsory) - complete path to an annotation file to parse.
|
||||||
|
% For example, "/matlab/annotation.eaf" or "C:\matlab\annotation.eaf" on
|
||||||
|
% Windows.
|
||||||
|
|
||||||
|
% - "startFrame" (optional) - ignore all annotations before "startFrame".
|
||||||
|
% Default is 1.
|
||||||
|
|
||||||
|
% - "endFrame" (optional) - ignore all annotations after "endFrame".
|
||||||
|
% Default is the last frame of a video.
|
||||||
|
|
||||||
|
% The function requires XML IO Toolbox
|
||||||
|
% (http://www.mathworks.com/matlabcentral/fileexchange/12907-xml-io-tools)
|
||||||
|
% to run properly (supplied).
|
||||||
|
|
||||||
|
function activations = ParseSEMAINEAnnotations (filepath, startFrame, endFrame)
|
||||||
|
activations = [];
|
||||||
|
|
||||||
|
% Framerate value used to convert ELAN millisecond time slots to more
|
||||||
|
% usual frames. 50 is a valid framerate for all SEMAINE videos.
|
||||||
|
framerate = 50;
|
||||||
|
|
||||||
|
% A fixed set of 6 Action Units selected for the challenge from the
|
||||||
|
% SEMAINE annotations
|
||||||
|
aus = [2 12 17 25 28 45];
|
||||||
|
|
||||||
|
% Total number of AUs.
|
||||||
|
naus = length(aus);
|
||||||
|
|
||||||
|
% Load XML structure from the file, return in case of a problem.
|
||||||
|
[success, XML] = OpenXML(filepath);
|
||||||
|
if ~success
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
% Parse annotation time slots
|
||||||
|
tslots = ParseTimeSlots(XML);
|
||||||
|
|
||||||
|
% Init start and end frames with default values
|
||||||
|
if nargin < 2
|
||||||
|
startFrame = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if nargin < 3
|
||||||
|
% Get total number of time slots
|
||||||
|
ntslots = length(tslots);
|
||||||
|
% Get last slot ID
|
||||||
|
lastID = strcat('ts', num2str(ntslots));
|
||||||
|
% Get last time slot value in ms
|
||||||
|
lastValue = tslots(lastID);
|
||||||
|
% Convert last time slot value in ms to frames
|
||||||
|
endFrame = floor((lastValue / 1000) * framerate);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Get total number of tiers. There are 65 of them, 1 for speech, 32 for
|
||||||
|
% activations (1 per AU) and 32 for intensities. We are going to ignore
|
||||||
|
% intensity tiers.
|
||||||
|
ntiers = length(XML.TIER);
|
||||||
|
|
||||||
|
% Compose vector of frame indexes to extract annotations from
|
||||||
|
frames = (startFrame:endFrame);
|
||||||
|
|
||||||
|
% Preallocate activations matrix
|
||||||
|
activations = zeros(length(frames), naus);
|
||||||
|
|
||||||
|
indx = 1;
|
||||||
|
% Go through all tiers skipping the first one (speech) as well as every
|
||||||
|
% intensity tier. A single activation tier is processed at every
|
||||||
|
% iteration.
|
||||||
|
for k = 2:2:ntiers
|
||||||
|
tier = XML.TIER(k);
|
||||||
|
% Only extract annotations of selected AUs, skip the rest
|
||||||
|
au = strcat('AU', num2str(aus(indx)));
|
||||||
|
if strcmp(au, tier.ATTRIBUTE.TIER_ID)
|
||||||
|
% Read all activation periods from the current tier
|
||||||
|
activationTier = ParseActivationTier(tier, tslots);
|
||||||
|
% Convert of all activation periods into frame level numerical
|
||||||
|
% representation
|
||||||
|
activations(:, indx) = ParseOccurrences(activationTier, frames, framerate);
|
||||||
|
|
||||||
|
indx = indx + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if indx > naus
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
activations = [frames' activations];
|
||||||
|
activations = [[0 aus]; activations];
|
||||||
|
end
|
||||||
|
|
||||||
|
function occurrences = ParseOccurrences (activations, frames, framerate)
|
||||||
|
% Preallocate activations vector
|
||||||
|
occurrences = zeros(length(frames), 1);
|
||||||
|
% Go through all activation periods, convert ms into frames and init
|
||||||
|
% corresponding values of activations vector with 1 leaving the rest be 0
|
||||||
|
for i = 1:length(activations)
|
||||||
|
% Convert ms into frames
|
||||||
|
sframe = floor((activations(i).start / 1000) * framerate);
|
||||||
|
eframe = floor((activations(i).end / 1000) * framerate);
|
||||||
|
|
||||||
|
% Determine indexes of frames vector corresponding to the above
|
||||||
|
% time frame
|
||||||
|
sindx = find(frames == sframe);
|
||||||
|
eindx = find(frames == eframe);
|
||||||
|
|
||||||
|
% Mark active set of frames with 1
|
||||||
|
occurrences(sindx:eindx) = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function activationTier = ParseActivationTier (tier, tslots)
|
||||||
|
% Get total number of activation periods
|
||||||
|
nactivations = length(tier.ANNOTATION);
|
||||||
|
% Preallocate activation tier structure holding start and end time
|
||||||
|
% stamps of all activation periods for the given AU
|
||||||
|
activationTier = repmat(struct('start', 0, 'end', 0), nactivations, 1);
|
||||||
|
% Go through all activation periods and init activation tier
|
||||||
|
% structure array
|
||||||
|
for i = 1:nactivations
|
||||||
|
% Read start time slot ID of the current activation period
|
||||||
|
t = tier.ANNOTATION(i).ALIGNABLE_ANNOTATION.ATTRIBUTE.TIME_SLOT_REF1;
|
||||||
|
% Read time in ms corresponding to the time slot ID
|
||||||
|
activationTier(i).start = tslots(t);
|
||||||
|
|
||||||
|
% Read end time slot ID of the current activation period
|
||||||
|
t = tier.ANNOTATION(i).ALIGNABLE_ANNOTATION.ATTRIBUTE.TIME_SLOT_REF2;
|
||||||
|
% Read time in ms corresponding to the time slot ID
|
||||||
|
activationTier(i).end = tslots(t);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function tslots = ParseTimeSlots (xmlObject)
|
||||||
|
% Get total number of time slots
|
||||||
|
nslots = length(xmlObject.TIME_ORDER.TIME_SLOT);
|
||||||
|
% Preallocate cell arrays of time slot IDs and values
|
||||||
|
tids = cell(nslots, 1);
|
||||||
|
tvalues = zeros(nslots, 1);
|
||||||
|
% Read all time slot IDs and numerical values (in ms)
|
||||||
|
for i = 1:nslots
|
||||||
|
tids{i} = xmlObject.TIME_ORDER.TIME_SLOT(i).ATTRIBUTE.TIME_SLOT_ID;
|
||||||
|
tvalues(i) = xmlObject.TIME_ORDER.TIME_SLOT(i).ATTRIBUTE.TIME_VALUE;
|
||||||
|
end
|
||||||
|
% Map time slot IDs and values together so that values are accessible
|
||||||
|
% by their IDs
|
||||||
|
tslots = containers.Map(tids, tvalues);
|
||||||
|
end
|
||||||
|
|
||||||
|
function [success, xmlObject] = OpenXML (xmlPath)
|
||||||
|
fprintf(' *** Attempting to load \"%s\" ... ', xmlPath);
|
||||||
|
xmlObject = [];
|
||||||
|
success = false;
|
||||||
|
% Check if the specified file exists and return error otherwise
|
||||||
|
if exist(xmlPath, 'file')
|
||||||
|
% Load XML structure
|
||||||
|
xmlObject = xml_read(xmlPath);
|
||||||
|
% Check if XML object loaded correctly, return error otherwise
|
||||||
|
if isempty(xmlObject)
|
||||||
|
fprintf(' ERROR - unable to read xml tree *** \n');
|
||||||
|
return
|
||||||
|
else
|
||||||
|
success = true;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fprintf(' ERROR - specified path does not exist *** \n');
|
||||||
|
return
|
||||||
|
end
|
||||||
|
fprintf(' Done *** \n');
|
||||||
|
end
|
|
@ -26,14 +26,9 @@ function [ labels, valid_ids, vid_ids ] = extract_SEMAINE_labels( SEMAINE_dir,
|
||||||
|
|
||||||
xml_file = [SEMAINE_dir, recs{i}, '\' file.name];
|
xml_file = [SEMAINE_dir, recs{i}, '\' file.name];
|
||||||
[root_xml, name_xml, ~] = fileparts(xml_file);
|
[root_xml, name_xml, ~] = fileparts(xml_file);
|
||||||
m_file = [root_xml, name_xml, '.mat'];
|
|
||||||
|
|
||||||
if(~exist(m_file, 'file'))
|
activations = ParseSEMAINEAnnotations([SEMAINE_dir, recs{i}, '/' file.name]);
|
||||||
activations = ParseSEMAINEAnnotations([SEMAINE_dir, recs{i}, '\' file.name]);
|
|
||||||
save(m_file, 'activations');
|
|
||||||
else
|
|
||||||
load(m_file);
|
|
||||||
end
|
|
||||||
if(size(activations,1) < vid_ids(i,2))
|
if(size(activations,1) < vid_ids(i,2))
|
||||||
vid_ids(i,2) = size(activations,1);
|
vid_ids(i,2) = size(activations,1);
|
||||||
if(vid_ids(i,2) > 2999)
|
if(vid_ids(i,2) > 2999)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
if(exist('D:\Datasets\fera/au_training', 'file'))
|
if(exist('D:\Datasets\fera/au_training', 'file'))
|
||||||
FERA2011_dir = 'D:\Datasets\fera/au_training/';
|
FERA2011_dir = 'D:\Datasets\fera/au_training/';
|
||||||
hog_data_dir = 'D:\Datasets\face_datasets\hog_aligned_rigid/';
|
elseif(exist('/multicomp/datasets/fera2011/', 'file'))
|
||||||
|
FERA2011_dir = '/multicomp/datasets/fera2011/au_training/';
|
||||||
else
|
else
|
||||||
fprintf('FERA2011 location not found (or not defined)\n');
|
fprintf('FERA2011 location not found (or not defined)\n');
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,8 +10,10 @@ elseif(exist('D:\Datasets\FERA_2015\semaine\SEMAINE-Sessions/', 'file'))
|
||||||
SEMAINE_dir = 'D:\Datasets\FERA_2015\semaine\SEMAINE-Sessions/';
|
SEMAINE_dir = 'D:\Datasets\FERA_2015\semaine\SEMAINE-Sessions/';
|
||||||
elseif(exist('D:/fera_2015/semaine/SEMAINE-Sessions/', 'file'))
|
elseif(exist('D:/fera_2015/semaine/SEMAINE-Sessions/', 'file'))
|
||||||
SEMAINE_dir = 'D:/fera_2015/semaine/SEMAINE-Sessions/';
|
SEMAINE_dir = 'D:/fera_2015/semaine/SEMAINE-Sessions/';
|
||||||
|
elseif(exist('/multicomp/datasets/face_datasets/FERA_2015/Semaine/SEMAINE-Sessions/', 'file'))
|
||||||
|
SEMAINE_dir = '/multicomp/datasets/face_datasets/FERA_2015/Semaine/SEMAINE-Sessions/';
|
||||||
else
|
else
|
||||||
fprintf('DISFA location not found (or not defined)\n');
|
fprintf('SEMAINE location not found (or not defined)\n');
|
||||||
end
|
end
|
||||||
|
|
||||||
if(exist('SEMAINE_dir', 'var'))
|
if(exist('SEMAINE_dir', 'var'))
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
function y = base64decode(x, outfname, alg)
|
||||||
|
%BASE64DECODE Perform base64 decoding on a string.
|
||||||
|
%
|
||||||
|
% INPUT:
|
||||||
|
% x - block of data to be decoded. Can be a string or a numeric
|
||||||
|
% vector containing integers in the range 0-255. Any character
|
||||||
|
% not part of the 65-character base64 subset set is silently
|
||||||
|
% ignored. Characters occuring after a '=' padding character are
|
||||||
|
% never decoded. If the length of the string to decode (after
|
||||||
|
% ignoring non-base64 chars) is not a multiple of 4, then a
|
||||||
|
% warning is generated.
|
||||||
|
%
|
||||||
|
% outfname - if provided the binary date from decoded string will be
|
||||||
|
% saved into a file. Since Base64 coding is often used to embbed
|
||||||
|
% binary data in xml files, this option can be used to extract and
|
||||||
|
% save them.
|
||||||
|
%
|
||||||
|
% alg - Algorithm to use: can take values 'java' or 'matlab'. Optional
|
||||||
|
% variable defaulting to 'java' which is a little faster. If
|
||||||
|
% 'java' is chosen than core of the code is performed by a call to
|
||||||
|
% a java library. Optionally all operations can be performed using
|
||||||
|
% matleb code.
|
||||||
|
%
|
||||||
|
% OUTPUT:
|
||||||
|
% y - array of binary data returned as uint8
|
||||||
|
%
|
||||||
|
% This function is used to decode strings from the Base64 encoding specified
|
||||||
|
% in RFC 2045 - MIME (Multipurpose Internet Mail Extensions). The Base64
|
||||||
|
% encoding is designed to represent arbitrary sequences of octets in a form
|
||||||
|
% that need not be humanly readable. A 65-character subset ([A-Za-z0-9+/=])
|
||||||
|
% of US-ASCII is used, enabling 6 bits to be represented per printable
|
||||||
|
% character.
|
||||||
|
%
|
||||||
|
% See also BASE64ENCODE.
|
||||||
|
%
|
||||||
|
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||||||
|
%
|
||||||
|
% Matlab version based on 2004 code by Peter J. Acklam
|
||||||
|
% E-mail: pjacklam@online.no
|
||||||
|
% URL: http://home.online.no/~pjacklam
|
||||||
|
% http://home.online.no/~pjacklam/matlab/software/util/datautil/base64encode.m
|
||||||
|
|
||||||
|
if nargin<3, alg='java'; end
|
||||||
|
if nargin<2, outfname=''; end
|
||||||
|
|
||||||
|
%% if x happen to be a filename than read the file
|
||||||
|
if (numel(x)<256)
|
||||||
|
if (exist(x, 'file')==2)
|
||||||
|
fid = fopen(x,'rb');
|
||||||
|
x = fread(fid, 'uint8');
|
||||||
|
fclose(fid);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
x = uint8(x(:)); % unify format
|
||||||
|
|
||||||
|
%% Perform conversion
|
||||||
|
switch (alg)
|
||||||
|
case 'java'
|
||||||
|
base64 = org.apache.commons.codec.binary.Base64;
|
||||||
|
y = base64.decode(x);
|
||||||
|
y = mod(int16(y),256); % convert from int8 to uint8
|
||||||
|
case 'matlab'
|
||||||
|
%% Perform the mapping
|
||||||
|
% A-Z -> 0 - 25
|
||||||
|
% a-z -> 26 - 51
|
||||||
|
% 0-9 -> 52 - 61
|
||||||
|
% + - -> 62 '-' is URL_SAFE alternative
|
||||||
|
% / _ -> 63 '_' is URL_SAFE alternative
|
||||||
|
map = uint8(zeros(1,256)+65);
|
||||||
|
map(uint8(['A':'Z', 'a':'z', '0':'9', '+/=']))= 0:64;
|
||||||
|
map(uint8('-_'))= 62:63; % URL_SAFE alternatives
|
||||||
|
x = map(x); % mapping
|
||||||
|
|
||||||
|
x(x>64)=[]; % remove non-base64 chars
|
||||||
|
if rem(numel(x), 4)
|
||||||
|
warning('Length of base64 data not a multiple of 4; padding input.');
|
||||||
|
end
|
||||||
|
x(x==64)=[]; % remove padding characters
|
||||||
|
|
||||||
|
%% add padding and reshape
|
||||||
|
nebytes = length(x); % number of encoded bytes
|
||||||
|
nchunks = ceil(nebytes/4); % number of chunks/groups
|
||||||
|
if rem(nebytes, 4)>0
|
||||||
|
x(end+1 : 4*nchunks) = 0; % add padding
|
||||||
|
end
|
||||||
|
x = reshape(uint8(x), 4, nchunks);
|
||||||
|
y = repmat(uint8(0), 3, nchunks); % for the decoded data
|
||||||
|
|
||||||
|
%% Rearrange every 4 bytes into 3 bytes
|
||||||
|
% 00aaaaaa 00bbbbbb 00cccccc 00dddddd
|
||||||
|
% to form
|
||||||
|
% aaaaaabb bbbbcccc ccdddddd
|
||||||
|
y(1,:) = bitshift(x(1,:), 2); % 6 highest bits of y(1,:)
|
||||||
|
y(1,:) = bitor(y(1,:), bitshift(x(2,:), -4)); % 2 lowest bits of y(1,:)
|
||||||
|
y(2,:) = bitshift(x(2,:), 4); % 4 highest bits of y(2,:)
|
||||||
|
y(2,:) = bitor(y(2,:), bitshift(x(3,:), -2)); % 4 lowest bits of y(2,:)
|
||||||
|
y(3,:) = bitshift(x(3,:), 6); % 2 highest bits of y(3,:)
|
||||||
|
y(3,:) = bitor(y(3,:), x(4,:)); % 6 lowest bits of y(3,:)
|
||||||
|
|
||||||
|
%% remove extra padding
|
||||||
|
switch rem(nebytes, 4)
|
||||||
|
case 2
|
||||||
|
y = y(1:end-2);
|
||||||
|
case 3
|
||||||
|
y = y(1:end-1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% reshape to a row vector and make it a character array
|
||||||
|
y = uint8(reshape(y, 1, numel(y)));
|
||||||
|
|
||||||
|
%% save to file if needed
|
||||||
|
if ~isempty(outfname)
|
||||||
|
fid = fopen(outfname,'wb');
|
||||||
|
fwrite(fid, y, 'uint8');
|
||||||
|
fclose(fid);
|
||||||
|
end
|
|
@ -0,0 +1,138 @@
|
||||||
|
function y = base64encode(x, alg, isChunked, url_safe)
|
||||||
|
%BASE64ENCODE Perform base64 encoding on a string.
|
||||||
|
% INPUT:
|
||||||
|
% x - block of data to be encoded. Can be a string or a numeric
|
||||||
|
% vector containing integers in the range 0-255.
|
||||||
|
% alg - Algorithm to use: can take values 'java' or 'matlab'. Optional
|
||||||
|
% variable defaulting to 'java' which is a little faster. If
|
||||||
|
% 'java' is chosen than core of the code is performed by a call to
|
||||||
|
% a java library. Optionally all operations can be performed using
|
||||||
|
% matleb code.
|
||||||
|
% isChunked - encode output into 76 character blocks. The returned
|
||||||
|
% encoded string is broken into lines of no more than
|
||||||
|
% 76 characters each, and each line will end with EOL. Notice that
|
||||||
|
% if resulting string is saved as part of an xml file, those EOL's
|
||||||
|
% are often stripped by xmlwrite funtrion prior to saving.
|
||||||
|
% url_safe - use Modified Base64 for URL applications ('base64url'
|
||||||
|
% encoding) "Base64 alphabet" ([A-Za-z0-9-_=]).
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% OUTPUT:
|
||||||
|
% y - character array using only "Base64 alphabet" characters
|
||||||
|
%
|
||||||
|
% This function may be used to encode strings into the Base64 encoding
|
||||||
|
% specified in RFC 2045 - MIME (Multipurpose Internet Mail Extensions).
|
||||||
|
% The Base64 encoding is designed to represent arbitrary sequences of
|
||||||
|
% octets in a form that need not be humanly readable. A 65-character
|
||||||
|
% subset ([A-Za-z0-9+/=]) of US-ASCII is used, enabling 6 bits to be
|
||||||
|
% represented per printable character.
|
||||||
|
%
|
||||||
|
% See also BASE64DECODE.
|
||||||
|
%
|
||||||
|
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||||||
|
%
|
||||||
|
% Matlab version based on 2004 code by Peter J. Acklam
|
||||||
|
% E-mail: pjacklam@online.no
|
||||||
|
% URL: http://home.online.no/~pjacklam
|
||||||
|
% http://home.online.no/~pjacklam/matlab/software/util/datautil/base64encode.m
|
||||||
|
|
||||||
|
if nargin<2, alg='java'; end
|
||||||
|
if nargin<3, isChunked=false; end
|
||||||
|
if ~islogical(isChunked)
|
||||||
|
if isnumeric(isChunked)
|
||||||
|
isChunked=(isChunked>0);
|
||||||
|
else
|
||||||
|
isChunked=false;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if nargin<4, url_safe=false; end
|
||||||
|
if ~islogical(url_safe)
|
||||||
|
if isnumeric(url_safe)
|
||||||
|
url_safe=(url_safe>0);
|
||||||
|
else
|
||||||
|
url_safe=false;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
%% if x happen to be a filename than read the file
|
||||||
|
if (numel(x)<256)
|
||||||
|
if (exist(x, 'file')==2)
|
||||||
|
fid = fopen(x,'rb');
|
||||||
|
x = fread(fid, 'uint8'); % read image file as a raw binary
|
||||||
|
fclose(fid);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Perform conversion
|
||||||
|
switch (alg)
|
||||||
|
case 'java'
|
||||||
|
base64 = org.apache.commons.codec.binary.Base64;
|
||||||
|
y = base64.encodeBase64(x, isChunked);
|
||||||
|
if url_safe
|
||||||
|
y = strrep(y,'=','-');
|
||||||
|
y = strrep(y,'/','_');
|
||||||
|
end
|
||||||
|
|
||||||
|
case 'matlab'
|
||||||
|
|
||||||
|
%% add padding if necessary, to make the length of x a multiple of 3
|
||||||
|
x = uint8(x(:));
|
||||||
|
ndbytes = length(x); % number of decoded bytes
|
||||||
|
nchunks = ceil(ndbytes / 3); % number of chunks/groups
|
||||||
|
if rem(ndbytes, 3)>0
|
||||||
|
x(end+1 : 3*nchunks) = 0; % add padding
|
||||||
|
end
|
||||||
|
x = reshape(x, [3, nchunks]); % reshape the data
|
||||||
|
y = repmat(uint8(0), 4, nchunks); % for the encoded data
|
||||||
|
|
||||||
|
%% Split up every 3 bytes into 4 pieces
|
||||||
|
% aaaaaabb bbbbcccc ccdddddd
|
||||||
|
% to form
|
||||||
|
% 00aaaaaa 00bbbbbb 00cccccc 00dddddd
|
||||||
|
y(1,:) = bitshift(x(1,:), -2); % 6 highest bits of x(1,:)
|
||||||
|
y(2,:) = bitshift(bitand(x(1,:), 3), 4); % 2 lowest bits of x(1,:)
|
||||||
|
y(2,:) = bitor(y(2,:), bitshift(x(2,:), -4)); % 4 highest bits of x(2,:)
|
||||||
|
y(3,:) = bitshift(bitand(x(2,:), 15), 2); % 4 lowest bits of x(2,:)
|
||||||
|
y(3,:) = bitor(y(3,:), bitshift(x(3,:), -6)); % 2 highest bits of x(3,:)
|
||||||
|
y(4,:) = bitand(x(3,:), 63); % 6 lowest bits of x(3,:)
|
||||||
|
|
||||||
|
%% Perform the mapping
|
||||||
|
% 0 - 25 -> A-Z
|
||||||
|
% 26 - 51 -> a-z
|
||||||
|
% 52 - 61 -> 0-9
|
||||||
|
% 62 -> +
|
||||||
|
% 63 -> /
|
||||||
|
map = ['A':'Z', 'a':'z', '0':'9', '+/'];
|
||||||
|
if (url_safe), map(63:64)='-_'; end
|
||||||
|
y = map(y(:)+1);
|
||||||
|
|
||||||
|
%% Add padding if necessary.
|
||||||
|
npbytes = 3 * nchunks - ndbytes; % number of padding bytes
|
||||||
|
if npbytes>0
|
||||||
|
y(end-npbytes+1 : end) = '='; % '=' is used for padding
|
||||||
|
end
|
||||||
|
|
||||||
|
%% break into lines with length LineLength
|
||||||
|
if (isChunked)
|
||||||
|
eol = sprintf('\n');
|
||||||
|
nebytes = numel(y);
|
||||||
|
nlines = ceil(nebytes / 76); % number of lines
|
||||||
|
neolbytes = length(eol); % number of bytes in eol string
|
||||||
|
|
||||||
|
% pad data so it becomes a multiple of 76 elements
|
||||||
|
y(nebytes + 1 : 76 * nlines) = 0;
|
||||||
|
y = reshape(y, 76, nlines);
|
||||||
|
|
||||||
|
% insert eol strings
|
||||||
|
y(end + 1 : end + neolbytes, :) = eol(:, ones(1, nlines));
|
||||||
|
|
||||||
|
% remove padding, but keep the last eol string
|
||||||
|
m = nebytes + neolbytes * (nlines - 1);
|
||||||
|
n = (76+neolbytes)*nlines - neolbytes;
|
||||||
|
y(m+1 : n) = [];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% reshape to a row vector and make it a character array
|
||||||
|
y = char(reshape(y, 1, numel(y)));
|
|
@ -0,0 +1,143 @@
|
||||||
|
function gen_object_display( obj_struct,indent )
|
||||||
|
%
|
||||||
|
% gen_object_display - general function to display an object's content
|
||||||
|
%
|
||||||
|
% format: gen_object_display( obj_struct,indent )
|
||||||
|
%
|
||||||
|
% input: obj_struct - a copy of the object stored inside a structure
|
||||||
|
% indent - amount of "indent" when printing to the screen
|
||||||
|
%
|
||||||
|
% output: to the screen
|
||||||
|
%
|
||||||
|
% example: gen_object_display( struct( my_object_handle) );
|
||||||
|
% gen_object_display( ny_structure );
|
||||||
|
%
|
||||||
|
% Correction History:
|
||||||
|
% 2006-11-01 - Jarek Tuszynski - added support for struct arrays
|
||||||
|
|
||||||
|
%% handle insufficient input
|
||||||
|
if ( nargin == 0 )
|
||||||
|
help gen_object_display;
|
||||||
|
return;
|
||||||
|
elseif (nargin == 1)
|
||||||
|
indent = 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
%% check input for errors
|
||||||
|
% if ~isstruct( obj_struct )
|
||||||
|
% fprintf( '\n\n\tMake sure that ''obj_struct'' is a struct type\n' );
|
||||||
|
% return
|
||||||
|
% end
|
||||||
|
|
||||||
|
% if (iscell( obj_struct ))
|
||||||
|
% for i =1:length(obj_struct)
|
||||||
|
% gen_object_display( obj_struct{i},indent + 2 );
|
||||||
|
% end
|
||||||
|
% return
|
||||||
|
% end
|
||||||
|
if ~isstruct( obj_struct )
|
||||||
|
space = sprintf( sprintf( '%%%ds',indent ),' ' );
|
||||||
|
fprintf( ' %s', space);
|
||||||
|
disp(obj_struct);
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
% find the longest name
|
||||||
|
field_list = fieldnames( obj_struct );
|
||||||
|
max_strlen = 0;
|
||||||
|
for idx = 1:length( field_list )
|
||||||
|
max_strlen = max( max_strlen,length(field_list{idx}) );
|
||||||
|
end
|
||||||
|
|
||||||
|
%% setup the display format (spacing)
|
||||||
|
space = sprintf( sprintf( '%%%ds',indent ),' ' );
|
||||||
|
name_format = sprintf( ' %s%%%ds: ', space, max_strlen );
|
||||||
|
name_format2= sprintf( ' %s%%%ds', space, max_strlen );
|
||||||
|
max_displen = 110 - max_strlen - indent;
|
||||||
|
|
||||||
|
%% display each field, if it is not too long
|
||||||
|
for iItem = 1:length( obj_struct ) % loop added by JT
|
||||||
|
for idx = 1:length( field_list )
|
||||||
|
|
||||||
|
% prepare field name to be displayed
|
||||||
|
name = sprintf( name_format,field_list{idx} );
|
||||||
|
%temp = getfield( obj_struct,field_list{idx} ); % original by OG
|
||||||
|
temp = obj_struct(iItem).(field_list{idx}); % modification by JT
|
||||||
|
|
||||||
|
% proceed according the variable's type
|
||||||
|
switch (1)
|
||||||
|
case islogical( temp ), % case added by JT
|
||||||
|
if isscalar(temp)
|
||||||
|
if (temp)
|
||||||
|
fprintf( '%strue\n',name );
|
||||||
|
else
|
||||||
|
fprintf( '%sfalse\n',name );
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fprintf( '%s[%dx%d logical]\n',name,size(temp,1),size(temp,2) );
|
||||||
|
end
|
||||||
|
case ischar( temp ),
|
||||||
|
if (length(temp)<max_displen )
|
||||||
|
fprintf( '%s''%s''\n',name,temp' );
|
||||||
|
else
|
||||||
|
fprintf( '%s[%dx%d char]\n',name,size(temp,1),size(temp,2) );
|
||||||
|
end
|
||||||
|
case isnumeric( temp ),
|
||||||
|
if (size( temp,1 )==1 )
|
||||||
|
temp_b = num2str( temp );
|
||||||
|
if (length(temp_b)<max_displen )
|
||||||
|
fprintf( '%s[%s]\n',name,temp_b );
|
||||||
|
else
|
||||||
|
fprintf( '%s[%dx%d double]\n',name,size(temp,1),size(temp,2) );
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fprintf( '%s[%dx%d double]\n',name,size(temp,1),size(temp,2) );
|
||||||
|
end
|
||||||
|
case iscell( temp ),
|
||||||
|
if (numel(temp)<10 && (isvector(temp) || isscalar(temp)))
|
||||||
|
fprintf( '%s[%dx%d cell] = \n',name,size(temp,1),size(temp,2) );
|
||||||
|
%disp(temp)
|
||||||
|
for r =1:numel(temp)
|
||||||
|
gen_object_display( temp{r},indent + max_strlen + 2 );
|
||||||
|
fprintf('\n');
|
||||||
|
end
|
||||||
|
elseif (numel(temp)<10)
|
||||||
|
fprintf( '%s[%dx%d cell] = \n',name,size(temp,1),size(temp,2) );
|
||||||
|
for r =1:size(temp,1)
|
||||||
|
gen_object_display( temp(r,:),indent + max_strlen + 2 );
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fprintf( '%s[%dx%d cell]\n',name,size(temp,1),size(temp,2) );
|
||||||
|
end
|
||||||
|
case isstruct( temp ),
|
||||||
|
fprintf( '%s[%dx%d struct]\n',name,size(temp,1),size(temp,2) );
|
||||||
|
if (indent<80)
|
||||||
|
if (numel(temp)<10 && (isvector(temp) || isscalar(temp)))
|
||||||
|
gen_object_display( temp,indent + max_strlen + 2 );
|
||||||
|
elseif (numel(temp)<10)
|
||||||
|
name2 = sprintf( name_format2,field_list{idx} );
|
||||||
|
for r =1:size(temp,1)
|
||||||
|
for c =1:size(temp,2)
|
||||||
|
fprintf( '%s(%d,%d) =\n',name2,r,c );
|
||||||
|
gen_object_display( temp(r,c),indent + max_strlen + 3 );
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
case isobject( temp ), fprintf( '%s[inherent object]\n',name );
|
||||||
|
if (indent<80)
|
||||||
|
cmd = sprintf( 'display( obj_struct.%s,%d );',field_list{idx},indent + max_strlen + 2 );
|
||||||
|
eval( cmd );
|
||||||
|
end
|
||||||
|
otherwise,
|
||||||
|
fprintf( '%s',name );
|
||||||
|
try
|
||||||
|
fprintf( temp );
|
||||||
|
catch %#ok<CTCH>
|
||||||
|
fprintf( '[No method to display type]' );
|
||||||
|
end
|
||||||
|
fprintf( '\n' );
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (length(obj_struct)>1), fprintf('\n'); end % added by JT
|
||||||
|
end % added by JT
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<MyTree>
|
||||||
|
<table border="1">
|
||||||
|
<tr>
|
||||||
|
<td>Apples</td>
|
||||||
|
<td>44%</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Bannanas</td>
|
||||||
|
<td>23%</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Oranges</td>
|
||||||
|
<td>13%</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Other</td>
|
||||||
|
<td>10%</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</MyTree>
|
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 156 KiB |
|
@ -0,0 +1,24 @@
|
||||||
|
Copyright (c) 2007, Jaroslaw Tuszynski
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the distribution
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<?xml-stylesheet type="text/css" href="foo.css"?>
|
||||||
|
<!-- This is a Global Comment -->
|
||||||
|
<aaa xmlns:xsi="http://www.foo.org">
|
||||||
|
<?ProcInst type="local processing instruction"?>
|
||||||
|
<!-- local comment 1 -->
|
||||||
|
bbb
|
||||||
|
<!-- local comment 2 -->
|
||||||
|
ccc
|
||||||
|
<matrix bad-name='fff'>
|
||||||
|
5e3+2*i, Inf
|
||||||
|
NaN, pi
|
||||||
|
</matrix>
|
||||||
|
<ee_e> ee_e </ee_e>
|
||||||
|
<ff-f> ff-f </ff-f>
|
||||||
|
<ggög> ggög </ggög>
|
||||||
|
<![CDATA[
|
||||||
|
Here <ddd>xml</ddd> tags are treated as ...
|
||||||
|
... text
|
||||||
|
]]>
|
||||||
|
</aaa>
|
||||||
|
|
|
@ -0,0 +1,550 @@
|
||||||
|
function [tree, RootName, DOMnode] = xml_read(xmlfile, Pref)
|
||||||
|
%XML_READ reads xml files and converts them into Matlab's struct tree.
|
||||||
|
%
|
||||||
|
% DESCRIPTION
|
||||||
|
% tree = xml_read(xmlfile) reads 'xmlfile' into data structure 'tree'
|
||||||
|
%
|
||||||
|
% tree = xml_read(xmlfile, Pref) reads 'xmlfile' into data structure 'tree'
|
||||||
|
% according to your preferences
|
||||||
|
%
|
||||||
|
% [tree, RootName, DOMnode] = xml_read(xmlfile) get additional information
|
||||||
|
% about XML file
|
||||||
|
%
|
||||||
|
% INPUT:
|
||||||
|
% xmlfile URL or filename of xml file to read
|
||||||
|
% Pref Preferences:
|
||||||
|
% Pref.ItemName - default 'item' - name of a special tag used to itemize
|
||||||
|
% cell arrays
|
||||||
|
% Pref.ReadAttr - default true - allow reading attributes
|
||||||
|
% Pref.ReadSpec - default true - allow reading special nodes
|
||||||
|
% Pref.Str2Num - default 'smart' - convert strings that look like numbers
|
||||||
|
% to numbers. Options: "always", "never", and "smart"
|
||||||
|
% Pref.KeepNS - default true - keep or strip namespace info
|
||||||
|
% Pref.NoCells - default true - force output to have no cell arrays
|
||||||
|
% Pref.Debug - default false - show mode specific error messages
|
||||||
|
% Pref.NumLevels- default infinity - how many recursive levels are
|
||||||
|
% allowed. Can be used to speed up the function by prunning the tree.
|
||||||
|
% Pref.RootOnly - default true - output variable 'tree' corresponds to
|
||||||
|
% xml file root element, otherwise it correspond to the whole file.
|
||||||
|
% Pref.CellItem - default 'true' - leave 'item' nodes in cell notation.
|
||||||
|
% OUTPUT:
|
||||||
|
% tree tree of structs and/or cell arrays corresponding to xml file
|
||||||
|
% RootName XML tag name used for root (top level) node.
|
||||||
|
% Optionally it can be a string cell array storing: Name of
|
||||||
|
% root node, document "Processing Instructions" data and
|
||||||
|
% document "comment" string
|
||||||
|
% DOMnode output of xmlread
|
||||||
|
%
|
||||||
|
% DETAILS:
|
||||||
|
% Function xml_read first calls MATLAB's xmlread function and than
|
||||||
|
% converts its output ('Document Object Model' tree of Java objects)
|
||||||
|
% to tree of MATLAB struct's. The output is in format of nested structs
|
||||||
|
% and cells. In the output data structure field names are based on
|
||||||
|
% XML tags, except in cases when tags produce illegal variable names.
|
||||||
|
%
|
||||||
|
% Several special xml node types result in special tags for fields of
|
||||||
|
% 'tree' nodes:
|
||||||
|
% - node.CONTENT - stores data section of the node if other fields are
|
||||||
|
% present. Usually data section is stored directly in 'node'.
|
||||||
|
% - node.ATTRIBUTE.name - stores node's attribute called 'name'.
|
||||||
|
% - node.COMMENT - stores node's comment section (string). For global
|
||||||
|
% comments see "RootName" output variable.
|
||||||
|
% - node.CDATA_SECTION - stores node's CDATA section (string).
|
||||||
|
% - node.PROCESSING_INSTRUCTIONS - stores "processing instruction" child
|
||||||
|
% node. For global "processing instructions" see "RootName" output variable.
|
||||||
|
% - other special node types like: document fragment nodes, document type
|
||||||
|
% nodes, entity nodes, notation nodes and processing instruction nodes
|
||||||
|
% will be treated like regular nodes
|
||||||
|
%
|
||||||
|
% EXAMPLES:
|
||||||
|
% MyTree=[];
|
||||||
|
% MyTree.MyNumber = 13;
|
||||||
|
% MyTree.MyString = 'Hello World';
|
||||||
|
% xml_write('test.xml', MyTree);
|
||||||
|
% [tree treeName] = xml_read ('test.xml');
|
||||||
|
% disp(treeName)
|
||||||
|
% gen_object_display()
|
||||||
|
% % See also xml_examples.m
|
||||||
|
%
|
||||||
|
% See also:
|
||||||
|
% xml_write, xmlread, xmlwrite
|
||||||
|
%
|
||||||
|
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||||||
|
% References:
|
||||||
|
% - Function inspired by Example 3 found in xmlread function.
|
||||||
|
% - Output data structures inspired by xml_toolbox structures.
|
||||||
|
|
||||||
|
%% default preferences
|
||||||
|
DPref.TableName = {'tr','td'}; % name of a special tags used to itemize 2D cell arrays
|
||||||
|
DPref.ItemName = 'item'; % name of a special tag used to itemize 1D cell arrays
|
||||||
|
DPref.CellItem = false; % leave 'item' nodes in cell notation
|
||||||
|
DPref.ReadAttr = true; % allow reading attributes
|
||||||
|
DPref.ReadSpec = true; % allow reading special nodes: comments, CData, etc.
|
||||||
|
DPref.KeepNS = true; % Keep or strip namespace info
|
||||||
|
DPref.Str2Num = 'smart';% convert strings that look like numbers to numbers
|
||||||
|
DPref.NoCells = true; % force output to have no cell arrays
|
||||||
|
DPref.NumLevels = 1e10; % number of recurence levels
|
||||||
|
DPref.PreserveSpace = false; % Preserve or delete spaces at the beggining and the end of stings?
|
||||||
|
RootOnly = true; % return root node with no top level special nodes
|
||||||
|
Debug = false; % show specific errors (true) or general (false)?
|
||||||
|
tree = [];
|
||||||
|
RootName = [];
|
||||||
|
|
||||||
|
%% Check Matlab Version
|
||||||
|
v = ver('MATLAB');
|
||||||
|
version = str2double(regexp(v.Version, '\d.\d','match','once'));
|
||||||
|
if (version<7.1)
|
||||||
|
error('Your MATLAB version is too old. You need version 7.1 or newer.');
|
||||||
|
end
|
||||||
|
|
||||||
|
%% read user preferences
|
||||||
|
if (nargin>1)
|
||||||
|
if (isfield(Pref, 'TableName')), DPref.TableName = Pref.TableName; end
|
||||||
|
if (isfield(Pref, 'ItemName' )), DPref.ItemName = Pref.ItemName; end
|
||||||
|
if (isfield(Pref, 'CellItem' )), DPref.CellItem = Pref.CellItem; end
|
||||||
|
if (isfield(Pref, 'Str2Num' )), DPref.Str2Num = Pref.Str2Num ; end
|
||||||
|
if (isfield(Pref, 'NoCells' )), DPref.NoCells = Pref.NoCells ; end
|
||||||
|
if (isfield(Pref, 'NumLevels')), DPref.NumLevels = Pref.NumLevels; end
|
||||||
|
if (isfield(Pref, 'ReadAttr' )), DPref.ReadAttr = Pref.ReadAttr; end
|
||||||
|
if (isfield(Pref, 'ReadSpec' )), DPref.ReadSpec = Pref.ReadSpec; end
|
||||||
|
if (isfield(Pref, 'KeepNS' )), DPref.KeepNS = Pref.KeepNS; end
|
||||||
|
if (isfield(Pref, 'RootOnly' )), RootOnly = Pref.RootOnly; end
|
||||||
|
if (isfield(Pref, 'Debug' )), Debug = Pref.Debug ; end
|
||||||
|
if (isfield(Pref, 'PreserveSpace')), DPref.PreserveSpace = Pref.PreserveSpace; end
|
||||||
|
end
|
||||||
|
if ischar(DPref.Str2Num), % convert from character description to numbers
|
||||||
|
DPref.Str2Num = find(strcmpi(DPref.Str2Num, {'never', 'smart', 'always'}))-1;
|
||||||
|
if isempty(DPref.Str2Num), DPref.Str2Num=1; end % 1-smart by default
|
||||||
|
end
|
||||||
|
|
||||||
|
%% read xml file using Matlab function
|
||||||
|
if isa(xmlfile, 'org.apache.xerces.dom.DeferredDocumentImpl');
|
||||||
|
% if xmlfile is a DOMnode than skip the call to xmlread
|
||||||
|
try
|
||||||
|
try
|
||||||
|
DOMnode = xmlfile;
|
||||||
|
catch ME
|
||||||
|
error('Invalid DOM node: \n%s.', getReport(ME));
|
||||||
|
end
|
||||||
|
catch %#ok<CTCH> catch for mablab versions prior to 7.5
|
||||||
|
error('Invalid DOM node. \n');
|
||||||
|
end
|
||||||
|
else % we assume xmlfile is a filename
|
||||||
|
if (Debug) % in debuging mode crashes are allowed
|
||||||
|
DOMnode = xmlread(xmlfile);
|
||||||
|
else % in normal mode crashes are not allowed
|
||||||
|
try
|
||||||
|
try
|
||||||
|
DOMnode = xmlread(xmlfile);
|
||||||
|
catch ME
|
||||||
|
error('Failed to read XML file %s: \n%s',xmlfile, getReport(ME));
|
||||||
|
end
|
||||||
|
catch %#ok<CTCH> catch for mablab versions prior to 7.5
|
||||||
|
error('Failed to read XML file %s\n',xmlfile);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Node = DOMnode.getFirstChild;
|
||||||
|
|
||||||
|
%% Find the Root node. Also store data from Global Comment and Processing
|
||||||
|
% Instruction nodes, if any.
|
||||||
|
GlobalTextNodes = cell(1,3);
|
||||||
|
GlobalProcInst = [];
|
||||||
|
GlobalComment = [];
|
||||||
|
GlobalDocType = [];
|
||||||
|
while (~isempty(Node))
|
||||||
|
if (Node.getNodeType==Node.ELEMENT_NODE)
|
||||||
|
RootNode=Node;
|
||||||
|
elseif (Node.getNodeType==Node.PROCESSING_INSTRUCTION_NODE)
|
||||||
|
data = strtrim(char(Node.getData));
|
||||||
|
target = strtrim(char(Node.getTarget));
|
||||||
|
GlobalProcInst = [target, ' ', data];
|
||||||
|
GlobalTextNodes{2} = GlobalProcInst;
|
||||||
|
elseif (Node.getNodeType==Node.COMMENT_NODE)
|
||||||
|
GlobalComment = strtrim(char(Node.getData));
|
||||||
|
GlobalTextNodes{3} = GlobalComment;
|
||||||
|
% elseif (Node.getNodeType==Node.DOCUMENT_TYPE_NODE)
|
||||||
|
% GlobalTextNodes{4} = GlobalDocType;
|
||||||
|
end
|
||||||
|
Node = Node.getNextSibling;
|
||||||
|
end
|
||||||
|
|
||||||
|
%% parse xml file through calls to recursive DOMnode2struct function
|
||||||
|
if (Debug) % in debuging mode crashes are allowed
|
||||||
|
[tree RootName] = DOMnode2struct(RootNode, DPref, 1);
|
||||||
|
else % in normal mode crashes are not allowed
|
||||||
|
try
|
||||||
|
try
|
||||||
|
[tree RootName] = DOMnode2struct(RootNode, DPref, 1);
|
||||||
|
catch ME
|
||||||
|
error('Unable to parse XML file %s: \n %s.',xmlfile, getReport(ME));
|
||||||
|
end
|
||||||
|
catch %#ok<CTCH> catch for mablab versions prior to 7.5
|
||||||
|
error('Unable to parse XML file %s.',xmlfile);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% If there were any Global Text nodes than return them
|
||||||
|
if (~RootOnly)
|
||||||
|
if (~isempty(GlobalProcInst) && DPref.ReadSpec)
|
||||||
|
t.PROCESSING_INSTRUCTION = GlobalProcInst;
|
||||||
|
end
|
||||||
|
if (~isempty(GlobalComment) && DPref.ReadSpec)
|
||||||
|
t.COMMENT = GlobalComment;
|
||||||
|
end
|
||||||
|
if (~isempty(GlobalDocType) && DPref.ReadSpec)
|
||||||
|
t.DOCUMENT_TYPE = GlobalDocType;
|
||||||
|
end
|
||||||
|
t.(RootName) = tree;
|
||||||
|
tree=t;
|
||||||
|
end
|
||||||
|
if (~isempty(GlobalTextNodes))
|
||||||
|
GlobalTextNodes{1} = RootName;
|
||||||
|
RootName = GlobalTextNodes;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === DOMnode2struct Function ===========================================
|
||||||
|
% =======================================================================
|
||||||
|
function [s TagName LeafNode] = DOMnode2struct(node, Pref, level)
|
||||||
|
|
||||||
|
%% === Step 1: Get node name and check if it is a leaf node ==============
|
||||||
|
[TagName LeafNode] = NodeName(node, Pref.KeepNS);
|
||||||
|
s = []; % initialize output structure
|
||||||
|
|
||||||
|
%% === Step 2: Process Leaf Nodes (nodes with no children) ===============
|
||||||
|
if (LeafNode)
|
||||||
|
if (LeafNode>1 && ~Pref.ReadSpec), LeafNode=-1; end % tags only so ignore special nodes
|
||||||
|
if (LeafNode>0) % supported leaf node types
|
||||||
|
try
|
||||||
|
try % use try-catch: errors here are often due to VERY large fields (like images) that overflow java memory
|
||||||
|
s = char(node.getData);
|
||||||
|
if (isempty(s)), s = ' '; end % make it a string
|
||||||
|
% for some reason current xmlread 'creates' a lot of empty text
|
||||||
|
% fields with first chatacter=10 - those will be deleted.
|
||||||
|
if (~Pref.PreserveSpace || s(1)==10)
|
||||||
|
if (isspace(s(1)) || isspace(s(end))), s = strtrim(s); end % trim speces is any
|
||||||
|
end
|
||||||
|
if (LeafNode==1), s=str2var(s, Pref.Str2Num, 0); end % convert to number(s) if needed
|
||||||
|
catch ME % catch for mablab versions 7.5 and higher
|
||||||
|
warning('xml_io_tools:read:LeafRead', ...
|
||||||
|
'This leaf node could not be read and was ignored. ');
|
||||||
|
getReport(ME)
|
||||||
|
end
|
||||||
|
catch %#ok<CTCH> catch for mablab versions prior to 7.5
|
||||||
|
warning('xml_io_tools:read:LeafRead', ...
|
||||||
|
'This leaf node could not be read and was ignored. ');
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (LeafNode==3) % ProcessingInstructions need special treatment
|
||||||
|
target = strtrim(char(node.getTarget));
|
||||||
|
s = [target, ' ', s];
|
||||||
|
end
|
||||||
|
return % We are done the rest of the function deals with nodes with children
|
||||||
|
end
|
||||||
|
if (level>Pref.NumLevels+1), return; end % if Pref.NumLevels is reached than we are done
|
||||||
|
|
||||||
|
%% === Step 3: Process nodes with children ===============================
|
||||||
|
if (node.hasChildNodes) % children present
|
||||||
|
Child = node.getChildNodes; % create array of children nodes
|
||||||
|
nChild = Child.getLength; % number of children
|
||||||
|
|
||||||
|
% --- pass 1: how many children with each name -----------------------
|
||||||
|
f = [];
|
||||||
|
for iChild = 1:nChild % read in each child
|
||||||
|
[cname cLeaf] = NodeName(Child.item(iChild-1), Pref.KeepNS);
|
||||||
|
if (cLeaf<0), continue; end % unsupported leaf node types
|
||||||
|
if (~isfield(f,cname)),
|
||||||
|
f.(cname)=0; % initialize first time I see this name
|
||||||
|
end
|
||||||
|
f.(cname) = f.(cname)+1; % add to the counter
|
||||||
|
end % end for iChild
|
||||||
|
% text_nodes become CONTENT & for some reason current xmlread 'creates' a
|
||||||
|
% lot of empty text fields so f.CONTENT value should not be trusted
|
||||||
|
if (isfield(f,'CONTENT') && f.CONTENT>2), f.CONTENT=2; end
|
||||||
|
|
||||||
|
% --- pass 2: store all the children as struct of cell arrays ----------
|
||||||
|
for iChild = 1:nChild % read in each child
|
||||||
|
[c cname cLeaf] = DOMnode2struct(Child.item(iChild-1), Pref, level+1);
|
||||||
|
if (cLeaf && isempty(c)) % if empty leaf node than skip
|
||||||
|
continue; % usually empty text node or one of unhandled node types
|
||||||
|
elseif (nChild==1 && cLeaf==1)
|
||||||
|
s=c; % shortcut for a common case
|
||||||
|
else % if normal node
|
||||||
|
if (level>Pref.NumLevels), continue; end
|
||||||
|
n = f.(cname); % how many of them in the array so far?
|
||||||
|
if (~isfield(s,cname)) % encountered this name for the first time
|
||||||
|
if (n==1) % if there will be only one of them ...
|
||||||
|
s.(cname) = c; % than save it in format it came in
|
||||||
|
else % if there will be many of them ...
|
||||||
|
s.(cname) = cell(1,n);
|
||||||
|
s.(cname){1} = c; % than save as cell array
|
||||||
|
end
|
||||||
|
f.(cname) = 1; % initialize the counter
|
||||||
|
else % already have seen this name
|
||||||
|
s.(cname){n+1} = c; % add to the array
|
||||||
|
f.(cname) = n+1; % add to the array counter
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end % for iChild
|
||||||
|
end % end if (node.hasChildNodes)
|
||||||
|
|
||||||
|
%% === Step 4: Post-process struct's created for nodes with children =====
|
||||||
|
if (isstruct(s))
|
||||||
|
fields = fieldnames(s);
|
||||||
|
nField = length(fields);
|
||||||
|
|
||||||
|
% Detect structure that looks like Html table and store it in cell Matrix
|
||||||
|
if (nField==1 && strcmpi(fields{1},Pref.TableName{1}))
|
||||||
|
tr = s.(Pref.TableName{1});
|
||||||
|
fields2 = fieldnames(tr{1});
|
||||||
|
if (length(fields2)==1 && strcmpi(fields2{1},Pref.TableName{2}))
|
||||||
|
% This seems to be a special structure such that for
|
||||||
|
% Pref.TableName = {'tr','td'} 's' corresponds to
|
||||||
|
% <tr> <td>M11</td> <td>M12</td> </tr>
|
||||||
|
% <tr> <td>M12</td> <td>M22</td> </tr>
|
||||||
|
% Recognize it as encoding for 2D struct
|
||||||
|
nr = length(tr);
|
||||||
|
for r = 1:nr
|
||||||
|
row = tr{r}.(Pref.TableName{2});
|
||||||
|
Table(r,1:length(row)) = row; %#ok<AGROW>
|
||||||
|
end
|
||||||
|
s = Table;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% --- Post-processing: convert 'struct of cell-arrays' to 'array of structs'
|
||||||
|
% Example: let say s has 3 fields s.a, s.b & s.c and each field is an
|
||||||
|
% cell-array with more than one cell-element and all 3 have the same length.
|
||||||
|
% Then change it to array of structs, each with single cell.
|
||||||
|
% This way element s.a{1} will be now accessed through s(1).a
|
||||||
|
vec = zeros(size(fields));
|
||||||
|
for i=1:nField, vec(i) = f.(fields{i}); end
|
||||||
|
if (numel(vec)>1 && vec(1)>1 && var(vec)==0) % convert from struct of
|
||||||
|
s = cell2struct(struct2cell(s), fields, 1); % arrays to array of struct
|
||||||
|
end % if anyone knows better way to do above conversion please let me know.
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
%% === Step 5: Process nodes with attributes =============================
|
||||||
|
if (node.hasAttributes && Pref.ReadAttr)
|
||||||
|
if (~isstruct(s)), % make into struct if is not already
|
||||||
|
ss.CONTENT=s;
|
||||||
|
s=ss;
|
||||||
|
end
|
||||||
|
Attr = node.getAttributes; % list of all attributes
|
||||||
|
for iAttr = 1:Attr.getLength % for each attribute
|
||||||
|
name = char(Attr.item(iAttr-1).getName); % attribute name
|
||||||
|
name = str2varName(name, Pref.KeepNS); % fix name if needed
|
||||||
|
value = char(Attr.item(iAttr-1).getValue); % attribute value
|
||||||
|
value = str2var(value, Pref.Str2Num, 1); % convert to number if possible
|
||||||
|
s.ATTRIBUTE.(name) = value; % save again
|
||||||
|
end % end iAttr loop
|
||||||
|
end % done with attributes
|
||||||
|
if (~isstruct(s)), return; end %The rest of the code deals with struct's
|
||||||
|
|
||||||
|
%% === Post-processing: fields of "s"
|
||||||
|
% convert 'cell-array of structs' to 'arrays of structs'
|
||||||
|
fields = fieldnames(s); % get field names
|
||||||
|
nField = length(fields);
|
||||||
|
for iItem=1:length(s) % for each struct in the array - usually one
|
||||||
|
for iField=1:length(fields)
|
||||||
|
field = fields{iField}; % get field name
|
||||||
|
% if this is an 'item' field and user want to leave those as cells
|
||||||
|
% than skip this one
|
||||||
|
if (strcmpi(field, Pref.ItemName) && Pref.CellItem), continue; end
|
||||||
|
x = s(iItem).(field);
|
||||||
|
if (iscell(x) && all(cellfun(@isstruct,x(:))) && numel(x)>1) % it's cell-array of structs
|
||||||
|
% numel(x)>1 check is to keep 1 cell-arrays created when Pref.CellItem=1
|
||||||
|
try % this operation fails sometimes
|
||||||
|
% example: change s(1).a{1}.b='jack'; s(1).a{2}.b='john'; to
|
||||||
|
% more convinient s(1).a(1).b='jack'; s(1).a(2).b='john';
|
||||||
|
s(iItem).(field) = [x{:}]'; %#ok<AGROW> % converted to arrays of structs
|
||||||
|
catch %#ok<CTCH>
|
||||||
|
% above operation will fail if s(1).a{1} and s(1).a{2} have
|
||||||
|
% different fields. If desired, function forceCell2Struct can force
|
||||||
|
% them to the same field structure by adding empty fields.
|
||||||
|
if (Pref.NoCells)
|
||||||
|
s(iItem).(field) = forceCell2Struct(x); %#ok<AGROW>
|
||||||
|
end
|
||||||
|
end % end catch
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% === Step 4: Post-process struct's created for nodes with children =====
|
||||||
|
|
||||||
|
% --- Post-processing: remove special 'item' tags ---------------------
|
||||||
|
% many xml writes (including xml_write) use a special keyword to mark
|
||||||
|
% arrays of nodes (see xml_write for examples). The code below converts
|
||||||
|
% s.item to s.CONTENT
|
||||||
|
ItemContent = false;
|
||||||
|
if (isfield(s,Pref.ItemName))
|
||||||
|
s.CONTENT = s.(Pref.ItemName);
|
||||||
|
s = rmfield(s,Pref.ItemName);
|
||||||
|
ItemContent = Pref.CellItem; % if CellItem than keep s.CONTENT as cells
|
||||||
|
end
|
||||||
|
|
||||||
|
% --- Post-processing: clean up CONTENT tags ---------------------
|
||||||
|
% if s.CONTENT is a cell-array with empty elements at the end than trim
|
||||||
|
% the length of this cell-array. Also if s.CONTENT is the only field than
|
||||||
|
% remove .CONTENT part and store it as s.
|
||||||
|
if (isfield(s,'CONTENT'))
|
||||||
|
if (iscell(s.CONTENT) && isvector(s.CONTENT))
|
||||||
|
x = s.CONTENT;
|
||||||
|
for i=numel(x):-1:1, if ~isempty(x{i}), break; end; end
|
||||||
|
if (i==1 && ~ItemContent)
|
||||||
|
s.CONTENT = x{1}; % delete cell structure
|
||||||
|
else
|
||||||
|
s.CONTENT = x(1:i); % delete empty cells
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (nField==1)
|
||||||
|
if (ItemContent)
|
||||||
|
ss = s.CONTENT; % only child: remove a level but ensure output is a cell-array
|
||||||
|
s=[]; s{1}=ss;
|
||||||
|
else
|
||||||
|
s = s.CONTENT; % only child: remove a level
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === forceCell2Struct Function =========================================
|
||||||
|
% =======================================================================
|
||||||
|
function s = forceCell2Struct(x)
|
||||||
|
% Convert cell-array of structs, where not all of structs have the same
|
||||||
|
% fields, to a single array of structs
|
||||||
|
|
||||||
|
%% Convert 1D cell array of structs to 2D cell array, where each row
|
||||||
|
% represents item in original array and each column corresponds to a unique
|
||||||
|
% field name. Array "AllFields" store fieldnames for each column
|
||||||
|
AllFields = fieldnames(x{1}); % get field names of the first struct
|
||||||
|
CellMat = cell(length(x), length(AllFields));
|
||||||
|
for iItem=1:length(x)
|
||||||
|
fields = fieldnames(x{iItem}); % get field names of the next struct
|
||||||
|
for iField=1:length(fields) % inspect all fieldnames and find those
|
||||||
|
field = fields{iField}; % get field name
|
||||||
|
col = find(strcmp(field,AllFields),1);
|
||||||
|
if isempty(col) % no column for such fieldname yet
|
||||||
|
AllFields = [AllFields; field]; %#ok<AGROW>
|
||||||
|
col = length(AllFields); % create a new column for it
|
||||||
|
end
|
||||||
|
CellMat{iItem,col} = x{iItem}.(field); % store rearanged data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
%% Convert 2D cell array to array of structs
|
||||||
|
s = cell2struct(CellMat, AllFields, 2);
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === str2var Function ==================================================
|
||||||
|
% =======================================================================
|
||||||
|
function val=str2var(str, option, attribute)
|
||||||
|
% Can this string 'str' be converted to a number? if so than do it.
|
||||||
|
val = str;
|
||||||
|
len = numel(str);
|
||||||
|
if (len==0 || option==0), return; end % Str2Num="never" of empty string -> do not do enything
|
||||||
|
if (len>10000 && option==1), return; end % Str2Num="smart" and string is very long -> probably base64 encoded binary
|
||||||
|
digits = '(Inf)|(NaN)|(pi)|[\t\n\d\+\-\*\.ei EI\[\]\;\,]';
|
||||||
|
s = regexprep(str, digits, ''); % remove all the digits and other allowed characters
|
||||||
|
if (~all(~isempty(s))) % if nothing left than this is probably a number
|
||||||
|
if (~isempty(strfind(str, ' '))), option=2; end %if str has white-spaces assume by default that it is not a date string
|
||||||
|
if (~isempty(strfind(str, '['))), option=2; end % same with brackets
|
||||||
|
str(strfind(str, '\n')) = ';';% parse data tables into 2D arrays, if any
|
||||||
|
if (option==1) % the 'smart' option
|
||||||
|
try % try to convert to a date, like 2007-12-05
|
||||||
|
datenum(str); % if successful than leave it as string
|
||||||
|
catch %#ok<CTCH> % if this is not a date than ...
|
||||||
|
option=2; % ... try converting to a number
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (option==2)
|
||||||
|
if (attribute)
|
||||||
|
num = str2double(str); % try converting to a single number using sscanf function
|
||||||
|
if isnan(num), return; end % So, it wasn't really a number after all
|
||||||
|
else
|
||||||
|
num = str2num(str); %#ok<ST2NM> % try converting to a single number or array using eval function
|
||||||
|
end
|
||||||
|
if(isnumeric(num) && numel(num)>0), val=num; end % if convertion to a single was succesful than save
|
||||||
|
end
|
||||||
|
elseif ((str(1)=='[' && str(end)==']') || (str(1)=='{' && str(end)=='}')) % this looks like a (cell) array encoded as a string
|
||||||
|
try
|
||||||
|
val = eval(str);
|
||||||
|
catch %#ok<CTCH>
|
||||||
|
val = str;
|
||||||
|
end
|
||||||
|
elseif (~attribute) % see if it is a boolean array with no [] brackets
|
||||||
|
str1 = lower(str);
|
||||||
|
str1 = strrep(str1, 'false', '0');
|
||||||
|
str1 = strrep(str1, 'true' , '1');
|
||||||
|
s = regexprep(str1, '[01 \;\,]', ''); % remove all 0/1, spaces, commas and semicolons
|
||||||
|
if (~all(~isempty(s))) % if nothing left than this is probably a boolean array
|
||||||
|
num = str2num(str1); %#ok<ST2NM>
|
||||||
|
if(isnumeric(num) && numel(num)>0), val = (num>0); end % if convertion was succesful than save as logical
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === str2varName Function ==============================================
|
||||||
|
% =======================================================================
|
||||||
|
function str = str2varName(str, KeepNS)
|
||||||
|
% convert a sting to a valid matlab variable name
|
||||||
|
if(KeepNS)
|
||||||
|
str = regexprep(str,':','_COLON_', 'once', 'ignorecase');
|
||||||
|
else
|
||||||
|
k = strfind(str,':');
|
||||||
|
if (~isempty(k))
|
||||||
|
str = str(k+1:end);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
str = regexprep(str,'-','_DASH_' ,'once', 'ignorecase');
|
||||||
|
if (~isvarname(str)) && (~iskeyword(str))
|
||||||
|
str = genvarname(str);
|
||||||
|
end
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === NodeName Function =================================================
|
||||||
|
% =======================================================================
|
||||||
|
function [Name LeafNode] = NodeName(node, KeepNS)
|
||||||
|
% get node name and make sure it is a valid variable name in Matlab.
|
||||||
|
% also get node type:
|
||||||
|
% LeafNode=0 - normal element node,
|
||||||
|
% LeafNode=1 - text node
|
||||||
|
% LeafNode=2 - supported non-text leaf node,
|
||||||
|
% LeafNode=3 - supported processing instructions leaf node,
|
||||||
|
% LeafNode=-1 - unsupported non-text leaf node
|
||||||
|
switch (node.getNodeType)
|
||||||
|
case node.ELEMENT_NODE
|
||||||
|
Name = char(node.getNodeName);% capture name of the node
|
||||||
|
Name = str2varName(Name, KeepNS); % if Name is not a good variable name - fix it
|
||||||
|
LeafNode = 0;
|
||||||
|
case node.TEXT_NODE
|
||||||
|
Name = 'CONTENT';
|
||||||
|
LeafNode = 1;
|
||||||
|
case node.COMMENT_NODE
|
||||||
|
Name = 'COMMENT';
|
||||||
|
LeafNode = 2;
|
||||||
|
case node.CDATA_SECTION_NODE
|
||||||
|
Name = 'CDATA_SECTION';
|
||||||
|
LeafNode = 2;
|
||||||
|
case node.DOCUMENT_TYPE_NODE
|
||||||
|
Name = 'DOCUMENT_TYPE';
|
||||||
|
LeafNode = 2;
|
||||||
|
case node.PROCESSING_INSTRUCTION_NODE
|
||||||
|
Name = 'PROCESSING_INSTRUCTION';
|
||||||
|
LeafNode = 3;
|
||||||
|
otherwise
|
||||||
|
NodeType = {'ELEMENT','ATTRIBUTE','TEXT','CDATA_SECTION', ...
|
||||||
|
'ENTITY_REFERENCE', 'ENTITY', 'PROCESSING_INSTRUCTION', 'COMMENT',...
|
||||||
|
'DOCUMENT', 'DOCUMENT_TYPE', 'DOCUMENT_FRAGMENT', 'NOTATION'};
|
||||||
|
Name = char(node.getNodeName);% capture name of the node
|
||||||
|
warning('xml_io_tools:read:unkNode', ...
|
||||||
|
'Unknown node type encountered: %s_NODE (%s)', NodeType{node.getNodeType}, Name);
|
||||||
|
LeafNode = -1;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,914 @@
|
||||||
|
%% Tutorial for xml_io_tools Package
|
||||||
|
% *By Jarek Tuszynski*
|
||||||
|
%
|
||||||
|
% Package xml_io_tools can read XML files into MATLAB struct and writes
|
||||||
|
% MATLAB data types to XML files with help of simple interface to
|
||||||
|
% MATLAB's xmlwrite and xmlread functions.
|
||||||
|
%
|
||||||
|
% Two function to simplify reading and writing XML files from MATLAB:
|
||||||
|
%
|
||||||
|
% * Function xml_read first calls MATLAB's xmlread function and than
|
||||||
|
% converts its output ('Document Object Model' tree of Java objects)
|
||||||
|
% to tree of MATLAB struct's. The output is in the format of nested
|
||||||
|
% structs and cells. In the output data structure field names are based on
|
||||||
|
% XML tags.
|
||||||
|
%
|
||||||
|
% * Function xml_write first convert input tree of MATLAB structs and cells
|
||||||
|
% and other types to tree of 'Document Object Model' nodes, and then writes
|
||||||
|
% resulting object to XML file using MATLAB's xmlwrite function. .
|
||||||
|
%
|
||||||
|
%% This package can:
|
||||||
|
% * Read most XML files, created inside and outside of MATLAB environment,
|
||||||
|
% and convert them to MATLAB data structures.
|
||||||
|
% * Write any MATLAB's struct tree to XML file
|
||||||
|
% * Handle XML attributes and special XML nodes like comments, processing
|
||||||
|
% instructions and CDATA sections
|
||||||
|
% * Supports base64 encoding and decoding to allow handling embeded binary
|
||||||
|
% data
|
||||||
|
% * Be studied, modified, customized, rewritten and used in other packages
|
||||||
|
% without any limitations. All code is included and documented. Software
|
||||||
|
% is distributed under BSD Licence (included).
|
||||||
|
%
|
||||||
|
%% This package does not:
|
||||||
|
% * Guarantee to recover the same Matlab objects that were saved. If you
|
||||||
|
% need to be able to recover carbon copy of the structure that was saved
|
||||||
|
% than you will have to use one of the packages that uses special set of
|
||||||
|
% tags saved as xml attributes that help to guide the parsing of XML code.
|
||||||
|
% This package does not use those tags.
|
||||||
|
% * Guarantee to work with older versions of MATLAB. Functions do not work
|
||||||
|
% with versions of MATLAB prior to 7.1 (26-Jul-2005).
|
||||||
|
%
|
||||||
|
%% Change History
|
||||||
|
% * 2006-11-06 - original version
|
||||||
|
% * 2006-11-26 - corrected xml_write to handle writing Matlab's column
|
||||||
|
% arrays to xml files. Bug discovered and diagnosed by Kalyan Dutta.
|
||||||
|
% * 2006-11-28 - made changes to handle special node types like:
|
||||||
|
% COMMENTS and CDATA sections
|
||||||
|
% * 2007-03-12 - Writing CDATA sections still did not worked. The problem
|
||||||
|
% was diagnosed and fixed by Alberto Amaro. The fix involved rewriting
|
||||||
|
% xmlwrite to use Apache Xerces java files directly instead of MATLAB's
|
||||||
|
% XMLUtils java class.
|
||||||
|
% * 2007-06-21 - Fixed problem reported by Anna Kelbert in Reviews about
|
||||||
|
% not writing attributes of ROOT node. Also: added support for Processing
|
||||||
|
% Instructions, added support for global text nodes: Processing
|
||||||
|
% Instructions and comments, allowed writing tag names with special
|
||||||
|
% characters
|
||||||
|
% * 2007-07-20 - Added tutorial script file. Extended support for global
|
||||||
|
% text nodes. Added more Preference fields.
|
||||||
|
% * 2008-01-23 - Fixed problem reported by Anna Krewet of converting dates
|
||||||
|
% in format '2007-01-01' to numbers. Improved and added warning messages.
|
||||||
|
% Added detection of old Matlab versions incompatible with the library.
|
||||||
|
% Expanded documentation.
|
||||||
|
% * 2008-06-23 - Fixed problem with writing 1D array reported by Mark Neil.
|
||||||
|
% Extended xml_read's Pref.Num2Str to 3 settings (never, smart and always)
|
||||||
|
% for better control. Added parameter Pref.KeepNS for keeping or ignoring
|
||||||
|
% namespace data when reading. Fixed a bug related to writing 2D cell
|
||||||
|
% arrays brought up by Andrej's Mosat review.
|
||||||
|
% * 2008-09-11 - Resubmitting last upload - zip file is still old
|
||||||
|
% * 2009-02-26 - Small changes. More error handling. More robust in case of
|
||||||
|
% large binary objects. Added support for Base64 encoding/decoding of
|
||||||
|
% binary objects (using functions by Peter J. Acklam).
|
||||||
|
% * 2009-06-26 - changes to xml_read: added CellItem parameter to allow
|
||||||
|
% better control of reading files with 'item' notation (see comment by
|
||||||
|
% Shlomi); changed try-catch statements so xml_read would work for mablab
|
||||||
|
% versions prior to 7.5 (see Thomas Pilutti comment)
|
||||||
|
% * 2009-12-03 - added PreserveSpace parameter for contolling empty string
|
||||||
|
% handling as suggested by Sebastiaan. Fix suggested by Michael Murphy.
|
||||||
|
% Fixed number recognition code as suggested by Yuan Ren.
|
||||||
|
% * 2010-05-04 - implemented fixes suggested by Dylan Reynolds from Airbus.
|
||||||
|
% * 2010-07-28 - implemented support for 2D arrays of cells and structs
|
||||||
|
% suggested by Rodney Behn from MIT Lincoln Laboratory. Also attempted
|
||||||
|
% large scale cleanup of xml_write function
|
||||||
|
% * 2010-08-18 - minor extension to allow better handling of logical
|
||||||
|
% scalars and arrays and function handles suggested by Andreas Richter
|
||||||
|
% and others
|
||||||
|
% * 2010-09-20 - allow reading and writing of sparse matrices. Improve
|
||||||
|
% reading of 1D boolean arrays.
|
||||||
|
% * 2010-11-05 - Fix problem with empty cells reported by Richard Cotton;
|
||||||
|
% fixed issues with reading boolean arrays reported by Zohar Bar-Yehuda;
|
||||||
|
% Improved speed of base64 coding and decoding by switching to java based
|
||||||
|
% code.
|
||||||
|
%% Licence
|
||||||
|
% The package is distributed under BSD License
|
||||||
|
format compact; % viewing preference
|
||||||
|
clear variables;
|
||||||
|
type('license.txt')
|
||||||
|
|
||||||
|
%% Write XML file based on a Struct using "xml_write"
|
||||||
|
% Any MATLAB data struct can be saved to XML file.
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString = 'Hello World';
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Read XML file producing a Struct using "xml_read"
|
||||||
|
[tree treeName] = xml_read ('test.xml');
|
||||||
|
disp([treeName{1} ' ='])
|
||||||
|
gen_object_display(tree)
|
||||||
|
|
||||||
|
%% "Pref.XmlEngine" flag in "xml_write"
|
||||||
|
% Occasionaly some operations are performed better by Apache Xerces XML
|
||||||
|
% engine than default xmlread function. That is why xml_write provide an
|
||||||
|
% option for choosing the underlaying xml engine. Code below performs the
|
||||||
|
% same operation as the previous section but using Apache Xerces XML engine.
|
||||||
|
% Notice that in this case name of root element
|
||||||
|
% was passed as variable and not extracted from the variable name.
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
xml_write('test.xml', MyTree, 'TreeOfMine', Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Writing Struct with different type MATLAB arrays
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.Empty = []; % Empty variable
|
||||||
|
MyTree.Num_1x1 = 13; % simple scalar
|
||||||
|
MyTree.Vec_1x3 = [1 2 3]; % horizontal vector
|
||||||
|
MyTree.Vec_4x1 = [1; 2; 3; 4]; % vertical vector
|
||||||
|
MyTree.Mat_2x2 = [1, 2; 3, 4]; % 2D matrix
|
||||||
|
MyTree.Cube_3D = reshape(1:8,[2 2 2]); % 3D array
|
||||||
|
MyTree.String1 = '[2003 10 30]'; % number string with [] brackets
|
||||||
|
MyTree.String2 = ' 2003 10 30 '; % number string without [] brackets
|
||||||
|
MyTree.Logical_1x1 = false; % single logical
|
||||||
|
MyTree.Logical_2x2 = [false, true; true, false]; % 2D matrix of logicals
|
||||||
|
MyTree.Logical_Str = 'False False True True';
|
||||||
|
MyTree.Int_2x2 = uint8([1 2;3 4]); % 2D matrix of uint8 integers
|
||||||
|
MyTree.Complex_1x1 = complex(1, 7); % complex scalar
|
||||||
|
MyTree.Complex_2x2 = complex([1 2;3 4],[2 2;7 7]); % 2D matrix of complex numbers
|
||||||
|
MyTree.Sparse_9x9 = sparse(1:9,1:9,1); % sparse 9x9 matrix
|
||||||
|
MyTree.Function = @sum; % function handle
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Read Struct with MATLAB arrays
|
||||||
|
% Notice that 'Cube_3D' did not preserve original dimentions
|
||||||
|
[tree treeName] = xml_read ('test.xml');
|
||||||
|
disp([treeName{1} ' ='])
|
||||||
|
gen_object_display(tree)
|
||||||
|
|
||||||
|
%% "Pref.StructItem" flag in "xml_write" (controls 1D arrays of structs)
|
||||||
|
% *Create a simple structure with 1D array of struct's*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.a(1).b = 'jack';
|
||||||
|
MyTree.a(2).b = 'john';
|
||||||
|
gen_object_display(MyTree)
|
||||||
|
%%
|
||||||
|
% *Write XML with "StructItem = true" (default). Notice single 'a'
|
||||||
|
% section and multiple 'item' sub-sections. Those subsections are used
|
||||||
|
% to store array elements*
|
||||||
|
wPref.StructItem = true;
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n')
|
||||||
|
gen_object_display(xml_read ('test.xml'))
|
||||||
|
%%
|
||||||
|
% *Write XML with "StructItem = false". Notice multiple 'a' sections*
|
||||||
|
wPref.StructItem = false;
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n')
|
||||||
|
gen_object_display(xml_read ('test.xml'))
|
||||||
|
%%
|
||||||
|
% *Notice that xml_read function produced the same struct when reading both files*
|
||||||
|
%%
|
||||||
|
% *Potential problems with "StructItem = true":*
|
||||||
|
wPref.StructItem = true;
|
||||||
|
MyTree1 = []; MyTree1.a.b = 'jack';
|
||||||
|
MyTree2 = []; MyTree2.a(1).b = 'jack';
|
||||||
|
MyTree3 = []; MyTree3.a(2).b = 'jack';
|
||||||
|
xml_write('test.xml', MyTree1, [], wPref); type('test.xml');
|
||||||
|
xml_write('test.xml', MyTree2, [], wPref); type('test.xml');
|
||||||
|
xml_write('test.xml', MyTree3, [], wPref); type('test.xml');
|
||||||
|
%%
|
||||||
|
% *Notice that MyTree1 and MyTree2 produce identical files with no 'items',
|
||||||
|
% while MyTree2 and MyTree3 produce very different file structures. It was
|
||||||
|
% pointed out to me that files produced from MyTree2 and MyTree3 can not
|
||||||
|
% belong to the same schema, which can be a problem. The solution is to use
|
||||||
|
% cells.*
|
||||||
|
wPref.CellItem = true;
|
||||||
|
wPref.NoCells = true;
|
||||||
|
MyTree2 = []; MyTree2.a{1}.b = 'jack';
|
||||||
|
MyTree3 = []; MyTree3.a{2}.b = 'jack';
|
||||||
|
xml_write('test.xml', MyTree2, [], wPref); type('test.xml');
|
||||||
|
xml_write('test.xml', MyTree3, [], wPref); type('test.xml');
|
||||||
|
|
||||||
|
|
||||||
|
%% "Pref.CellItem" flag in "xml_write" (controls 1D arrays of cells)
|
||||||
|
% *Create a simple structure with cell arrays*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.a = {'jack', 'john'};
|
||||||
|
disp(MyTree)
|
||||||
|
%%
|
||||||
|
% *Write XML with "CellItem = true" (default). Notice single 'a'
|
||||||
|
% section and multiple 'item' sections*
|
||||||
|
Pref=[]; Pref.CellItem = true;
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n');
|
||||||
|
disp(xml_read ('test.xml'))
|
||||||
|
%%
|
||||||
|
% *Write XML with "CellItem = false". Notice multiple 'a' sections*
|
||||||
|
Pref=[]; Pref.CellItem = false;
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n');
|
||||||
|
disp(xml_read ('test.xml'))
|
||||||
|
%%
|
||||||
|
% *Notice that xml_read function produced the same struct when reading both files*
|
||||||
|
|
||||||
|
%% "Pref.NoCells" flag in "xml_read"
|
||||||
|
% *Create a cell/struct mixture object*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.a{1}.b = 'jack';
|
||||||
|
MyTree.a{2}.b = [];
|
||||||
|
MyTree.a{2}.c = 'john';
|
||||||
|
gen_object_display(MyTree);
|
||||||
|
%%
|
||||||
|
% *Save it to xml file*
|
||||||
|
Pref=[]; Pref.CellItem = false;
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.NoCells=true" (default) - output is quite different then input*
|
||||||
|
% By default program is trying to convert everything to struct's and arrays
|
||||||
|
% of structs. In case arrays of structs all the structs in array need to have the
|
||||||
|
% same fields, and if they are not than MATLAB creates empty fields.
|
||||||
|
Pref=[]; Pref.NoCells=true;
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.NoCells=false" - now input and output are the same*
|
||||||
|
% Cell arrays of structs allow structs in array to have different fields.
|
||||||
|
Pref=[]; Pref.NoCells=false;
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
|
||||||
|
%% "Pref.ItemName" flag in "xml_write" (customize 1D arrays of structs and cells)
|
||||||
|
% *Create a cell/struct mixture object*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.a{1}.b = 'jack';
|
||||||
|
MyTree.a{2}.c = 'john';
|
||||||
|
gen_object_display(MyTree);
|
||||||
|
%%
|
||||||
|
% *Save it to xml file, using 'item' notation but with different name*
|
||||||
|
Pref=[];
|
||||||
|
Pref.CellItem = true;
|
||||||
|
Pref.ItemName = 'MyItem';
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% "Pref.ItemName" flag in "xml_read"
|
||||||
|
% *Read above file with default settings ("Pref.ItemName = 'item'")*
|
||||||
|
% The results do not match the original structure
|
||||||
|
Pref=[]; Pref.NoCells = false;
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.ItemName = 'MyItem'" - now saved and read
|
||||||
|
% MATLAB structures are the same*
|
||||||
|
Pref=[];
|
||||||
|
Pref.ItemName = 'MyItem';
|
||||||
|
Pref.NoCells = false;
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
|
||||||
|
%% "Pref.CellItem" flag in "xml_read"
|
||||||
|
% "Pref.ItemName" is used to create xml files with clearly marked arrays
|
||||||
|
% "Pref.CellItem" flag in "xml_read" ensures that they are always read as
|
||||||
|
% arrays by forcing output to stay in cell format. In cell format s{1} is
|
||||||
|
% different than s, while s(1) is indistinguishable from s.
|
||||||
|
%%
|
||||||
|
% *Create a test file*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.a1{1}.b = 'jack'; % a1 - single struct
|
||||||
|
MyTree.a2{1}.b = 'jack'; % a2 - cell array of structs with the same fields
|
||||||
|
MyTree.a2{2}.b = 'john';
|
||||||
|
MyTree.a3{1}.b = 'jack'; % a3 - cell array of structs with the different fields
|
||||||
|
MyTree.a3{2}.c = 'john';
|
||||||
|
Pref=[];
|
||||||
|
Pref.CellItem = true;
|
||||||
|
Pref.Debug = true;
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.CellItem = true" (default)*
|
||||||
|
% All outputs are in cell format
|
||||||
|
Pref=[];
|
||||||
|
Pref.NoCells = false; % allow cell output
|
||||||
|
Pref.CellItem = true; % keep 'item' arrays as cells
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.CellItem = false"*
|
||||||
|
% Outputs format is determined by content
|
||||||
|
Pref=[];
|
||||||
|
Pref.NoCells = false; % allow cell output
|
||||||
|
Pref.CellItem = false; % allow 'item' arrays to beheave like other fields
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.CellItem = false" and "Pref.NoCells = true"*
|
||||||
|
% All outputs are in struct format
|
||||||
|
Pref=[];
|
||||||
|
Pref.NoCells = true; % don't allow cell output
|
||||||
|
Pref.CellItem = false; % allow 'item' arrays to beheave like other fields
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
|
||||||
|
%% "Pref.CellTable" flag in "xml_write" (controls 2D arrays of cells)
|
||||||
|
% *Create a structure with 2D arrays of cells*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.M = {[1,2;3,4], 'M12'; struct('a','jack'), {11, 'N12'; 21, 'N22'}};
|
||||||
|
gen_object_display(MyTree)
|
||||||
|
%%
|
||||||
|
% *Write XML with "CellTable = 'Html" (default). This option mimics use of
|
||||||
|
% HTML "tr" and "td" tags to encode 2D tables. Tag names can
|
||||||
|
% be changed using TableName parameter (see below)*
|
||||||
|
wPref = [];
|
||||||
|
wPref.CellTable = 'Html';
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n')
|
||||||
|
rPref=[]; rPref.NoCells=false;
|
||||||
|
gen_object_display(xml_read('test.xml', rPref))
|
||||||
|
%%
|
||||||
|
% *Write XML with "CellTable = 'Vector'".*
|
||||||
|
% Converts 2D arrays to 1D array and item or regular notation. This option
|
||||||
|
% is mostly provided for backward compatibility since this was the
|
||||||
|
% behavior in prior verions of the code
|
||||||
|
wPref = [];
|
||||||
|
wPref.CellTable = 'Vector';
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n')
|
||||||
|
rPref=[]; rPref.NoCells=false;
|
||||||
|
gen_object_display(xml_read('test.xml', rPref))
|
||||||
|
%%
|
||||||
|
% *Create a simpler structure without struct's*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.M = {[1,2;3,4], 'M12'; 'M21', {11, 'N12'; 21, 'N22'}};
|
||||||
|
gen_object_display(MyTree)
|
||||||
|
%%
|
||||||
|
% *Write XML with "CellTable = 'Matlab". This option encodes tables
|
||||||
|
% consisting of numbers, strings and other cell arrays as MATLAB command
|
||||||
|
% string. Unlike 'Html' option it does not work if one of the cells is
|
||||||
|
% a struct*
|
||||||
|
wPref = [];
|
||||||
|
wPref.CellTable = 'Matlab';
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n')
|
||||||
|
rPref=[]; rPref.NoCells=false;
|
||||||
|
gen_object_display(xml_read('test.xml', rPref))
|
||||||
|
|
||||||
|
%% Write 2D cell array in HTML format
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.table.ATTRIBUTE.border=1;
|
||||||
|
MyTree.table.CONTENT = {'Apples', '44%'; 'Bannanas', '23%'; 'Oranges', '13%'; 'Other', '10%'};
|
||||||
|
xml_write('html/test.html', MyTree);
|
||||||
|
type('html/test.html')
|
||||||
|
%%
|
||||||
|
% Click on <test.html> to opened this file with a web brouwser
|
||||||
|
|
||||||
|
%% "Pref.StructTable" flag in "xml_write" (controls 2D arrays of structs)
|
||||||
|
% *Create a simple structure with arrays of struct's*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.a(1,1).b = 'jack';
|
||||||
|
MyTree.a(1,2).b = 'john';
|
||||||
|
MyTree.a(2,1).b = 'jim';
|
||||||
|
MyTree.a(2,2).b = 'jill';
|
||||||
|
gen_object_display(MyTree)
|
||||||
|
%%
|
||||||
|
% *Write XML with "StructTable = 'Html" (default). This option mimics use of
|
||||||
|
% HTML "tr" and "td" tags to encode 2D tables. Tag names can
|
||||||
|
% be changed using TableName parameter (see below)*
|
||||||
|
wPref = [];
|
||||||
|
wPref.StructTable = 'Html';
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n')
|
||||||
|
gen_object_display(xml_read ('test.xml'))
|
||||||
|
%%
|
||||||
|
% *Write XML with "CellTable = 'Vector'".*
|
||||||
|
% Converts 2D arrays to 1D array and item or regular notation. This option
|
||||||
|
% is mostly provided for backward compatibility since this was the
|
||||||
|
% behavior in prior verions of the code
|
||||||
|
wPref = [];
|
||||||
|
wPref.StructTable = 'Vector';
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||||
|
type('test.xml')
|
||||||
|
fprintf('\nxml_read output:\n')
|
||||||
|
gen_object_display(xml_read ('test.xml'))
|
||||||
|
|
||||||
|
%% "Pref.TableName" flag in "xml_write" (controls encoding tags used for 2D arrays)
|
||||||
|
% *Create a cell object*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.M = {[1,2;3,4], 'M12'; 21, {11, 'N12'; 21, 'N22'}};
|
||||||
|
gen_object_display(MyTree);
|
||||||
|
%%
|
||||||
|
% *Save it to xml file, using 'Html' notation but with different names for
|
||||||
|
% rows and cells*
|
||||||
|
Pref=[]; Pref.TableName = {'row','cell'};
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% "Pref.TableName" flag in "xml_read"
|
||||||
|
% *Read above file with default settings ("Pref.TableName = {'tr','td'}")*
|
||||||
|
% The results do not match the original structure
|
||||||
|
Pref=[]; Pref.NoCells = false;
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.TableName = {'row','cell'}" - now saved and read
|
||||||
|
% MATLAB structures are the same*
|
||||||
|
Pref=[];
|
||||||
|
Pref.TableName = {'row','cell'};
|
||||||
|
Pref.NoCells = false;
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
|
||||||
|
%% "Pref.Str2Num" flag in xml_read (control conversion to numbers while reading)
|
||||||
|
% *Create a cell/struct mixture object*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.str = 'sphere';
|
||||||
|
MyTree.num1 = 123;
|
||||||
|
MyTree.num2 = '123';
|
||||||
|
MyTree.num3 = '[Inf,NaN]';
|
||||||
|
MyTree.calc = '1+2+3+4';
|
||||||
|
MyTree.func = 'sin(pi)/2';
|
||||||
|
MyTree.String1 = '[2003 10 30]';
|
||||||
|
MyTree.String2 = '2003 10 30'; % array resembling date
|
||||||
|
MyTree.ISO8601 = '2003-10-30'; % date in ISO 8601 format
|
||||||
|
MyTree.US_date = '2003/10/30'; % US style date format
|
||||||
|
MyTree.complex = '2003i-10e-30'; % complex number resembling a date
|
||||||
|
gen_object_display(MyTree);
|
||||||
|
%%
|
||||||
|
% *Save it to xml file*
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Read above file with default settings*
|
||||||
|
% ("Pref.Str2Num = true" or "Pref.Str2Num = 'smart'"). Under this setting all
|
||||||
|
% strings that look like numbers are converted to numbers, except for
|
||||||
|
% strings that are recognized by MATLAB 'datenum' function as dates
|
||||||
|
gen_object_display(xml_read('test.xml'))
|
||||||
|
%%
|
||||||
|
% *Note that all the fields of 'MyTree' can be converted to numbers (even
|
||||||
|
% 'sphere') but by default the function is trying to 'judge' if a string
|
||||||
|
% should be converted to a number or not*
|
||||||
|
MyCell = {'sphere','1+2+3+4','sin(pi)/2','2003 10 30','2003-10-30','2003/10/30','2003i-10e-30'};
|
||||||
|
cellfun(@str2num, MyCell, 'UniformOutput', false)
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.Str2Num = false" or "Pref.Str2Num = 'never'"
|
||||||
|
% to keep all the fields in string format*
|
||||||
|
Pref=[]; Pref.Str2Num = false;
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.Str2Num = always"
|
||||||
|
% to convert all strings that look like numbers to numbers* note the likelly
|
||||||
|
% unintendet conversion of 'ISO8601'
|
||||||
|
Pref=[]; Pref.Str2Num = 'always';
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Notice that all three settings will produce the same output for "num1" and
|
||||||
|
% "num2" and there is no way to reproduce the original "MyTree" structure.*
|
||||||
|
|
||||||
|
%% "Pref.PreserveSpace" flag in xml_write (control handling of strings with leading/trailing spaces)
|
||||||
|
% *Create a struct with strings*
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.Empty = '';
|
||||||
|
MyTree.OneSpace = ' ';
|
||||||
|
MyTree.TwoSpaces = ' ';
|
||||||
|
MyTree.String1 = ' Hello World ';
|
||||||
|
%%
|
||||||
|
% *Write XML with "PreserveSpace = false" (default).*
|
||||||
|
Pref=[]; Pref.PreserveSpace = false; % (default setting)
|
||||||
|
xml_write('test.xml', MyTree, [], Pref);
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Write XML with "PreserveSpace = true".*
|
||||||
|
Pref=[]; Pref.PreserveSpace = true;
|
||||||
|
xml_write('test.xml', MyTree, [], Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% "Pref.PreserveSpace" flag in xml_read
|
||||||
|
% *Read file while using "PreserveSpace = false" (default).*
|
||||||
|
Pref=[]; Pref.PreserveSpace = false; % (default setting)
|
||||||
|
gen_object_display(xml_read('test.xml',Pref))
|
||||||
|
%%
|
||||||
|
% *Read file while using "PreserveSpace = true".*
|
||||||
|
Pref=[]; Pref.PreserveSpace = true;
|
||||||
|
gen_object_display(xml_read('test.xml',Pref))
|
||||||
|
|
||||||
|
|
||||||
|
%% Write XML files with ATTRIBUTEs
|
||||||
|
% In order to add node attributes a special ATTRIBUTE field is used.
|
||||||
|
% ATTRIBUTEs have to be of simple types like numbers or strings (not
|
||||||
|
% struct or cells). Attributes are easy to attach to structs nodes like
|
||||||
|
% MyTree below.
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString = 'Hello World'; % simple case
|
||||||
|
MyTree.ATTRIBUTE.Num = 2;
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% In case when one needs to attach attributes to nodes which are not
|
||||||
|
% structs (for example strings, numbers or calls) then special CONTENT
|
||||||
|
% field needs to be used to make the node a struct node.
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString.CONTENT = 'Hello World'; % simple case
|
||||||
|
MyTree.MyString.ATTRIBUTE.Num = 2;
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% "Pref.Str2Num" flag in file with ATTRIBUTEs
|
||||||
|
% *Create a cell/struct mixture object*
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.X.ATTRIBUTE.str = 'sphere';
|
||||||
|
MyTree.X.ATTRIBUTE.num1 = 123;
|
||||||
|
MyTree.X.ATTRIBUTE.num2 = '123';
|
||||||
|
MyTree.X.ATTRIBUTE.num3 = '[Inf,NaN]';
|
||||||
|
MyTree.X.ATTRIBUTE.calc = '1+2+3+4';
|
||||||
|
MyTree.X.ATTRIBUTE.func = 'sin(pi)/2';
|
||||||
|
MyTree.X.ATTRIBUTE.String1 = '[2003 10 30]';
|
||||||
|
MyTree.X.ATTRIBUTE.String2 = '2003 10 30'; % array resembling date
|
||||||
|
MyTree.X.ATTRIBUTE.ISO8601 = '2003-10-30'; % date in ISO 8601 format
|
||||||
|
MyTree.X.ATTRIBUTE.US_date = '2003/10/30'; % US style date format
|
||||||
|
MyTree.X.ATTRIBUTE.complex = '2003i-10e-30'; % complex number resembling a date
|
||||||
|
gen_object_display(MyTree);
|
||||||
|
%%
|
||||||
|
% *Save it to xml file*
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Read above file with default settings*
|
||||||
|
% ("Pref.Str2Num = true" or "Pref.Str2Num = 'smart'"). Under this setting all
|
||||||
|
% strings that look like numbers are converted to numbers, except for
|
||||||
|
% strings that are recognized by MATLAB 'datenum' function as dates
|
||||||
|
gen_object_display(xml_read('test.xml'))
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.Str2Num = false" or "Pref.Str2Num = 'never'"
|
||||||
|
% to keep all the fields in string format*
|
||||||
|
Pref=[]; Pref.Str2Num = false;
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Read above file with "Pref.Str2Num = always"
|
||||||
|
% to convert all strings that look like numbers to numbers*
|
||||||
|
Pref=[]; Pref.Str2Num = 'always';
|
||||||
|
gen_object_display(xml_read('test.xml', Pref))
|
||||||
|
%%
|
||||||
|
% *Notice that all three settings will produce the same output for "num1" and
|
||||||
|
% "num2" and there is no way to reproduce the original "MyTree" structure.*
|
||||||
|
|
||||||
|
|
||||||
|
%% Write XML files with COMMENTs
|
||||||
|
% Insertion of Comments is done with help of special COMMENT field.
|
||||||
|
% Note that MATLAB's xmlwrite is less readable due to lack of end-of-line
|
||||||
|
% characters around comment section.
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.COMMENT = 'This is a comment';
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString.CONTENT = 'Hello World';
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *Same operation using Apache Xerces XML engine*
|
||||||
|
% gives the same result
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree', Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *Comments in XML top level (method #1)*
|
||||||
|
% This method uses cell array
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString = 'Hello World';
|
||||||
|
xml_write('test.xml', MyTree, {'MyTree', [], 'This is a global comment'});
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Same operation using Apache Xerces XML engine*
|
||||||
|
% gives even nicer results.
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
xml_write('test.xml', MyTree, {'MyTree', [], 'This is a global comment'}, Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *Comments in XML top level (method #2)*
|
||||||
|
% This method adds an extra top layer to the struct 'tree' and sets
|
||||||
|
% "Pref.RootOnly = false", which informs the function about the extra
|
||||||
|
% layer. Notice that RootName is also saved as a part of
|
||||||
|
% the 'tree', and does not have to be passed in separately.
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.COMMENT = 'This is a global comment';
|
||||||
|
MyTree.MyTest.MyNumber = 13;
|
||||||
|
MyTree.MyTest.MyString = 'Hello World';
|
||||||
|
Pref=[]; Pref.RootOnly = false;
|
||||||
|
xml_write('test.xml', MyTree, [], Pref);
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Same operation using Apache Xerces XML engine*
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
Pref.RootOnly = false;
|
||||||
|
xml_write('test.xml', MyTree, [], Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Write XML files with PROCESSING_INSTRUCTIONs
|
||||||
|
% Insertion of Processing Instructions is done through use of special
|
||||||
|
% PROCESSING_INSTRUCTION field, which stores the instruction string. The
|
||||||
|
% string has to be in 'target data' format separated by space.
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.PROCESSING_INSTRUCTION = 'xml-stylesheet type="a" href="foo"';
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString = 'Hello World';
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *Same operation using Apache Xerces XML engine*
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree', Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *PROCESSING_INSTRUCTIONs in XML top level (method #1)*
|
||||||
|
% This method uses cell array
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString = 'Hello World';
|
||||||
|
xml_write('test.xml', MyTree, {'MyTree', 'xml-stylesheet type="a" href="foo"'});
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Same operation using Apache Xerces XML engine*
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
xml_write('test.xml', MyTree, {'MyTree', 'xml-stylesheet type="a" href="foo"'}, Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *PROCESSING_INSTRUCTIONs in XML top level (method #2)*
|
||||||
|
% This method adds an extra top layer to the struct 'tree' and sets
|
||||||
|
% pref.RootOnly=false, which informs the function about the extra
|
||||||
|
% layer. Notice that RootName is also saved as a part of
|
||||||
|
% the 'tree', and does not have to be passed in separately.
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.PROCESSING_INSTRUCTION = 'xml-stylesheet type="a" href="foo"';
|
||||||
|
MyTree.MyTest.MyNumber = 13;
|
||||||
|
MyTree.MyTest.MyString = 'Hello World';
|
||||||
|
Pref=[]; Pref.RootOnly = false;
|
||||||
|
xml_write('test.xml', MyTree, [], Pref);
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Same operation using Apache Xerces XML engine*
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
Pref.RootOnly = false;
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree', Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Write XML files with CDATA Sections
|
||||||
|
% "In an XML document a CDATA (Character DATA) section is a section of
|
||||||
|
% element content that is marked for the parser to interpret as only
|
||||||
|
% character data, not markup." (from Wikipedia)
|
||||||
|
% To insert CDATA Sections one use special CDATA_SECTION field,
|
||||||
|
% which stores the instruction string. Note that MATLAB's xmlwrite created
|
||||||
|
% wrong xml code for CDATA section
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.CDATA_SECTION = '<A>txt</A>';
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString = 'Hello World';
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Same operation using Apache Xerces XML engine produces correct results*
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree', Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Write XML files with special characters in TAG names
|
||||||
|
% The input to xml_write requires that all tags one wants in XML document
|
||||||
|
% have to be encoded as field names of MATLAB's struct's. Matlab has a lot
|
||||||
|
% of restrictions on variable names. This section is about XML tags with
|
||||||
|
% names not allowed as MATLAB variables, or more specifically with
|
||||||
|
% characters allowed as xml tag names but not allowed as MATLAB variable
|
||||||
|
% names. Characters like that can be replaced by their hexadecimal
|
||||||
|
% representation just as it is done by genvarname function. Alternative way
|
||||||
|
% of writing the first example is:
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.('MyNumber') = 13; % same as MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString.CONTENT = 'Hello World';
|
||||||
|
MyTree.MyString.ATTRIBUTE.('Num') = 2; % same as MyTree.MyString.ATTRIBUTE.Num = 2;
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *This approach fails for some characters like dash '-', colon ':', and
|
||||||
|
% international characters.*
|
||||||
|
MyTree=[];
|
||||||
|
try
|
||||||
|
MyTree.('My-Number') = 13;
|
||||||
|
MyTree.MyString.CONTENT = 'Hello World';
|
||||||
|
MyTree.MyString.ATTRIBUTE.('Num_ö') = 2;
|
||||||
|
catch %#ok<CTCH>
|
||||||
|
err = lasterror; %#ok<LERR>
|
||||||
|
disp(err.message);
|
||||||
|
end
|
||||||
|
|
||||||
|
%%
|
||||||
|
% It can be overcome by replacing offending characters with their
|
||||||
|
% hexadecimal representation. That can be done manually or with use of
|
||||||
|
% genvarname function. Note that MATLAB 'type' function does not show
|
||||||
|
% correctly 'ö' letter in xml file, but opening the file in editor shows
|
||||||
|
% that it is correct.
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.(genvarname('My-Number')) = 13;
|
||||||
|
MyTree.MyString.CONTENT = 'Hello World';
|
||||||
|
MyTree.MyString.ATTRIBUTE.Num_0xF6 = 2;
|
||||||
|
gen_object_display(MyTree);
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%%
|
||||||
|
% *Also two of the characters '-' and ':' can be encoded by a special strings:
|
||||||
|
% '_DASH_' and '_COLON_' respectively*
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.My_DASH_Number = 13;
|
||||||
|
MyTree.MyString.CONTENT = 'Hello World';
|
||||||
|
MyTree.MyString.ATTRIBUTE.Num0xF6 = 2;
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Write XML files with Namespaces
|
||||||
|
% No extra special fields are needed to define XML namespaces, only colon
|
||||||
|
% character written using '0x3A' or '_COLON_'. Below is an
|
||||||
|
% example of a namespace definition
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.f_COLON_child.ATTRIBUTE.xmlns_COLON_f = 'http://www.foo.com';
|
||||||
|
MyTree.f_COLON_child.f_COLON_MyNumber = 13;
|
||||||
|
MyTree.f_COLON_child.f_COLON_MyString = 'Hello World';
|
||||||
|
xml_write('test.xml', MyTree, 'MyTree');
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Same operation using Apache Xerces XML engine*
|
||||||
|
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
xml_write('test.xml', MyTree, 'f_COLON_MyTree', Pref);
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% "Pref.KeepNS" flag in "xml_read"
|
||||||
|
% Thise option allow keeping or exclusion of namespaces in tag names.
|
||||||
|
% By default the namespace data is kept but it produces much longer field
|
||||||
|
% names in the output structure. Ignoring namespace will produce more
|
||||||
|
% readible output.
|
||||||
|
% Perform default read of file with namespace
|
||||||
|
tree = xml_read('test.xml');
|
||||||
|
gen_object_display(tree);
|
||||||
|
|
||||||
|
%%
|
||||||
|
% Now the same operation with KeepNS = false.
|
||||||
|
Pref=[]; Pref.KeepNS = false; % do not read attributes
|
||||||
|
tree = xml_read('test.xml', Pref);
|
||||||
|
gen_object_display(tree);
|
||||||
|
|
||||||
|
%% Read XML files with special node types
|
||||||
|
% Display and read the file, then show the data structure. Note that
|
||||||
|
% MATLAB 'type' function shows 'ö' letter incorrectly as 'A¶' in xml file,
|
||||||
|
% but opening the file in editor shows that it is correct.
|
||||||
|
fprintf('Test xml file:\n');
|
||||||
|
type('test_file.xml')
|
||||||
|
%%
|
||||||
|
% Read only the Root Element (default)
|
||||||
|
[tree GlobalTextNodes] = xml_read('test_file.xml');
|
||||||
|
fprintf('Global Data (Root name, Global Processing Instructions and Global Comments):\n');
|
||||||
|
disp(GlobalTextNodes')
|
||||||
|
fprintf('\nStructure read from the file (uncludes COMMENT and CDATA sections):\n');
|
||||||
|
gen_object_display(tree);
|
||||||
|
%%
|
||||||
|
% Read the whole tree including global Comments and Processing Instructions
|
||||||
|
Pref=[]; Pref.RootOnly = false;
|
||||||
|
[tree GlobalTextNodes] = xml_read('test_file.xml', Pref);
|
||||||
|
fprintf('Global Data (Root name, Global Processing Instructions and Global Comments):\n');
|
||||||
|
disp(GlobalTextNodes')
|
||||||
|
fprintf('\nStructure read from the file (uncludes COMMENT and CDATA sections):\n');
|
||||||
|
gen_object_display(tree);
|
||||||
|
|
||||||
|
%% "Pref.ReadAttr" flag in "xml_read" (control handling of nodes with attributes)
|
||||||
|
% Those option allow exclusion of attributes
|
||||||
|
Pref=[]; Pref.ReadAttr = false; % do not read attributes
|
||||||
|
tree = xml_read('test_file.xml', Pref);
|
||||||
|
gen_object_display(tree);
|
||||||
|
|
||||||
|
%% "Pref.ReadSpec" flag in "xml_read"
|
||||||
|
% Those option allow exclusion of special nodes, like
|
||||||
|
% comments, processing instructions, CData sections, etc.
|
||||||
|
Pref=[]; Pref.ReadSpec = false; % do not read special node types
|
||||||
|
tree = xml_read('test_file.xml', Pref);
|
||||||
|
gen_object_display(tree);
|
||||||
|
|
||||||
|
%% "Pref.RootOnly" flag in "xml_read"
|
||||||
|
% As it was shown in previous examples RootOnly parameter can be used to
|
||||||
|
% capture global (top level) special nodes (like COMMENTs and
|
||||||
|
% PROCESSING_INSTRUCTIONs) which are ignored by default
|
||||||
|
Pref=[]; Pref.RootOnly = false; % do not read special node types
|
||||||
|
tree = xml_read('test_file.xml', Pref);
|
||||||
|
gen_object_display(tree);
|
||||||
|
|
||||||
|
%% "Pref.RootOnly" flag in "xml_write"
|
||||||
|
% Writing previously read tree with default "Pref.RootOnly = true" gives
|
||||||
|
% wrong output file
|
||||||
|
Pref=[]; Pref.RootOnly = true; % do not read special node types
|
||||||
|
xml_write('test.xml', tree, [], Pref);
|
||||||
|
fprintf('Test xml file:\n');
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% Writing the same tree with "Pref.RootOnly = false" gives correct output
|
||||||
|
Pref=[]; Pref.RootOnly = false; % do not read special node types
|
||||||
|
xml_write('test.xml', tree, [], Pref);
|
||||||
|
fprintf('Test xml file:\n');
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% "Pref.NumLevels" flag in "xml_read"
|
||||||
|
% This parameter allows user to skip parts of the tree in order to save
|
||||||
|
% time and memory. Usefull only in a rare case when a small portion of
|
||||||
|
% large XML file is needed.
|
||||||
|
%
|
||||||
|
% Create test tile
|
||||||
|
MyTree = [];
|
||||||
|
MyTree.Level1 = 1;
|
||||||
|
MyTree.Level1_.Level2 = 2;
|
||||||
|
MyTree.Level1_.Level2_.Level3 = 3;
|
||||||
|
MyTree.Level1_.Level2_.Level3_.Level4 = 4;
|
||||||
|
xml_write('test.xml', MyTree);
|
||||||
|
fprintf('Test xml file:\n');
|
||||||
|
type('test.xml')
|
||||||
|
%%
|
||||||
|
% *Use Default ("Pref.NumLevels = infinity") setting*
|
||||||
|
tree = xml_read('test.xml');
|
||||||
|
gen_object_display(tree);
|
||||||
|
%%
|
||||||
|
% *Limit the read to only 2 levels*
|
||||||
|
Pref=[]; Pref.NumLevels = 2;
|
||||||
|
tree = xml_read('test.xml', Pref);
|
||||||
|
gen_object_display(tree);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%% Create DOM object based on a Struct using "xml_write"
|
||||||
|
% *Create Struct tree*
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.MyNumber = 13;
|
||||||
|
MyTree.MyString = 'Hello World';
|
||||||
|
%%
|
||||||
|
% *Convert Struct to DOM object using xml_write*
|
||||||
|
DOM = xml_write([], MyTree);
|
||||||
|
xmlwrite('test.xml', DOM); % Save DOM object using MATLAB function
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Convert DOM object to Struct using "xml_read"
|
||||||
|
DOM = xmlread('test.xml'); % Read DOM object using MATLAB function
|
||||||
|
[tree treeName] = xml_read(DOM); % Convert DOM object to Struct
|
||||||
|
disp([treeName{1} ' ='])
|
||||||
|
gen_object_display(tree)
|
||||||
|
|
||||||
|
%% Write XML file based on a DOM using "xml_write_xerces"
|
||||||
|
xmlwrite_xerces('test.xml', DOM); % Save DOM object using Xerces library
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Write XML to string instead of a file
|
||||||
|
DOM = xml_write([], MyTree);
|
||||||
|
str = xmlwrite(DOM);
|
||||||
|
disp(str)
|
||||||
|
|
||||||
|
%% Write XML file with embedded binary data encoded as Base64 (using java version)
|
||||||
|
fid = fopen('football.jpg', 'rb');
|
||||||
|
raw1 = uint8(fread(fid, 'uint8')); % read image file as a raw binary
|
||||||
|
fclose(fid);
|
||||||
|
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.Size = 13;
|
||||||
|
MyTree.MyString = 'Hello World'; % simple case
|
||||||
|
MyTree.MyImage.ATTRIBUTE.EncodingMIMEType = 'base64';
|
||||||
|
MyTree.MyImage.CONTENT = base64encode(raw1,'java');% perform base64 encoding of the binary data
|
||||||
|
xml_write('test.xml', MyTree); % write xml file
|
||||||
|
|
||||||
|
%% Read XML file with embedded binary data encoded as Base64 (using java version)
|
||||||
|
tree = xml_read('test.xml', Pref); % read xml file
|
||||||
|
raw = base64decode(tree.MyImage.CONTENT, '', 'java'); % convert xml image to raw binary
|
||||||
|
fid = fopen('MyFootball.jpg', 'wb');
|
||||||
|
fwrite(fid, raw, 'uint8'); % dumb the raw binary to the hard disk
|
||||||
|
fclose(fid);
|
||||||
|
I = imread('MyFootball.jpg'); % read it as an image
|
||||||
|
imshow(I);
|
||||||
|
|
||||||
|
%% Write XML file with embedded binary data encoded as Base64 (simpler version using only matlab code
|
||||||
|
% Notice that process of writing to xml stripped all end-of-lie characters
|
||||||
|
% from base64 code.
|
||||||
|
isChunked = true; % break into chunks 76 characters long
|
||||||
|
url_safe = true; % 'base64url' encoding
|
||||||
|
code = base64encode('license.txt', 'matlab', isChunked, url_safe);
|
||||||
|
disp(code)
|
||||||
|
MyTree=[];
|
||||||
|
MyTree.Size = 13;
|
||||||
|
MyTree.MyString = 'Hello World';
|
||||||
|
MyTree.MyImage.ATTRIBUTE.EncodingMIMEType = 'base64';
|
||||||
|
MyTree.MyImage.CONTENT = code; % perform base64 encoding of the binary data
|
||||||
|
xml_write('test.xml', MyTree); % write xml file
|
||||||
|
type('test.xml')
|
||||||
|
|
||||||
|
%% Read XML file with embedded binary data encoded as Base64 (simpler version using only matlab code
|
||||||
|
tree = xml_read('test.xml', Pref); % read xml file
|
||||||
|
base64decode(tree.MyImage.CONTENT, 'license2.txt', 'matlab'); % save xml image as raw binary
|
||||||
|
type('license2.txt')
|
|
@ -0,0 +1,447 @@
|
||||||
|
function DOMnode = xml_write(filename, tree, RootName, Pref)
|
||||||
|
%XML_WRITE Writes Matlab data structures to XML file
|
||||||
|
%
|
||||||
|
% DESCRIPTION
|
||||||
|
% xml_write( filename, tree) Converts Matlab data structure 'tree' containing
|
||||||
|
% cells, structs, numbers and strings to Document Object Model (DOM) node
|
||||||
|
% tree, then saves it to XML file 'filename' using Matlab's xmlwrite
|
||||||
|
% function. Optionally one can also use alternative version of xmlwrite
|
||||||
|
% function which directly calls JAVA functions for XML writing without
|
||||||
|
% MATLAB middleware. This function is provided as a patch to existing
|
||||||
|
% bugs in xmlwrite (in R2006b).
|
||||||
|
%
|
||||||
|
% xml_write(filename, tree, RootName, Pref) allows you to specify
|
||||||
|
% additional preferences about file format
|
||||||
|
%
|
||||||
|
% DOMnode = xml_write([], tree) same as above except that DOM node is
|
||||||
|
% not saved to the file but returned.
|
||||||
|
%
|
||||||
|
% INPUT
|
||||||
|
% filename file name
|
||||||
|
% tree Matlab structure tree to store in xml file.
|
||||||
|
% RootName String with XML tag name used for root (top level) node
|
||||||
|
% Optionally it can be a string cell array storing: Name of
|
||||||
|
% root node, document "Processing Instructions" data and
|
||||||
|
% document "comment" string
|
||||||
|
% Pref Other preferences:
|
||||||
|
% Pref.ItemName - default 'item' - name of a special tag used to
|
||||||
|
% itemize cell or struct arrays
|
||||||
|
% Pref.XmlEngine - let you choose the XML engine. Currently default is
|
||||||
|
% 'Xerces', which is using directly the apache xerces java file.
|
||||||
|
% Other option is 'Matlab' which uses MATLAB's xmlwrite and its
|
||||||
|
% XMLUtils java file. Both options create identical results except in
|
||||||
|
% case of CDATA sections where xmlwrite fails.
|
||||||
|
% Pref.CellItem - default 'true' - allow cell arrays to use 'item'
|
||||||
|
% notation. See below.
|
||||||
|
% Pref.RootOnly - default true - output variable 'tree' corresponds to
|
||||||
|
% xml file root element, otherwise it correspond to the whole file.
|
||||||
|
% Pref.StructItem - default 'true' - allow arrays of structs to use
|
||||||
|
% 'item' notation. For example "Pref.StructItem = true" gives:
|
||||||
|
% <a>
|
||||||
|
% <b>
|
||||||
|
% <item> ... <\item>
|
||||||
|
% <item> ... <\item>
|
||||||
|
% <\b>
|
||||||
|
% <\a>
|
||||||
|
% while "Pref.StructItem = false" gives:
|
||||||
|
% <a>
|
||||||
|
% <b> ... <\b>
|
||||||
|
% <b> ... <\b>
|
||||||
|
% <\a>
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% Several special xml node types can be created if special tags are used
|
||||||
|
% for field names of 'tree' nodes:
|
||||||
|
% - node.CONTENT - stores data section of the node if other fields
|
||||||
|
% (usually ATTRIBUTE are present. Usually data section is stored
|
||||||
|
% directly in 'node'.
|
||||||
|
% - node.ATTRIBUTE.name - stores node's attribute called 'name'.
|
||||||
|
% - node.COMMENT - create comment child node from the string. For global
|
||||||
|
% comments see "RootName" input variable.
|
||||||
|
% - node.PROCESSING_INSTRUCTIONS - create "processing instruction" child
|
||||||
|
% node from the string. For global "processing instructions" see
|
||||||
|
% "RootName" input variable.
|
||||||
|
% - node.CDATA_SECTION - stores node's CDATA section (string). Only works
|
||||||
|
% if Pref.XmlEngine='Xerces'. For more info, see comments of F_xmlwrite.
|
||||||
|
% - other special node types like: document fragment nodes, document type
|
||||||
|
% nodes, entity nodes and notation nodes are not being handled by
|
||||||
|
% 'xml_write' at the moment.
|
||||||
|
%
|
||||||
|
% OUTPUT
|
||||||
|
% DOMnode Document Object Model (DOM) node tree in the format
|
||||||
|
% required as input to xmlwrite. (optional)
|
||||||
|
%
|
||||||
|
% EXAMPLES:
|
||||||
|
% MyTree=[];
|
||||||
|
% MyTree.MyNumber = 13;
|
||||||
|
% MyTree.MyString = 'Hello World';
|
||||||
|
% xml_write('test.xml', MyTree);
|
||||||
|
% type('test.xml')
|
||||||
|
% %See also xml_tutorial.m
|
||||||
|
%
|
||||||
|
% See also
|
||||||
|
% xml_read, xmlread, xmlwrite
|
||||||
|
%
|
||||||
|
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||||||
|
|
||||||
|
%% Check Matlab Version
|
||||||
|
v = ver('MATLAB');
|
||||||
|
v = str2double(regexp(v.Version, '\d.\d','match','once'));
|
||||||
|
if (v<7)
|
||||||
|
error('Your MATLAB version is too old. You need version 7.0 or newer.');
|
||||||
|
end
|
||||||
|
|
||||||
|
%% default preferences
|
||||||
|
DPref.TableName = {'tr','td'}; % name of a special tags used to itemize 2D cell arrays
|
||||||
|
DPref.ItemName = 'item'; % name of a special tag used to itemize 1D cell arrays
|
||||||
|
DPref.StructItem = true; % allow arrays of structs to use 'item' notation
|
||||||
|
DPref.CellItem = true; % allow cell arrays to use 'item' notation
|
||||||
|
DPref.StructTable= 'Html';
|
||||||
|
DPref.CellTable = 'Html';
|
||||||
|
DPref.XmlEngine = 'Matlab'; % use matlab provided XMLUtils
|
||||||
|
%DPref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||||
|
DPref.PreserveSpace = false; % Preserve or delete spaces at the beggining and the end of stings?
|
||||||
|
RootOnly = true; % Input is root node only
|
||||||
|
GlobalProcInst = [];
|
||||||
|
GlobalComment = [];
|
||||||
|
GlobalDocType = [];
|
||||||
|
|
||||||
|
%% read user preferences
|
||||||
|
if (nargin>3)
|
||||||
|
if (isfield(Pref, 'TableName' )), DPref.TableName = Pref.TableName; end
|
||||||
|
if (isfield(Pref, 'ItemName' )), DPref.ItemName = Pref.ItemName; end
|
||||||
|
if (isfield(Pref, 'StructItem')), DPref.StructItem = Pref.StructItem; end
|
||||||
|
if (isfield(Pref, 'CellItem' )), DPref.CellItem = Pref.CellItem; end
|
||||||
|
if (isfield(Pref, 'CellTable')), DPref.CellTable = Pref.CellTable; end
|
||||||
|
if (isfield(Pref, 'StructTable')), DPref.StructTable= Pref.StructTable; end
|
||||||
|
if (isfield(Pref, 'XmlEngine' )), DPref.XmlEngine = Pref.XmlEngine; end
|
||||||
|
if (isfield(Pref, 'RootOnly' )), RootOnly = Pref.RootOnly; end
|
||||||
|
if (isfield(Pref, 'PreserveSpace')), DPref.PreserveSpace = Pref.PreserveSpace; end
|
||||||
|
end
|
||||||
|
if (nargin<3 || isempty(RootName)), RootName=inputname(2); end
|
||||||
|
if (isempty(RootName)), RootName='ROOT'; end
|
||||||
|
if (iscell(RootName)) % RootName also stores global text node data
|
||||||
|
rName = RootName;
|
||||||
|
RootName = char(rName{1});
|
||||||
|
if (length(rName)>1), GlobalProcInst = char(rName{2}); end
|
||||||
|
if (length(rName)>2), GlobalComment = char(rName{3}); end
|
||||||
|
if (length(rName)>3), GlobalDocType = char(rName{4}); end
|
||||||
|
end
|
||||||
|
if(~RootOnly && isstruct(tree)) % if struct than deal with each field separatly
|
||||||
|
fields = fieldnames(tree);
|
||||||
|
for i=1:length(fields)
|
||||||
|
field = fields{i};
|
||||||
|
x = tree(1).(field);
|
||||||
|
if (strcmp(field, 'COMMENT'))
|
||||||
|
GlobalComment = x;
|
||||||
|
elseif (strcmp(field, 'PROCESSING_INSTRUCTION'))
|
||||||
|
GlobalProcInst = x;
|
||||||
|
elseif (strcmp(field, 'DOCUMENT_TYPE'))
|
||||||
|
GlobalDocType = x;
|
||||||
|
else
|
||||||
|
RootName = field;
|
||||||
|
t = x;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tree = t;
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Initialize jave object that will store xml data structure
|
||||||
|
RootName = varName2str(RootName);
|
||||||
|
if (~isempty(GlobalDocType))
|
||||||
|
% n = strfind(GlobalDocType, ' ');
|
||||||
|
% if (~isempty(n))
|
||||||
|
% dtype = com.mathworks.xml.XMLUtils.createDocumentType(GlobalDocType);
|
||||||
|
% end
|
||||||
|
% DOMnode = com.mathworks.xml.XMLUtils.createDocument(RootName, dtype);
|
||||||
|
warning('xml_io_tools:write:docType', ...
|
||||||
|
'DOCUMENT_TYPE node was encountered which is not supported yet. Ignoring.');
|
||||||
|
end
|
||||||
|
DOMnode = com.mathworks.xml.XMLUtils.createDocument(RootName);
|
||||||
|
|
||||||
|
|
||||||
|
%% Use recursive function to convert matlab data structure to XML
|
||||||
|
root = DOMnode.getDocumentElement;
|
||||||
|
struct2DOMnode(DOMnode, root, tree, DPref.ItemName, DPref);
|
||||||
|
|
||||||
|
%% Remove the only child of the root node
|
||||||
|
root = DOMnode.getDocumentElement;
|
||||||
|
Child = root.getChildNodes; % create array of children nodes
|
||||||
|
nChild = Child.getLength; % number of children
|
||||||
|
if (nChild==1)
|
||||||
|
node = root.removeChild(root.getFirstChild);
|
||||||
|
while(node.hasChildNodes)
|
||||||
|
root.appendChild(node.removeChild(node.getFirstChild));
|
||||||
|
end
|
||||||
|
while(node.hasAttributes) % copy all attributes
|
||||||
|
root.setAttributeNode(node.removeAttributeNode(node.getAttributes.item(0)));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Save exotic Global nodes
|
||||||
|
if (~isempty(GlobalComment))
|
||||||
|
DOMnode.insertBefore(DOMnode.createComment(GlobalComment), DOMnode.getFirstChild());
|
||||||
|
end
|
||||||
|
if (~isempty(GlobalProcInst))
|
||||||
|
n = strfind(GlobalProcInst, ' ');
|
||||||
|
if (~isempty(n))
|
||||||
|
proc = DOMnode.createProcessingInstruction(GlobalProcInst(1:(n(1)-1)),...
|
||||||
|
GlobalProcInst((n(1)+1):end));
|
||||||
|
DOMnode.insertBefore(proc, DOMnode.getFirstChild());
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% Not supported yet as the code below does not work
|
||||||
|
% if (~isempty(GlobalDocType))
|
||||||
|
% n = strfind(GlobalDocType, ' ');
|
||||||
|
% if (~isempty(n))
|
||||||
|
% dtype = DOMnode.createDocumentType(GlobalDocType);
|
||||||
|
% DOMnode.insertBefore(dtype, DOMnode.getFirstChild());
|
||||||
|
% end
|
||||||
|
% end
|
||||||
|
|
||||||
|
%% save java DOM tree to XML file
|
||||||
|
if (~isempty(filename))
|
||||||
|
if (strcmpi(DPref.XmlEngine, 'Xerces'))
|
||||||
|
xmlwrite_xerces(filename, DOMnode);
|
||||||
|
else
|
||||||
|
xmlwrite(filename, DOMnode);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === struct2DOMnode Function ===========================================
|
||||||
|
% =======================================================================
|
||||||
|
function [] = struct2DOMnode(xml, parent, s, TagName, Pref)
|
||||||
|
% struct2DOMnode is a recursive function that converts matlab's structs to
|
||||||
|
% DOM nodes.
|
||||||
|
% INPUTS:
|
||||||
|
% xml - jave object that will store xml data structure
|
||||||
|
% parent - parent DOM Element
|
||||||
|
% s - Matlab data structure to save
|
||||||
|
% TagName - name to be used in xml tags describing 's'
|
||||||
|
% Pref - preferenced
|
||||||
|
% OUTPUT:
|
||||||
|
% parent - modified 'parent'
|
||||||
|
|
||||||
|
% perform some conversions
|
||||||
|
if (ischar(s) && min(size(s))>1) % if 2D array of characters
|
||||||
|
s=cellstr(s); % than convert to cell array
|
||||||
|
end
|
||||||
|
% if (strcmp(TagName, 'CONTENT'))
|
||||||
|
% while (iscell(s) && length(s)==1), s = s{1}; end % unwrap cell arrays of length 1
|
||||||
|
% end
|
||||||
|
TagName = varName2str(TagName);
|
||||||
|
|
||||||
|
%% == node is a 2D cell array ==
|
||||||
|
% convert to some other format prior to further processing
|
||||||
|
nDim = nnz(size(s)>1); % is it a scalar, vector, 2D array, 3D cube, etc?
|
||||||
|
if (iscell(s) && nDim==2 && strcmpi(Pref.CellTable, 'Matlab'))
|
||||||
|
s = var2str(s, Pref.PreserveSpace);
|
||||||
|
end
|
||||||
|
if (nDim==2 && (iscell (s) && strcmpi(Pref.CellTable, 'Vector')) || ...
|
||||||
|
(isstruct(s) && strcmpi(Pref.StructTable, 'Vector')))
|
||||||
|
s = s(:);
|
||||||
|
end
|
||||||
|
if (nDim>2), s = s(:); end % can not handle this case well
|
||||||
|
nItem = numel(s);
|
||||||
|
nDim = nnz(size(s)>1); % is it a scalar, vector, 2D array, 3D cube, etc?
|
||||||
|
|
||||||
|
%% == node is a cell ==
|
||||||
|
if (iscell(s)) % if this is a cell or cell array
|
||||||
|
if ((nDim==2 && strcmpi(Pref.CellTable,'Html')) || (nDim< 2 && Pref.CellItem))
|
||||||
|
% if 2D array of cells than can use HTML-like notation or if 1D array
|
||||||
|
% than can use item notation
|
||||||
|
if (strcmp(TagName, 'CONTENT')) % CONTENT nodes already have <TagName> ... </TagName>
|
||||||
|
array2DOMnode(xml, parent, s, Pref.ItemName, Pref ); % recursive call
|
||||||
|
else
|
||||||
|
node = xml.createElement(TagName); % <TagName> ... </TagName>
|
||||||
|
array2DOMnode(xml, node, s, Pref.ItemName, Pref ); % recursive call
|
||||||
|
parent.appendChild(node);
|
||||||
|
end
|
||||||
|
else % use <TagName>...<\TagName> <TagName>...<\TagName> notation
|
||||||
|
array2DOMnode(xml, parent, s, TagName, Pref ); % recursive call
|
||||||
|
end
|
||||||
|
%% == node is a struct ==
|
||||||
|
elseif (isstruct(s)) % if struct than deal with each field separatly
|
||||||
|
if ((nDim==2 && strcmpi(Pref.StructTable,'Html')) || (nItem>1 && Pref.StructItem))
|
||||||
|
% if 2D array of structs than can use HTML-like notation or
|
||||||
|
% if 1D array of structs than can use 'items' notation
|
||||||
|
node = xml.createElement(TagName);
|
||||||
|
array2DOMnode(xml, node, s, Pref.ItemName, Pref ); % recursive call
|
||||||
|
parent.appendChild(node);
|
||||||
|
elseif (nItem>1) % use <TagName>...<\TagName> <TagName>...<\TagName> notation
|
||||||
|
array2DOMnode(xml, parent, s, TagName, Pref ); % recursive call
|
||||||
|
else % otherwise save each struct separatelly
|
||||||
|
fields = fieldnames(s);
|
||||||
|
node = xml.createElement(TagName);
|
||||||
|
for i=1:length(fields) % add field by field to the node
|
||||||
|
field = fields{i};
|
||||||
|
x = s.(field);
|
||||||
|
switch field
|
||||||
|
case {'COMMENT', 'CDATA_SECTION', 'PROCESSING_INSTRUCTION'}
|
||||||
|
if iscellstr(x) % cell array of strings -> add them one by one
|
||||||
|
array2DOMnode(xml, node, x(:), field, Pref ); % recursive call will modify 'node'
|
||||||
|
elseif ischar(x) % single string -> add it
|
||||||
|
struct2DOMnode(xml, node, x, field, Pref ); % recursive call will modify 'node'
|
||||||
|
else % not a string - Ignore
|
||||||
|
warning('xml_io_tools:write:badSpecialNode', ...
|
||||||
|
['Struct field named ',field,' encountered which was not a string. Ignoring.']);
|
||||||
|
end
|
||||||
|
case 'ATTRIBUTE' % set attributes of the node
|
||||||
|
if (isempty(x)), continue; end
|
||||||
|
if (isstruct(x))
|
||||||
|
attName = fieldnames(x); % get names of all the attributes
|
||||||
|
for k=1:length(attName) % attach them to the node
|
||||||
|
att = xml.createAttribute(varName2str(attName(k)));
|
||||||
|
att.setValue(var2str(x.(attName{k}),Pref.PreserveSpace));
|
||||||
|
node.setAttributeNode(att);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
warning('xml_io_tools:write:badAttribute', ...
|
||||||
|
'Struct field named ATTRIBUTE encountered which was not a struct. Ignoring.');
|
||||||
|
end
|
||||||
|
otherwise % set children of the node
|
||||||
|
struct2DOMnode(xml, node, x, field, Pref ); % recursive call will modify 'node'
|
||||||
|
end
|
||||||
|
end % end for i=1:nFields
|
||||||
|
parent.appendChild(node);
|
||||||
|
end
|
||||||
|
%% == node is a leaf node ==
|
||||||
|
else % if not a struct and not a cell than it is a leaf node
|
||||||
|
switch TagName % different processing depending on desired type of the node
|
||||||
|
case 'COMMENT' % create comment node
|
||||||
|
com = xml.createComment(s);
|
||||||
|
parent.appendChild(com);
|
||||||
|
case 'CDATA_SECTION' % create CDATA Section
|
||||||
|
cdt = xml.createCDATASection(s);
|
||||||
|
parent.appendChild(cdt);
|
||||||
|
case 'PROCESSING_INSTRUCTION' % set attributes of the node
|
||||||
|
OK = false;
|
||||||
|
if (ischar(s))
|
||||||
|
n = strfind(s, ' ');
|
||||||
|
if (~isempty(n))
|
||||||
|
proc = xml.createProcessingInstruction(s(1:(n(1)-1)),s((n(1)+1):end));
|
||||||
|
parent.insertBefore(proc, parent.getFirstChild());
|
||||||
|
OK = true;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (~OK)
|
||||||
|
warning('xml_io_tools:write:badProcInst', ...
|
||||||
|
['Struct field named PROCESSING_INSTRUCTION need to be',...
|
||||||
|
' a string, for example: xml-stylesheet type="text/css" ', ...
|
||||||
|
'href="myStyleSheet.css". Ignoring.']);
|
||||||
|
end
|
||||||
|
case 'CONTENT' % this is text part of already existing node
|
||||||
|
txt = xml.createTextNode(var2str(s, Pref.PreserveSpace)); % convert to text
|
||||||
|
parent.appendChild(txt);
|
||||||
|
otherwise % I guess it is a regular text leaf node
|
||||||
|
txt = xml.createTextNode(var2str(s, Pref.PreserveSpace));
|
||||||
|
node = xml.createElement(TagName);
|
||||||
|
node.appendChild(txt);
|
||||||
|
parent.appendChild(node);
|
||||||
|
end
|
||||||
|
end % of struct2DOMnode function
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === array2DOMnode Function ============================================
|
||||||
|
% =======================================================================
|
||||||
|
function [] = array2DOMnode(xml, parent, s, TagName, Pref)
|
||||||
|
% Deal with 1D and 2D arrays of cell or struct. Will modify 'parent'.
|
||||||
|
nDim = nnz(size(s)>1); % is it a scalar, vector, 2D array, 3D cube, etc?
|
||||||
|
switch nDim
|
||||||
|
case 2 % 2D array
|
||||||
|
for r=1:size(s,1)
|
||||||
|
subnode = xml.createElement(Pref.TableName{1});
|
||||||
|
for c=1:size(s,2)
|
||||||
|
v = s(r,c);
|
||||||
|
if iscell(v), v = v{1}; end
|
||||||
|
struct2DOMnode(xml, subnode, v, Pref.TableName{2}, Pref ); % recursive call
|
||||||
|
end
|
||||||
|
parent.appendChild(subnode);
|
||||||
|
end
|
||||||
|
case 1 %1D array
|
||||||
|
for iItem=1:numel(s)
|
||||||
|
v = s(iItem);
|
||||||
|
if iscell(v), v = v{1}; end
|
||||||
|
struct2DOMnode(xml, parent, v, TagName, Pref ); % recursive call
|
||||||
|
end
|
||||||
|
case 0 % scalar -> this case should never be called
|
||||||
|
if ~isempty(s)
|
||||||
|
if iscell(s), s = s{1}; end
|
||||||
|
struct2DOMnode(xml, parent, s, TagName, Pref );
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === var2str Function ==================================================
|
||||||
|
% =======================================================================
|
||||||
|
function str = var2str(object, PreserveSpace)
|
||||||
|
% convert matlab variables to a string
|
||||||
|
switch (1)
|
||||||
|
case isempty(object)
|
||||||
|
str = '';
|
||||||
|
case (isnumeric(object) || islogical(object))
|
||||||
|
if ndims(object)>2, object=object(:); end % can't handle arrays with dimention > 2
|
||||||
|
str=mat2str(object); % convert matrix to a string
|
||||||
|
% mark logical scalars with [] (logical arrays already have them) so the xml_read
|
||||||
|
% recognizes them as MATLAB objects instead of strings. Same with sparse
|
||||||
|
% matrices
|
||||||
|
if ((islogical(object) && isscalar(object)) || issparse(object)),
|
||||||
|
str = ['[' str ']'];
|
||||||
|
end
|
||||||
|
if (isinteger(object)),
|
||||||
|
str = ['[', class(object), '(', str ')]'];
|
||||||
|
end
|
||||||
|
case iscell(object)
|
||||||
|
if ndims(object)>2, object=object(:); end % can't handle cell arrays with dimention > 2
|
||||||
|
[nr nc] = size(object);
|
||||||
|
obj2 = object;
|
||||||
|
for i=1:length(object(:))
|
||||||
|
str = var2str(object{i}, PreserveSpace);
|
||||||
|
if (ischar(object{i})), object{i} = ['''' object{i} '''']; else object{i}=str; end
|
||||||
|
obj2{i} = [object{i} ','];
|
||||||
|
end
|
||||||
|
for r = 1:nr, obj2{r,nc} = [object{r,nc} ';']; end
|
||||||
|
obj2 = obj2.';
|
||||||
|
str = ['{' obj2{:} '}'];
|
||||||
|
case isstruct(object)
|
||||||
|
str='';
|
||||||
|
warning('xml_io_tools:write:var2str', ...
|
||||||
|
'Struct was encountered where string was expected. Ignoring.');
|
||||||
|
case isa(object, 'function_handle')
|
||||||
|
str = ['[@' char(object) ']'];
|
||||||
|
case ischar(object)
|
||||||
|
str = object;
|
||||||
|
otherwise
|
||||||
|
str = char(object);
|
||||||
|
end
|
||||||
|
|
||||||
|
%% string clean-up
|
||||||
|
str=str(:); str=str.'; % make sure this is a row vector of char's
|
||||||
|
if (~isempty(str))
|
||||||
|
str(str<32|str==127)=' '; % convert no-printable characters to spaces
|
||||||
|
if (~PreserveSpace)
|
||||||
|
str = strtrim(str); % remove spaces from begining and the end
|
||||||
|
str = regexprep(str,'\s+',' '); % remove multiple spaces
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% =======================================================================
|
||||||
|
% === var2Namestr Function ==============================================
|
||||||
|
% =======================================================================
|
||||||
|
function str = varName2str(str)
|
||||||
|
% convert matlab variable names to a sting
|
||||||
|
str = char(str);
|
||||||
|
p = strfind(str,'0x');
|
||||||
|
if (~isempty(p))
|
||||||
|
for i=1:length(p)
|
||||||
|
before = str( p(i)+(0:3) ); % string to replace
|
||||||
|
after = char(hex2dec(before(3:4))); % string to replace with
|
||||||
|
str = regexprep(str,before,after, 'once', 'ignorecase');
|
||||||
|
p=p-3; % since 4 characters were replaced with one - compensate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
str = regexprep(str,'_COLON_',':', 'once', 'ignorecase');
|
||||||
|
str = regexprep(str,'_DASH_' ,'-', 'once', 'ignorecase');
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
function varargout=xmlwrite_xerces(varargin)
|
||||||
|
%XMLWRITE_XERCES Serialize an XML Document Object Model node using Xerces parser.
|
||||||
|
% xmlwrite_xerces(FILENAME,DOMNODE) serializes the DOMNODE to file FILENAME.
|
||||||
|
%
|
||||||
|
% The function xmlwrite_xerces is very similar the Matlab function xmlwrite
|
||||||
|
% but works directly with the XERCES java classes (written by Apache XML
|
||||||
|
% Project) instead of the XMLUtils class created by Mathworks. Xerces files
|
||||||
|
% are provided in standard MATLAB instalation and live in root\java\jarext
|
||||||
|
% directory.
|
||||||
|
%
|
||||||
|
% Written by A.Amaro (02-22-2007) and generously donated to xml_io_tools.
|
||||||
|
% This function is needed as a work-around for a bug in XMLUtils library
|
||||||
|
% which can not write CDATA SECTION nodes correctly. Also Xerces and
|
||||||
|
% XMLUtils libraries handle namespaces differently.
|
||||||
|
%
|
||||||
|
% Examples:
|
||||||
|
% % See xmlwrite examples this function have almost identical behavior.
|
||||||
|
%
|
||||||
|
% Advanced use:
|
||||||
|
% FILENAME can also be a URN, java.io.OutputStream or java.io.Writer object
|
||||||
|
% SOURCE can also be a SAX InputSource, JAXP Source, InputStream, or
|
||||||
|
% Reader object
|
||||||
|
|
||||||
|
returnString = false;
|
||||||
|
if length(varargin)==1
|
||||||
|
returnString = true;
|
||||||
|
result = java.io.StringWriter;
|
||||||
|
source = varargin{1};
|
||||||
|
else
|
||||||
|
result = varargin{1};
|
||||||
|
if ischar(result)
|
||||||
|
% Using the XERCES classes directly, is not needed to modify the
|
||||||
|
% filename string. So I have commented this next line
|
||||||
|
% result = F_xmlstringinput(result,false);
|
||||||
|
end
|
||||||
|
|
||||||
|
source = varargin{2};
|
||||||
|
if ischar(source)
|
||||||
|
source = F_xmlstringinput(source,true);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% SERIALIZATION OF THE DOM DOCUMENT USING XERCES CLASSES DIRECTLY
|
||||||
|
|
||||||
|
% 1) create the output format according to the document definitions
|
||||||
|
% and type
|
||||||
|
objOutputFormat = org.apache.xml.serialize.OutputFormat(source);
|
||||||
|
set(objOutputFormat,'Indenting','on');
|
||||||
|
|
||||||
|
% 2) create the output stream. In this case: an XML file
|
||||||
|
objFile = java.io.File(result);
|
||||||
|
objOutputStream = java.io.FileOutputStream(objFile);
|
||||||
|
|
||||||
|
% 3) Create the Xerces Serializer object
|
||||||
|
objSerializer= org.apache.xml.serialize.XMLSerializer(objOutputStream,objOutputFormat);
|
||||||
|
|
||||||
|
% 4) Serialize to the XML files
|
||||||
|
javaMethod('serialize',objSerializer,source);
|
||||||
|
|
||||||
|
% 5) IMPORTANT! Delete the objects to liberate the XML file created
|
||||||
|
objOutputStream.close;
|
||||||
|
|
||||||
|
if returnString
|
||||||
|
varargout{1}=char(result.toString);
|
||||||
|
end
|
||||||
|
|
||||||
|
%% ========================================================================
|
||||||
|
function out = F_xmlstringinput(xString,isFullSearch,varargin)
|
||||||
|
% The function F_xmlstringinput is a copy of the private function:
|
||||||
|
% 'xmlstringinput' that the original xmlwrite function uses.
|
||||||
|
|
||||||
|
if isempty(xString)
|
||||||
|
error('Filename is empty');
|
||||||
|
elseif ~isempty(findstr(xString,'://'))
|
||||||
|
%xString is already a URL, most likely prefaced by file:// or http://
|
||||||
|
out = xString;
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
xPath=fileparts(xString);
|
||||||
|
if isempty(xPath)
|
||||||
|
if nargin<2 || isFullSearch
|
||||||
|
out = which(xString);
|
||||||
|
if isempty(out)
|
||||||
|
error('xml:FileNotFound','File %s not found',xString);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
out = fullfile(pwd,xString);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
out = xString;
|
||||||
|
if (nargin<2 || isFullSearch) && ~exist(xString,'file')
|
||||||
|
%search to see if xString exists when isFullSearch
|
||||||
|
error('xml:FileNotFound','File %s not found',xString);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%Return as a URN
|
||||||
|
if strncmp(out,'\\',2)
|
||||||
|
% SAXON UNC filepaths need to look like file:///\\\server-name\
|
||||||
|
out = ['file:///\',out];
|
||||||
|
elseif strncmp(out,'/',1)
|
||||||
|
% SAXON UNIX filepaths need to look like file:///root/dir/dir
|
||||||
|
out = ['file://',out];
|
||||||
|
else
|
||||||
|
% DOS filepaths need to look like file:///d:/foo/bar
|
||||||
|
out = ['file:///',strrep(out,'\','/')];
|
||||||
|
end
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
AU1 results - corr 0.825, rms 0.413, ccc - 0.803
|
AU1 results - corr 0.825, rms 0.414, ccc - 0.802
|
||||||
AU2 results - corr 0.765, rms 0.444, ccc - 0.659
|
AU2 results - corr 0.766, rms 0.443, ccc - 0.661
|
||||||
AU4 results - corr 0.863, rms 0.583, ccc - 0.838
|
AU4 results - corr 0.874, rms 0.562, ccc - 0.849
|
||||||
AU5 results - corr 0.749, rms 0.179, ccc - 0.717
|
AU5 results - corr 0.742, rms 0.182, ccc - 0.714
|
||||||
AU6 results - corr 0.702, rms 0.604, ccc - 0.657
|
AU6 results - corr 0.701, rms 0.610, ccc - 0.655
|
||||||
AU9 results - corr 0.742, rms 0.384, ccc - 0.689
|
AU9 results - corr 0.743, rms 0.383, ccc - 0.692
|
||||||
AU12 results - corr 0.865, rms 0.510, ccc - 0.850
|
AU12 results - corr 0.867, rms 0.506, ccc - 0.853
|
||||||
AU15 results - corr 0.747, rms 0.268, ccc - 0.714
|
AU15 results - corr 0.744, rms 0.271, ccc - 0.716
|
||||||
AU17 results - corr 0.646, rms 0.515, ccc - 0.578
|
AU17 results - corr 0.645, rms 0.520, ccc - 0.578
|
||||||
AU20 results - corr 0.637, rms 0.304, ccc - 0.595
|
AU20 results - corr 0.622, rms 0.311, ccc - 0.586
|
||||||
AU25 results - corr 0.926, rms 0.499, ccc - 0.920
|
AU25 results - corr 0.926, rms 0.501, ccc - 0.919
|
||||||
AU26 results - corr 0.805, rms 0.447, ccc - 0.764
|
AU26 results - corr 0.805, rms 0.447, ccc - 0.765
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
AU1 class, Precision - 0.588, Recall - 0.708, F1 - 0.643
|
AU1 class, Precision - 0.594, Recall - 0.643, F1 - 0.617
|
||||||
AU2 class, Precision - 0.473, Recall - 0.749, F1 - 0.580
|
AU2 class, Precision - 0.474, Recall - 0.779, F1 - 0.590
|
||||||
AU4 class, Precision - 0.509, Recall - 0.745, F1 - 0.605
|
AU4 class, Precision - 0.519, Recall - 0.727, F1 - 0.605
|
||||||
AU6 class, Precision - 0.834, Recall - 0.667, F1 - 0.741
|
AU6 class, Precision - 0.809, Recall - 0.669, F1 - 0.732
|
||||||
AU7 class, Precision - 0.685, Recall - 0.792, F1 - 0.735
|
AU7 class, Precision - 0.682, Recall - 0.795, F1 - 0.734
|
||||||
AU10 class, Precision - 0.520, Recall - 0.737, F1 - 0.610
|
AU10 class, Precision - 0.501, Recall - 0.786, F1 - 0.612
|
||||||
AU12 class, Precision - 0.919, Recall - 0.654, F1 - 0.764
|
AU12 class, Precision - 0.920, Recall - 0.659, F1 - 0.768
|
||||||
AU15 class, Precision - 0.362, Recall - 0.634, F1 - 0.461
|
AU15 class, Precision - 0.329, Recall - 0.724, F1 - 0.453
|
||||||
AU17 class, Precision - 0.230, Recall - 0.279, F1 - 0.252
|
AU17 class, Precision - 0.238, Recall - 0.313, F1 - 0.270
|
||||||
AU25 class, Precision - 0.205, Recall - 0.871, F1 - 0.332
|
AU25 class, Precision - 0.197, Recall - 0.900, F1 - 0.324
|
||||||
AU26 class, Precision - 0.122, Recall - 0.974, F1 - 0.217
|
AU26 class, Precision - 0.120, Recall - 0.986, F1 - 0.213
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
AU2 class, Precision - 0.369, Recall - 0.744, F1 - 0.493
|
AU2 class, Precision - 0.368, Recall - 0.743, F1 - 0.492
|
||||||
AU12 class, Precision - 0.427, Recall - 0.782, F1 - 0.553
|
AU12 class, Precision - 0.427, Recall - 0.781, F1 - 0.553
|
||||||
AU17 class, Precision - 0.126, Recall - 0.815, F1 - 0.219
|
AU17 class, Precision - 0.125, Recall - 0.813, F1 - 0.217
|
||||||
AU25 class, Precision - 0.344, Recall - 0.574, F1 - 0.430
|
AU25 class, Precision - 0.345, Recall - 0.576, F1 - 0.431
|
||||||
AU28 class, Precision - 0.486, Recall - 0.475, F1 - 0.481
|
AU28 class, Precision - 0.491, Recall - 0.480, F1 - 0.486
|
||||||
AU45 class, Precision - 0.289, Recall - 0.621, F1 - 0.394
|
AU45 class, Precision - 0.289, Recall - 0.621, F1 - 0.394
|
||||||
|
|
|
@ -1,6 +1,17 @@
|
||||||
clear
|
clear
|
||||||
DISFA_dir = 'D:/Datasets/DISFA/Videos_LeftCamera/';
|
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
|
if(exist('D:/Datasets/DISFA/Videos_LeftCamera/', 'file'))
|
||||||
|
DISFA_dir = 'D:/Datasets/DISFA/Videos_LeftCamera/';
|
||||||
|
else
|
||||||
|
DISFA_dir = '/multicomp/datasets/face_datasets/DISFA/Videos_LeftCamera/';
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
videos = dir([DISFA_dir, '*.avi']);
|
videos = dir([DISFA_dir, '*.avi']);
|
||||||
|
|
||||||
|
@ -22,7 +33,11 @@ parfor v = 1:numel(videos)
|
||||||
output_file = [output name '_au.txt'];
|
output_file = [output name '_au.txt'];
|
||||||
command = [executable ' -f "' vid_file '" -of "' output_file '" -q -no2Dfp -no3Dfp -noMparams -noPose -noGaze'];
|
command = [executable ' -f "' vid_file '" -of "' output_file '" -q -no2Dfp -no3Dfp -noMparams -noPose -noGaze'];
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command, '-echo');
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -31,8 +46,7 @@ end
|
||||||
% Note that DISFA was used in training, this is not meant for experimental
|
% Note that DISFA was used in training, this is not meant for experimental
|
||||||
% results but rather to show how to do AU prediction and how to interpret
|
% results but rather to show how to do AU prediction and how to interpret
|
||||||
% the results
|
% the results
|
||||||
|
Label_dir = [DISFA_dir, '/../ActionUnit_Labels/'];
|
||||||
Label_dir = 'D:/Datasets/DISFA/ActionUnit_Labels/';
|
|
||||||
prediction_dir = 'out_DISFA/';
|
prediction_dir = 'out_DISFA/';
|
||||||
|
|
||||||
label_folders = dir([Label_dir, 'SN*']);
|
label_folders = dir([Label_dir, 'SN*']);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
clear
|
clear
|
||||||
|
|
||||||
fera_loc = 'D:\Datasets\fera\';
|
addpath(genpath('helpers/'));
|
||||||
|
find_FERA2011;
|
||||||
|
|
||||||
out_loc = './out_fera/';
|
out_loc = './out_fera/';
|
||||||
|
|
||||||
|
@ -9,41 +10,38 @@ if(~exist(out_loc, 'dir'))
|
||||||
end
|
end
|
||||||
|
|
||||||
%%
|
%%
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
fera_dirs = dir([fera_loc, 'au_train*']);
|
fera_dirs = dir([FERA2011_dir, 'train*']);
|
||||||
|
|
||||||
for f1=1:numel(fera_dirs)
|
parfor f1=1:numel(fera_dirs)
|
||||||
|
|
||||||
fera_dirs_level_2 = dir([fera_loc, fera_dirs(f1).name]);
|
vid_files = dir([FERA2011_dir, fera_dirs(f1).name, '/*.avi']);
|
||||||
fera_dirs_level_2 = fera_dirs_level_2(3:end);
|
|
||||||
|
|
||||||
parfor f2=1:numel(fera_dirs_level_2)
|
for v=1:numel(vid_files)
|
||||||
|
|
||||||
vid_files = dir([fera_loc, fera_dirs(f1).name, '/', fera_dirs_level_2(f2).name, '/*.avi']);
|
command = [executable ' -asvid -q -no2Dfp -no3Dfp -noMparams -noPose -noGaze -au_static '];
|
||||||
|
|
||||||
for v=1:numel(vid_files)
|
curr_vid = [FERA2011_dir, fera_dirs(f1).name, '/', vid_files(v).name];
|
||||||
|
|
||||||
command = [executable ' -asvid -q -no2Dfp -no3Dfp -noMparams -noPose -noGaze -au_static '];
|
[~,name,~] = fileparts(curr_vid);
|
||||||
|
output_file = [out_loc name '.au.txt'];
|
||||||
curr_vid = [fera_loc, fera_dirs(f1).name, '/', fera_dirs_level_2(f2).name, '/', vid_files(v).name];
|
|
||||||
|
|
||||||
[~,name,~] = fileparts(curr_vid);
|
|
||||||
output_file = [out_loc name '.au.txt'];
|
|
||||||
|
|
||||||
command = cat(2, command, [' -f "' curr_vid '" -of "' output_file '"']);
|
|
||||||
|
|
||||||
|
command = cat(2, command, [' -f "' curr_vid '" -of "' output_file '"']);
|
||||||
|
|
||||||
|
if(isunix)
|
||||||
|
unix(command, '-echo');
|
||||||
|
else
|
||||||
dos(command);
|
dos(command);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
%%
|
%%
|
||||||
addpath('./helpers/');
|
|
||||||
|
|
||||||
find_FERA2011;
|
|
||||||
|
|
||||||
[ labels_gt, valid_ids, filenames] = extract_FERA2011_labels(FERA2011_dir, all_recs, all_aus);
|
[ labels_gt, valid_ids, filenames] = extract_FERA2011_labels(FERA2011_dir, all_recs, all_aus);
|
||||||
labels_gt = cat(1, labels_gt{:});
|
labels_gt = cat(1, labels_gt{:});
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,11 @@ if(~exist(out_loc, 'dir'))
|
||||||
mkdir(out_loc);
|
mkdir(out_loc);
|
||||||
end
|
end
|
||||||
|
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
%%
|
%%
|
||||||
parfor f1=1:numel(devel_recs)
|
parfor f1=1:numel(devel_recs)
|
||||||
|
|
||||||
|
@ -27,8 +31,13 @@ parfor f1=1:numel(devel_recs)
|
||||||
name = f1_dir;
|
name = f1_dir;
|
||||||
output_aus = [out_loc name '.au.txt'];
|
output_aus = [out_loc name '.au.txt'];
|
||||||
|
|
||||||
command = cat(2, command, [' -f "' curr_vid '" -of "' output_aus]);
|
command = cat(2, command, [' -f "' curr_vid '" -of "' output_aus, '"']);
|
||||||
dos(command);
|
|
||||||
|
if(isunix)
|
||||||
|
unix(command, '-echo');
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
clear
|
||||||
|
|
||||||
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
output = './output_features_seq/';
|
output = './output_features_seq/';
|
||||||
|
|
||||||
|
@ -33,7 +39,11 @@ for i=1:numel(in_dirs)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command);
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
|
|
||||||
%% Demonstrating reading the output files
|
%% Demonstrating reading the output files
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
clear
|
||||||
|
|
||||||
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
output = './output_features_vid/';
|
output = './output_features_vid/';
|
||||||
|
|
||||||
|
@ -40,7 +46,11 @@ for i=1:numel(in_files)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command);
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
|
|
||||||
%% Demonstrating reading the output files
|
%% Demonstrating reading the output files
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
exe = '"../../x64/Release/FeatureExtraction.exe"';
|
clear
|
||||||
|
|
||||||
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
output = './output_features_vid/';
|
output = './output_features_vid/';
|
||||||
|
|
||||||
|
@ -10,7 +16,7 @@ in_files = dir('../../videos/2015-10-15-15-14.avi');
|
||||||
% some parameters
|
% some parameters
|
||||||
verbose = true;
|
verbose = true;
|
||||||
|
|
||||||
command = exe;
|
command = executable;
|
||||||
command = cat(2, command, ' -verbose -no2Dfp -no3Dfp -noMparams -noPose -noAUs ');
|
command = cat(2, command, ' -verbose -no2Dfp -no3Dfp -noMparams -noPose -noAUs ');
|
||||||
|
|
||||||
% add all videos to single argument list (so as not to load the model anew
|
% add all videos to single argument list (so as not to load the model anew
|
||||||
|
@ -31,7 +37,11 @@ for i=1:numel(in_files)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command);
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
|
|
||||||
%% Demonstrating reading the output files
|
%% Demonstrating reading the output files
|
||||||
filename = [output name];
|
filename = [output name];
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
clear
|
clear
|
||||||
|
if(isunix)
|
||||||
executable = '"../../x64/Release/FaceLandmarkImg.exe"';
|
executable = '"../../build/bin/FaceLandmarkImg"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FaceLandmarkImg.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
in_dir = '../../videos/';
|
in_dir = '../../videos/';
|
||||||
out_dir = './demo_img/';
|
out_dir = './demo_img/';
|
||||||
|
@ -38,4 +41,8 @@ command = cat(2, command, [' -mloc "', model, '"']);
|
||||||
% Comment to skip this functionality
|
% Comment to skip this functionality
|
||||||
command = cat(2, command, ' -wild ');
|
command = cat(2, command, ' -wild ');
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command);
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
|
@ -1,4 +1,10 @@
|
||||||
executable = '"../../x64/Release/FaceLandmarkVidMulti.exe"';
|
clear;
|
||||||
|
|
||||||
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FaceLandmarkVidMulti"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FaceLandmarkVidMulti.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
output = './demo_vid/';
|
output = './demo_vid/';
|
||||||
|
|
||||||
|
@ -38,4 +44,8 @@ for i=1:numel(in_files)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command);
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
|
@ -1,4 +1,10 @@
|
||||||
executable = '"../../x64/Release/FaceLandmarkVid.exe"';
|
clear
|
||||||
|
|
||||||
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FaceLandmarkVid"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FaceLandmarkVid.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
output = './demo_vid/';
|
output = './demo_vid/';
|
||||||
|
|
||||||
|
@ -39,4 +45,8 @@ for i=1:numel(in_files)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command);
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
|
@ -1,6 +1,4 @@
|
||||||
function [ err_outline, err_no_outline ] = Run_CLM_fitting_on_images(output_loc, database_root, varargin)
|
function [ err_outline, err_no_outline ] = Run_OF_on_images(output_loc, database_root, varargin)
|
||||||
%RUN_CLM_FITTING_ON_IMAGES Summary of this function goes here
|
|
||||||
% Detailed explanation goes here
|
|
||||||
|
|
||||||
dataset_dirs = {};
|
dataset_dirs = {};
|
||||||
|
|
||||||
|
@ -27,7 +25,11 @@ else
|
||||||
verbose = false;
|
verbose = false;
|
||||||
end
|
end
|
||||||
|
|
||||||
command = '"../../x64/Release/FaceLandmarkImg.exe" ';
|
if(isunix)
|
||||||
|
command = '"../../build/bin/FaceLandmarkImg"';
|
||||||
|
else
|
||||||
|
command = '"../../x64/Release/FaceLandmarkImg.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
if(any(strcmp(varargin, 'model')))
|
if(any(strcmp(varargin, 'model')))
|
||||||
model = varargin{find(strcmp(varargin, 'model')) + 1};
|
model = varargin{find(strcmp(varargin, 'model')) + 1};
|
||||||
|
@ -61,7 +63,11 @@ parfor i=1:numel(dataset_dirs)
|
||||||
|
|
||||||
command_c = cat(2, command_c, ' -wild ');
|
command_c = cat(2, command_c, ' -wild ');
|
||||||
|
|
||||||
dos(command_c);
|
if(isunix)
|
||||||
|
unix(command_c, '-echo');
|
||||||
|
else
|
||||||
|
dos(command_c);
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
toc
|
toc
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,9 +1,9 @@
|
||||||
Type, mean, median
|
Type, mean, median
|
||||||
err clnf: 0.054348, 0.040034
|
err clnf: 0.054324, 0.040026
|
||||||
err clnf wild: 0.053107, 0.038525
|
err clnf wild: 0.053219, 0.038420
|
||||||
err svr: 0.070552, 0.050640
|
err svr: 0.070549, 0.050548
|
||||||
err svr wild: 0.067452, 0.048706
|
err svr wild: 0.067546, 0.048649
|
||||||
err clnf no out: 0.043081, 0.029782
|
err clnf no out: 0.043100, 0.029728
|
||||||
err clnf wild no out: 0.041386, 0.027463
|
err clnf wild no out: 0.041522, 0.027565
|
||||||
err svr no out: 0.058766, 0.038836
|
err svr no out: 0.058712, 0.038792
|
||||||
err svr wild no out: 0.054020, 0.036252
|
err svr wild no out: 0.054168, 0.036232
|
||||||
|
|
|
@ -5,8 +5,10 @@ curr_dir = cd('.');
|
||||||
% Replace this with your downloaded 300-W train data
|
% Replace this with your downloaded 300-W train data
|
||||||
if(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
if(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
||||||
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
||||||
else
|
elseif(exist('D:/Dropbox/Dropbox/AAM/test data/', 'file'))
|
||||||
database_root = 'D:/Dropbox/Dropbox/AAM/test data/';
|
database_root = 'D:/Dropbox/Dropbox/AAM/test data/';
|
||||||
|
else
|
||||||
|
database_root = '/multicomp/datasets/300-W/';
|
||||||
end
|
end
|
||||||
|
|
||||||
%% Run using CLNF in the wild model
|
%% Run using CLNF in the wild model
|
||||||
|
@ -15,7 +17,7 @@ if(~exist(out_clnf, 'file'))
|
||||||
mkdir(out_clnf);
|
mkdir(out_clnf);
|
||||||
end
|
end
|
||||||
|
|
||||||
[err_clnf_wild, err_no_out_clnf_wild] = Run_CLM_fitting_on_images(out_clnf, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clnf_wild.txt', 'multi_view', 1);
|
[err_clnf_wild, err_no_out_clnf_wild] = Run_OF_on_images(out_clnf, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clnf_wild.txt', 'multi_view', 1);
|
||||||
|
|
||||||
%% Run using SVR model
|
%% Run using SVR model
|
||||||
out_svr = [curr_dir '/out_wild_svr_wild/'];
|
out_svr = [curr_dir '/out_wild_svr_wild/'];
|
||||||
|
@ -23,7 +25,7 @@ if(~exist(out_svr, 'file'))
|
||||||
mkdir(out_svr);
|
mkdir(out_svr);
|
||||||
end
|
end
|
||||||
|
|
||||||
[err_svr_wild, err_no_out_svr_wild] = Run_CLM_fitting_on_images(out_svr, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clm_wild.txt', 'multi_view', 1);
|
[err_svr_wild, err_no_out_svr_wild] = Run_OF_on_images(out_svr, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clm_wild.txt', 'multi_view', 1);
|
||||||
|
|
||||||
%% Run using general CLNF model
|
%% Run using general CLNF model
|
||||||
out_clnf = [curr_dir '/out_wild_clnf/'];
|
out_clnf = [curr_dir '/out_wild_clnf/'];
|
||||||
|
@ -31,7 +33,7 @@ if(~exist(out_clnf, 'file'))
|
||||||
mkdir(out_clnf);
|
mkdir(out_clnf);
|
||||||
end
|
end
|
||||||
|
|
||||||
[err_clnf, err_no_out_clnf] = Run_CLM_fitting_on_images(out_clnf, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clnf_general.txt', 'multi_view', 1);
|
[err_clnf, err_no_out_clnf] = Run_OF_on_images(out_clnf, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clnf_general.txt', 'multi_view', 1);
|
||||||
|
|
||||||
%% Run using SVR model
|
%% Run using SVR model
|
||||||
out_svr = [curr_dir '/out_wild_svr/'];
|
out_svr = [curr_dir '/out_wild_svr/'];
|
||||||
|
@ -39,7 +41,7 @@ if(~exist(out_svr, 'file'))
|
||||||
mkdir(out_svr);
|
mkdir(out_svr);
|
||||||
end
|
end
|
||||||
|
|
||||||
[err_svr, err_no_out_svr] = Run_CLM_fitting_on_images(out_svr, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clm_general.txt', 'multi_view', 1);
|
[err_svr, err_no_out_svr] = Run_OF_on_images(out_svr, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clm_general.txt', 'multi_view', 1);
|
||||||
|
|
||||||
%%
|
%%
|
||||||
save('results/landmark_detections.mat');
|
save('results/landmark_detections.mat');
|
|
@ -1,6 +1,10 @@
|
||||||
clear
|
clear
|
||||||
|
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
output = 'yt_features/';
|
output = 'yt_features/';
|
||||||
|
|
||||||
|
@ -10,11 +14,13 @@ end
|
||||||
|
|
||||||
if(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
if(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
||||||
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
||||||
else
|
elseif(exist([getenv('USERPROFILE') 'D:/Dropbox/Dropbox/AAM/test data/'], 'file'))
|
||||||
database_root = 'D:/Dropbox/Dropbox/AAM/test data/';
|
database_root = 'D:/Dropbox/Dropbox/AAM/test data/';
|
||||||
|
else
|
||||||
|
database_root = '/multicomp/datasets/';
|
||||||
end
|
end
|
||||||
|
|
||||||
database_root = [database_root, '/ytceleb_annotations_CVPR2014/'];
|
database_root = [database_root, '/ytceleb/'];
|
||||||
|
|
||||||
in_vids = dir([database_root '/*.avi']);
|
in_vids = dir([database_root '/*.avi']);
|
||||||
|
|
||||||
|
@ -33,7 +39,11 @@ for i=1:numel(in_vids)
|
||||||
command = cat(2, command, [' -f "' in_file_name '" -of "' outputFile_fp '"']);
|
command = cat(2, command, [' -f "' in_file_name '" -of "' outputFile_fp '"']);
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command, '-echo')
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
|
|
||||||
%%
|
%%
|
||||||
output = 'yt_features_clm/';
|
output = 'yt_features_clm/';
|
||||||
|
@ -59,7 +69,11 @@ for i=1:numel(in_vids)
|
||||||
command = cat(2, command, [' -f "' in_file_name '" -of "' outputFile_fp '"']);
|
command = cat(2, command, [' -f "' in_file_name '" -of "' outputFile_fp '"']);
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command, '-echo')
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
%% evaluating yt datasets
|
%% evaluating yt datasets
|
||||||
d_loc = 'yt_features/';
|
d_loc = 'yt_features/';
|
||||||
d_loc_clm = 'yt_features_clm/';
|
d_loc_clm = 'yt_features_clm/';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
% This is sort of the unit test for the whole module (needs datasets)
|
% This is sort of the unit test for the whole module (needs datasets)
|
||||||
% Will take over an hour to run all
|
% Will take several hours to run all
|
||||||
|
clear
|
||||||
tic
|
tic
|
||||||
%% Head pose
|
%% Head pose
|
||||||
cd('Head Pose Experiments');
|
cd('Head Pose Experiments');
|
||||||
|
@ -12,7 +12,7 @@ cd('../');
|
||||||
|
|
||||||
%% Features
|
%% Features
|
||||||
cd('Feature Point Experiments');
|
cd('Feature Point Experiments');
|
||||||
run_clm_feature_point_tests_wild;
|
run_OpenFace_feature_point_tests_300W;
|
||||||
assert(median(err_clnf) < 0.041);
|
assert(median(err_clnf) < 0.041);
|
||||||
assert(median(err_clnf_wild) < 0.041);
|
assert(median(err_clnf_wild) < 0.041);
|
||||||
run_yt_dataset;
|
run_yt_dataset;
|
||||||
|
|
|
@ -7,9 +7,12 @@ if(exist([getenv('USERPROFILE') '/Dropbox/AAM/eye_clm/mpii_data/'], 'file'))
|
||||||
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/eye_clm/mpii_data/'];
|
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/eye_clm/mpii_data/'];
|
||||||
elseif(exist('D:\Dropbox/Dropbox/AAM/eye_clm/mpii_data/', 'file'))
|
elseif(exist('D:\Dropbox/Dropbox/AAM/eye_clm/mpii_data/', 'file'))
|
||||||
database_root = 'D:\Dropbox/Dropbox/AAM/eye_clm/mpii_data/';
|
database_root = 'D:\Dropbox/Dropbox/AAM/eye_clm/mpii_data/';
|
||||||
|
elseif(exist('/multicomp/datasets/mpii_gaze/mpii_data/', 'file'))
|
||||||
|
database_root = '/multicomp/datasets/mpii_gaze/mpii_data/';
|
||||||
else
|
else
|
||||||
fprintf('MPII gaze dataset not found\n');
|
fprintf('MPII gaze dataset not found\n');
|
||||||
end
|
end
|
||||||
|
|
||||||
output_loc = './gaze_estimates_MPII/';
|
output_loc = './gaze_estimates_MPII/';
|
||||||
if(~exist(output_loc, 'dir'))
|
if(~exist(output_loc, 'dir'))
|
||||||
mkdir(output_loc);
|
mkdir(output_loc);
|
||||||
|
@ -18,7 +21,13 @@ end
|
||||||
output = './mpii_out/';
|
output = './mpii_out/';
|
||||||
|
|
||||||
%% Perform actual gaze predictions
|
%% Perform actual gaze predictions
|
||||||
command = sprintf('"../../x64/Release/FaceLandmarkImg.exe" -fx 1028 -fy 1028 -gaze ');
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FaceLandmarkImg"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FaceLandmarkImg.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
|
command = sprintf('%s -fx 1028 -fy 1028 -gaze ', executable);
|
||||||
p_dirs = dir([database_root, 'p*']);
|
p_dirs = dir([database_root, 'p*']);
|
||||||
|
|
||||||
parfor p=1:numel(p_dirs)
|
parfor p=1:numel(p_dirs)
|
||||||
|
@ -30,7 +39,11 @@ parfor p=1:numel(p_dirs)
|
||||||
command_c = cat(2, command, input_loc, out_img_loc, out_p_loc);
|
command_c = cat(2, command, input_loc, out_img_loc, out_p_loc);
|
||||||
|
|
||||||
command_c = cat(2, command_c, ' -wild');
|
command_c = cat(2, command_c, ' -wild');
|
||||||
dos(command_c);
|
if(isunix)
|
||||||
|
unix(command_c, '-echo');
|
||||||
|
else
|
||||||
|
dos(command_c);
|
||||||
|
end;
|
||||||
|
|
||||||
end
|
end
|
||||||
%%
|
%%
|
||||||
|
|
Binary file not shown.
|
@ -1,2 +1,2 @@
|
||||||
Mean error, median error
|
Mean error, median error
|
||||||
9.469, 8.773
|
9.468, 8.773
|
||||||
|
|
Binary file not shown.
|
@ -1,4 +1,4 @@
|
||||||
Dataset and model, pitch, yaw, roll, mean, median
|
Dataset and model, pitch, yaw, roll, mean, median
|
||||||
biwi error: 7.955, 5.583, 4.402, 5.980, 2.624
|
biwi error: 7.957, 5.583, 4.403, 5.981, 2.624
|
||||||
bu error: 2.762, 4.103, 2.568, 3.145, 2.118
|
bu error: 2.762, 4.103, 2.568, 3.145, 2.118
|
||||||
ict error: 3.620, 3.608, 3.626, 3.618, 2.028
|
ict error: 3.620, 3.608, 3.626, 3.618, 2.028
|
||||||
|
|
|
@ -1,31 +1,26 @@
|
||||||
function [fps, resDir] = run_biwi_experiment(rootDir, biwiDir, outputDir, verbose, depth, version, varargin)
|
function [output_dir] = run_biwi_experiment(rootDir, biwiDir, verbose, depth, varargin)
|
||||||
% Biwi dataset experiment
|
% Biwi dataset experiment
|
||||||
|
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
output = 'Tracker_';
|
output_dir = 'experiments/biwi_out';
|
||||||
|
|
||||||
dbSeqDir = dir([rootDir biwiDir]);
|
dbSeqDir = dir([rootDir biwiDir]);
|
||||||
|
|
||||||
% listing the output based on the current revision
|
|
||||||
output = [output 'r' num2str(version)];
|
|
||||||
|
|
||||||
if(depth)
|
if(depth)
|
||||||
output = cat(2, output, '_depth');
|
output_dir = cat(2, output_dir, '_depth');
|
||||||
end
|
end
|
||||||
|
|
||||||
outputDir = cat(2, outputDir, ['/' output '/']);
|
output_dir = cat(2, output_dir, '/');
|
||||||
|
|
||||||
if(~exist([outputDir], 'dir'))
|
|
||||||
mkdir([outputDir]);
|
|
||||||
end
|
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
r = 1 + offset;
|
r = 1 + offset;
|
||||||
|
|
||||||
tic;
|
|
||||||
|
|
||||||
numTogether = 25;
|
numTogether = 25;
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +29,7 @@ for i=3 + offset:numTogether:numel(dbSeqDir)
|
||||||
|
|
||||||
command = executable;
|
command = executable;
|
||||||
|
|
||||||
command = cat(2, command, [' -root ' '"' rootDir '"']);
|
command = cat(2, command, [' -inroot ' '"' rootDir '"']);
|
||||||
|
|
||||||
% deal with edge cases
|
% deal with edge cases
|
||||||
if(numTogether + i > numel(dbSeqDir))
|
if(numTogether + i > numel(dbSeqDir))
|
||||||
|
@ -44,7 +39,7 @@ for i=3 + offset:numTogether:numel(dbSeqDir)
|
||||||
for n=0:numTogether-1
|
for n=0:numTogether-1
|
||||||
|
|
||||||
inputFile = [biwiDir dbSeqDir(i+n).name '/colour.avi'];
|
inputFile = [biwiDir dbSeqDir(i+n).name '/colour.avi'];
|
||||||
outputFile = [outputDir dbSeqDir(i+n).name '.txt'];
|
outputFile = [output_dir dbSeqDir(i+n).name '.txt'];
|
||||||
|
|
||||||
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '"']);
|
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '"']);
|
||||||
|
|
||||||
|
@ -54,7 +49,7 @@ for i=3 + offset:numTogether:numel(dbSeqDir)
|
||||||
end
|
end
|
||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
outputVideo = [outputDir dbSeqDir(i).name '.avi'];
|
outputVideo = [output_dir dbSeqDir(i).name '.avi'];
|
||||||
command = cat(2, command, [' -ov "' outputVideo '"']);
|
command = cat(2, command, [' -ov "' outputVideo '"']);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -65,9 +60,9 @@ for i=3 + offset:numTogether:numel(dbSeqDir)
|
||||||
end
|
end
|
||||||
|
|
||||||
r = r+1;
|
r = r+1;
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command, '-echo')
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
timeTaken = toc;
|
|
||||||
fps = 15678 / timeTaken;
|
|
||||||
resDir = outputDir;
|
|
|
@ -1,27 +1,21 @@
|
||||||
function [fps, resDir] = run_bu_experiment(bu_dir, verbose, version, varargin)
|
function [output_dir] = run_bu_experiment(bu_dir, verbose, varargin)
|
||||||
|
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
output = 'Tracker_';
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
% listing the output based on the current revision
|
|
||||||
output = [output 'r' num2str(version)];
|
|
||||||
|
|
||||||
output = cat(2, output, '/');
|
|
||||||
|
|
||||||
if(~exist([bu_dir output], 'dir'))
|
|
||||||
mkdir([bu_dir output]);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
output_dir = 'experiments/bu_out/';
|
||||||
|
|
||||||
buFiles = dir([bu_dir '*.avi']);
|
buFiles = dir([bu_dir '*.avi']);
|
||||||
|
|
||||||
numTogether = 25;
|
numTogether = 25;
|
||||||
|
|
||||||
tic;
|
|
||||||
for i=1:numTogether:numel(buFiles)
|
for i=1:numTogether:numel(buFiles)
|
||||||
|
|
||||||
command = executable;
|
command = executable;
|
||||||
command = cat(2, command, [' -root ' '"' bu_dir '/"']);
|
command = cat(2, command, [' -inroot ' '"' bu_dir '/"']);
|
||||||
|
|
||||||
% BU dataset orientation is in terms of camera plane, instruct the
|
% BU dataset orientation is in terms of camera plane, instruct the
|
||||||
% tracker to output it in that format
|
% tracker to output it in that format
|
||||||
|
@ -37,12 +31,12 @@ function [fps, resDir] = run_bu_experiment(bu_dir, verbose, version, varargin)
|
||||||
[~, name, ~] = fileparts(inputFile);
|
[~, name, ~] = fileparts(inputFile);
|
||||||
|
|
||||||
% where to output results
|
% where to output results
|
||||||
outputFile = [output name '.txt'];
|
outputFile = [output_dir name '.txt'];
|
||||||
|
|
||||||
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '"']);
|
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '"']);
|
||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
outputVideo = ['"' output name '.avi' '"'];
|
outputVideo = ['"' output_dir name '.avi' '"'];
|
||||||
command = cat(2, command, [' -ov ' outputVideo]);
|
command = cat(2, command, [' -ov ' outputVideo]);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -53,13 +47,11 @@ function [fps, resDir] = run_bu_experiment(bu_dir, verbose, version, varargin)
|
||||||
command = cat(2, command, [' -mloc "', varargin{find(strcmp('model', varargin))+1}, '"']);
|
command = cat(2, command, [' -mloc "', varargin{find(strcmp('model', varargin))+1}, '"']);
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command, '-echo')
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
timeTaken = toc;
|
|
||||||
fps = 9000 / timeTaken;
|
|
||||||
|
|
||||||
% tell the caller where the output was written
|
|
||||||
resDir = [bu_dir output];
|
|
||||||
|
|
||||||
end
|
end
|
|
@ -8,38 +8,34 @@ if exist('D:/Datasets/HeadPose', 'file')
|
||||||
database_root = 'D:/Datasets/HeadPose/';
|
database_root = 'D:/Datasets/HeadPose/';
|
||||||
elseif(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
elseif(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
||||||
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
||||||
else
|
elseif(exist([getenv('USERPROFILE') 'F:/Dropbox/Dropbox/AAM/test data/'], 'file'))
|
||||||
database_root = 'F:/Dropbox/Dropbox/AAM/test data/';
|
database_root = 'F:/Dropbox/Dropbox/AAM/test data/';
|
||||||
|
else
|
||||||
|
database_root = '/multicomp/datasets/head_pose_dbs/';
|
||||||
end
|
end
|
||||||
|
|
||||||
buDir = [database_root, '/bu/uniform-light/'];
|
buDir = [database_root, '/bu/uniform-light/'];
|
||||||
|
|
||||||
% The fast and accurate clnf
|
% The fast and accurate clnf
|
||||||
%%
|
%%
|
||||||
v = 3;
|
[resFolderBU_OF] = run_bu_experiment(buDir, false, 'model', 'model/main_clnf_general.txt');
|
||||||
[fps_bu_OF, resFolderBU_OF] = run_bu_experiment(buDir, false, v, 'model', 'model/main_clnf_general.txt');
|
|
||||||
[bu_error_OF, pred_hp_bu, gt_hp_bu, all_errors_bu_OF, rels_bu] = calcBUerror(resFolderBU_OF, buDir);
|
[bu_error_OF, pred_hp_bu, gt_hp_bu, all_errors_bu_OF, rels_bu] = calcBUerror(resFolderBU_OF, buDir);
|
||||||
|
|
||||||
%%
|
%%
|
||||||
% Run the Biwi test
|
% Run the Biwi test
|
||||||
biwi_dir = '/biwi pose/';
|
biwi_dir = '/biwi pose/';
|
||||||
biwi_results_root = '/biwi pose results/';
|
|
||||||
|
|
||||||
% Intensity
|
[res_folder_biwi_OF] = run_biwi_experiment(database_root, biwi_dir, false, false, 'model', 'model/main_clnf_general.txt');
|
||||||
v = 4;
|
|
||||||
[fps_biwi_OF, res_folder_OF] = run_biwi_experiment(database_root, biwi_dir, biwi_results_root, false, false, v, 'model', 'model/main_clnf_general.txt');
|
|
||||||
% Calculate the resulting errors
|
% Calculate the resulting errors
|
||||||
[biwi_error_OF, pred_hp_biwi, gt_hp_biwi, ~, all_errors_biwi_OF, rels_biwi] = calcBiwiError([database_root res_folder_OF], [database_root biwi_dir]);
|
[biwi_error_OF, pred_hp_biwi, gt_hp_biwi, ~, all_errors_biwi_OF, rels_biwi] = calcBiwiError(res_folder_biwi_OF, [database_root biwi_dir]);
|
||||||
|
|
||||||
%% Run the ICT test
|
%% Run the ICT test
|
||||||
ict_dir = ['ict/'];
|
ict_dir = ['/ict/'];
|
||||||
ict_results_root = ['ict results/'];
|
|
||||||
|
|
||||||
v = 4;
|
|
||||||
% Intensity
|
% Intensity
|
||||||
[fps_ict_OF, res_folder_ict_OF] = run_ict_experiment(database_root, ict_dir, ict_results_root, false, false, v, 'model', 'model/main_clnf_general.txt');
|
[res_folder_ict_OF] = run_ict_experiment(database_root, ict_dir, false, false, 'model', 'model/main_clnf_general.txt');
|
||||||
% Calculate the resulting errors
|
% Calculate the resulting errors
|
||||||
[ict_error_OF, pred_hp_ict, gt_hp_ict, ~, all_errors_ict_OF, rel_ict] = calcIctError([database_root res_folder_ict_OF], [database_root ict_dir]);
|
[ict_error_OF, pred_hp_ict, gt_hp_ict, ~, all_errors_ict_OF, rel_ict] = calcIctError(res_folder_ict_OF, [database_root ict_dir]);
|
||||||
|
|
||||||
%% Save the results
|
%% Save the results
|
||||||
filename = 'results/Pose_OF';
|
filename = 'results/Pose_OF';
|
||||||
|
|
|
@ -1,27 +1,22 @@
|
||||||
function [fps, resDir] = run_ict_experiment(rootDir, ictDir, outputRoot, verbose, depth, version, varargin)
|
function [output_dir] = run_ict_experiment(rootDir, ictDir, verbose, depth, varargin)
|
||||||
%EVALUATEICTDATABASE Summary of this function goes here
|
%EVALUATEICTDATABASE Summary of this function goes here
|
||||||
% Detailed explanation goes here
|
% Detailed explanation goes here
|
||||||
|
|
||||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
if(isunix)
|
||||||
|
executable = '"../../build/bin/FeatureExtraction"';
|
||||||
|
else
|
||||||
|
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||||
|
end
|
||||||
|
|
||||||
output = 'Tracker_';
|
output_dir = 'experiments/ict_out';
|
||||||
|
|
||||||
dbSeqDir = dir([rootDir ictDir]);
|
dbSeqDir = dir([rootDir ictDir]);
|
||||||
|
|
||||||
% listing the output based on the current revision
|
|
||||||
output = [output 'r' num2str(version)];
|
|
||||||
|
|
||||||
if(depth)
|
if(depth)
|
||||||
output = cat(2, output, '_depth');
|
output_dir = cat(2, output_dir, '_depth');
|
||||||
end
|
end
|
||||||
|
|
||||||
outputDir = cat(2, outputRoot, ['/' output '/']);
|
output_dir = cat(2, output_dir, '/');
|
||||||
|
|
||||||
if(~exist([rootDir outputDir], 'dir'))
|
|
||||||
mkdir([rootDir outputDir]);
|
|
||||||
end
|
|
||||||
|
|
||||||
tic;
|
|
||||||
|
|
||||||
numTogether = 10;
|
numTogether = 10;
|
||||||
|
|
||||||
|
@ -29,7 +24,7 @@ for i=3:numTogether:numel(dbSeqDir)
|
||||||
|
|
||||||
command = [executable ' -fx 535 -fy 536 -cx 327 -cy 241 -no2Dfp -no3Dfp -noMparams -noAUs -noGaze '];
|
command = [executable ' -fx 535 -fy 536 -cx 327 -cy 241 -no2Dfp -no3Dfp -noMparams -noAUs -noGaze '];
|
||||||
|
|
||||||
command = cat(2, command, [' -root ' '"' rootDir '/"']);
|
command = cat(2, command, [' -inroot ' '"' rootDir '/"']);
|
||||||
|
|
||||||
% deal with edge cases
|
% deal with edge cases
|
||||||
if(numTogether + i > numel(dbSeqDir))
|
if(numTogether + i > numel(dbSeqDir))
|
||||||
|
@ -39,7 +34,7 @@ for i=3:numTogether:numel(dbSeqDir)
|
||||||
for n=0:numTogether-1
|
for n=0:numTogether-1
|
||||||
|
|
||||||
inputFile = [ictDir dbSeqDir(i+n).name '/colour undist.avi'];
|
inputFile = [ictDir dbSeqDir(i+n).name '/colour undist.avi'];
|
||||||
outputFile = [outputDir dbSeqDir(i+n).name '.txt'];
|
outputFile = [output_dir dbSeqDir(i+n).name '.txt'];
|
||||||
|
|
||||||
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '" ']);
|
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '" ']);
|
||||||
|
|
||||||
|
@ -49,7 +44,7 @@ for i=3:numTogether:numel(dbSeqDir)
|
||||||
end
|
end
|
||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
outputVideo = [outputDir dbSeqDir(i+n).name '.avi'];
|
outputVideo = [output_dir dbSeqDir(i+n).name '.avi'];
|
||||||
command = cat(2, command, [' -ov "' outputVideo '"']);
|
command = cat(2, command, [' -ov "' outputVideo '"']);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -58,12 +53,13 @@ for i=3:numTogether:numel(dbSeqDir)
|
||||||
command = cat(2, command, [' -mloc "', varargin{find(strcmp('model', varargin))+1}, '"']);
|
command = cat(2, command, [' -mloc "', varargin{find(strcmp('model', varargin))+1}, '"']);
|
||||||
end
|
end
|
||||||
|
|
||||||
dos(command);
|
if(isunix)
|
||||||
|
unix(command, '-echo')
|
||||||
|
else
|
||||||
|
dos(command);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
timeTaken = toc;
|
|
||||||
fps = 10661 / timeTaken;
|
|
||||||
resDir = outputDir;
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue