Commit 9d7e1f8c authored by jayd1860's avatar jayd1860
Browse files

v1.18.4

-- Convert SNIRF acquired data loading code from using high level to low level HDF5 functions to improve performance.
-- Fix some bugs in Logger class and in code that uses it. Change the way unit test code uses logger as well.
-- Other small performance improvements most notably in not using the slow str2cell() where it's not needed.
parent ba348dad
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
function val = HDF5_DatasetLoad(gid, name, val)

if nargin==2
    val = []; 
end

try
    dsetid = H5D.open(gid, name);
    val = H5D.read(dsetid);
    H5D.close(dsetid);    
catch ME
    switch(class(val))
        case 'char'
            val = '';
        case 'cell'
            val = {};
        otherwise            
            val = [];
    end
end
+6 −0
Original line number Diff line number Diff line
function HDF5_GroupClose(fileobj, gid, fid)

H5G.close(gid);
if ischar(fileobj)
    H5F.close(fid);
end
+15 −0
Original line number Diff line number Diff line
function [gid, fid] = HDF5_GroupOpen(fileobj, location)

% Find data location
if ischar(fileobj)
    fid = H5F.open(fileobj);
else
    fid = fileobj;
end
try
    gid = H5G.open(fid, location);
catch
    gid = -1;
end

+5 −2
Original line number Diff line number Diff line
@@ -2,6 +2,9 @@ function snew = convertH5StrToStr(s)

snew = '';
if iscell(s) || ischar(s)
    if size(s,1) > size(s,2)
        s = s';
    end
    snew = strtrim_improve(s);
elseif iswholenum(s)
    snew = char(s(:)');  % make sure it's row vector
+115 −49
Original line number Diff line number Diff line
function varval = h5load(fname, varval, varname)
function data = h5load(filename, path)
%
% data = H5LOAD(filename)
% data = H5LOAD(filename, path_in_file)
%
% Load data in a HDF5 file to a Matlab structure.
%
% Parameters
% ----------
%
% filename
%     Name of the file to load data from
% path_in_file : optional
%     Path to the part of the HDF5 file to load
%

if nargin==1
    varname = '';
end
varval = h5loadvar(fname, varval, varname);
% Author: Pauli Virtanen <pav@iki.fi>
% This script is in the Public Domain. No warranty.

if nargin > 1
    path_parts = regexp(path, '/', 'split');
else
    path = '';
    path_parts = [];
end

loc = H5F.open(filename, 'H5F_ACC_RDONLY', 'H5P_DEFAULT');
try
    data = load_one(loc, path_parts, path);
    H5F.close(loc);
catch exc
    H5F.close(loc);
    rethrow(exc);
end

% ---------------------------------------------------------------------------
function varval = h5loadvar(fname, varval, varname)

% Simple matrices: uint, int, double, char, etc
if ~isstruct(varval) && ~isobject(varval)
% ---------------------------------------------------------------------
function data = load_one(loc, path_parts, full_path)
% Load a record recursively.

    % Create new leaf variable if it doesn't exist. 
    if exist(fname, 'file') && h5exist(h5info(fname), varname)
        varval = h5read(fname, varname);
    elseif exist(fname, 'file') && h5exist(h5info(fname), [varname, '_0'])
        switch(class(varval))
            case 'char'
                varval = '';
            case 'cell'
                varval = {};
            otherwise
                varval = [];                
        end
while ~isempty(path_parts) & strcmp(path_parts{1}, '')
    path_parts = path_parts(2:end);
end

% Structs and Classes
else
data = struct();

    props = propnames(varval(1));
    jj=1;
    while 1
num_objs = H5G.get_num_objs(loc);

        % Construct varname as it would appear in HDF5 file
        if isempty(varname) || varname(1)=='/'
            varname_jj = sprintf('%s_%d', varname, jj);
%
% Load groups and datasets
%
for j_item = 0:num_objs-1
    objtype = H5G.get_objtype_by_idx(loc, j_item);
    objname = H5G.get_objname_by_idx(loc, j_item);
    
    if objtype == 0
        % Group
        name = regexprep(objname, '.*/', '');
        
        if isempty(path_parts) | strcmp(path_parts{1}, name)
            if ~isempty(regexp(name,'^[a-zA-Z].*'))
                try
                    group_loc = H5G.open(loc, name);
                catch
                    d=1;
                end
                try
                    sub_data = load_one(group_loc, path_parts(2:end), full_path);
                    H5G.close(group_loc);
                catch exc
                    H5G.close(group_loc);
                    rethrow(exc);
                end
                if isempty(path_parts)
                    data = setfield(data, name, sub_data);
                else
            varname_jj = sprintf('/%s_%d', varname, jj);
                    data = sub_data;
                    return
                end
            end
        end
        
    elseif objtype == 1
        % Dataset
        name = regexprep(objname, '.*/', '');
        
        % Check if next struct or class element exists in HDF5 file
        if ~h5exist(h5info(fname), varname_jj);
            break;
        if isempty(path_parts) | strcmp(path_parts{1}, name)
            if ~isempty(regexp(name,'^[a-zA-Z].*'))
                dataset_loc = H5D.open(loc, name);
                try
                    sub_data = H5D.read(dataset_loc, 'H5ML_DEFAULT', 'H5S_ALL','H5S_ALL','H5P_DEFAULT');
                    H5D.close(dataset_loc);
                catch exc
                    H5D.close(dataset_loc);
                    rethrow(exc);
                end
                
        % Get values for all class/struct properties or fields
        for ii=1:length(props)
            subvarname = sprintf('%s/%s', varname_jj, props{ii});
            if jj>length(varval)
                if isstruct(varval)
                    varval(jj) = varval(1);
                sub_data = fix_data(sub_data);
                
                if isempty(path_parts)
                    data = setfield(data, name, sub_data);
                else
                    eval( sprintf('varval(jj) = %s();', class(varval(1))) );
                    data = sub_data;
                    return
                end
            end
        end
            varval_jj_prop = eval( sprintf('varval(jj).%s', props{ii}) );
            varval_jj_prop = h5loadvar(fname, varval_jj_prop, subvarname);
            eval( sprintf('varval(jj).%s = varval_jj_prop;', props{ii}) );
    end
        jj=jj+1;
end

% Check that we managed to load something if path walking is in progress
if ~isempty(path_parts)
    error(sprintf('Path "%s" not found in the HDF5 file', full_path));
end


% ---------------------------------------------------------------------
function data = fix_data(data)
% Fix some common types of data to more friendly form.

if isstruct(data)
    fields = fieldnames(data);
    if length(fields) == 2 & strcmp(fields{1}, 'r') & strcmp(fields{2}, 'i')
        if isnumeric(data.r) & isnumeric(data.i)
            data = data.r + 1j*data.i;
        end
    end
end

if isnumeric(data) & ndims(data) > 1
    % permute dimensions
    data = permute(data, fliplr(1:ndims(data)));
end
Loading