Files
nappMATLAB-toolbox/import/read_hdf5_as_table.m
T

131 lines
4.6 KiB
Matlab

function output_table = read_hdf5_as_table(filename,exclude_var_set)
% receives a h5 file written with function table2h5.
% reduced_var_set (cell of character_vectors), not usable yet.
% Last update: 14.08.2023
% By: Juan F. Florez Ospina
% Email: juan.florez-ospina@psi.ch
if ~iscellstr(exclude_var_set)
disp("exclude_var_set needs to be a cell of character vectors, e.g, {'var1','var2'} to be excluded.")
disp("To proceed, exclude_var_set was set to {}. So vars will be excluded.")
exclude_var_set = {};
end
INFO = h5info(filename);
num_rows = length(INFO.Groups);
num_attr1 = length(INFO.Groups(1).Datasets);
num_attr2 = length(INFO.Groups(1).Attributes);
num_cols = num_attr1 + num_attr2;
sz = [num_rows,num_cols];
% Extract group level attributes, they align for all
% groups (here denoting measurements/or rows) of the table in filename .h5
group_columns = {INFO.Groups(1).Attributes.Name};
if num_attr1 == 1 && isempty(INFO.Groups(1).Datasets(num_attr1).Attributes)
dataset_columns = {};
num_attr1 = 0;
num_cols = num_cols - 1;
else
for j = 1 : num_attr1
dataset_columns{j} = INFO.Groups(1).Datasets(j).Attributes.Value;
end
end
%TODO: Implement feature to exclude varibales/columns as well as rows at
%reading time. This requires propagating modifications
% % % Select group and dataset columns to be loaded from hdf5 file, which are
% % % those not in the exclude_var_set.
% % if ~isempty(exclude_var_set)
% % for j = 1 : length(exclude_var_set)
% % % keep all vars except exclude_var_set{j}
% % var_filter = ~strcmp(exclude_var_set{j},group_columns);
% % group_columns = group_columns(var_filter);
% % if sum(var_filter) > 0
% % exclude_var_set(j) = [];
% % end
% % end
% %
% % for j = 1 : length(exclude_var_set)
% % % keep all vars except exclude_var_set{j}
% % var_filter = ~strcmp(exclude_var_set{j},dataset_columns);
% % dataset_columns = dataset_columns(var_filter);
% % if sum(var_filter) > 0
% % exclude_var_set(j) = [];
% % end
% % end
% % end
% Construct cell array with table data, where each row denotes a group, and
% the columns are either datasets or attributes in the given group.
tmp = cell(num_rows,num_cols); % {};
idx = [];
group_columns = {};
for i = 1 : num_rows
disp(['Begin construction of row:',INFO.Groups(i).Name])
for j = 1 : num_cols
if j <= num_attr1
ds_name = [INFO.Groups(i).Name '/' INFO.Groups(i).Datasets(j).Name];
%disp(ds_name)
tmp{i,j} = h5read(filename,ds_name);
if i < 2
column_idx = str2double(INFO.Groups(i).Datasets(j).Name(3:end));
idx = [idx,column_idx];
end
end
if j > num_attr1
Name = INFO.Groups(i).Attributes(j-num_attr1).Name;
Datatype = INFO.Groups(i).Attributes(j-num_attr1).Datatype.Class;
% Detect string attributes and convert them to characters.
% TODO: extend to other necessary data types.
if strcmp(Datatype,'H5T_STRING')
convert_func = @(x) convertStringsToChars(x);
else % no data type conversion is performed
convert_func = @(x) x;
end
tmp{i,j} = convert_func(h5readatt(filename,INFO.Groups(i).Name, Name));
if i < 2
disp(Name)
% Split attribute name into column_tag (containing original
% column idx) and column_name
delimiter_idx = find(INFO.Groups(i).Attributes(j-num_attr1).Name=='_');
% Left most '_' determines the split location
delimiter_idx = delimiter_idx(1);
column_idx = str2double(Name(5:delimiter_idx-1));
group_columns = [group_columns,{Name(delimiter_idx+1:end)}];
%disp([Name(5:delimiter_idx-1),'-',column_name])
idx = [idx,column_idx];
end
end
end
disp(['Ends construction of row:',INFO.Groups(i).Name])
end
% Find original ordering of columns by sorting idx in ascending order
[~, idx_perm] = sort(idx,'ascend');
varNames = [dataset_columns,group_columns];
% Create output_table from cell array using cell2table. This as opposed to
% array2table extract the content of its cells, which facilitates filtering
% operations based on table columns/vars.
%output_table = array2table(tmp(:,idx_perm), 'VariableNames', varNames(idx_perm));
output_table = cell2table(tmp(:,idx_perm), 'VariableNames', varNames(idx_perm));