function compute_hmp_features(config, file_info, hmp_name, make_hmp_params)
%% Hierarchical Matching Pursuit
% Dictionary Learning and/or Data Coding
%
% Author: Austin Myers
% Based on code from Liefeng Bo
%
% compute_hmp_features()
% Learns hierarchical dictionaries using the data specified by file_info.
% If the dictionaries do not exist, then they will be learned from data.
% Once learned, the data is coded using the dictionaries.
%
% Data should be in:
%  ./<config.paths.img_feats>/<feature_type>/file_name
%
% Features of the data are saved in:
%  ./<config.paths.img_feats>/<hmp_name>/<feature_type>/layer_<j>/
%
% Dictionaries will be saved in:
%  ./<config.paths.hmp_dicts>/<hmp_name>/hmp_params.mat
%  ./<config.paths.hmp_dicts>/<hmp_name>/rgb_L1_75_15.mat
%  ./<config.paths.hmp_dicts>/<hmp_name>/<type>_L<layer_num>_<dict_sz>_<patch_sz>.mat

% Create a directory to save the learned dictionaries
dicts_path = fullfile(config.paths.hmp_dicts, hmp_name);
if ~exist(dicts_path, 'dir')
    mkdir(dicts_path);
end

% Working on path: <hmp_name>
fprintf('HMP : %s\n', hmp_name);

%% Compute HMP Features
% Determine which features have been selected.
use_feats = cellfun(@(x) any(strcmp([config.feat_sets{:}], x{1})), ...
                    config.raw_feature_types);
for i = find(use_feats)'
    hmp_params = make_hmp_params(config.raw_feature_types{i});
    feat_dir = fullfile(config.paths.img_feats, hmp_params(1).subdir);
    raw_feature_type = hmp_params(1).type;

    % Working on type ...
    fprintf('  - Working on raw %s data, type: %s\n', ...
            hmp_params(1).subdir, raw_feature_type);

    % Each element of hmp_params is a level of the HMP hierarchy
    for j = 1:numel(hmp_params)
        hmp_params(j).full_dir = feat_dir;

        % get_dict_path : <config.paths.hmp_dicts>/<hmp_name>/
        %                 <type>_L<layer_num>_<dict_sz>_<patch_sz>.mat
        dict_path = get_dict_path(dicts_path, raw_feature_type, j, hmp_params(j));

        % If the dictionary doesn't already exist, we need to learn it.
        if ~exist(dict_path, 'file') && config.learn_hmp
            % Learning dictionary
            fprintf('    - Learning dictionary %s\n', dict_path);

            % Dictionary Learning
            dict = learn_layer(hmp_params(j), file_info, config);
            save(dict_path, 'dict');
        elseif ~exist(dict_path, 'file')
            error('Dictionary does not exist');
        else
            fprintf('    - Loading dictionary %s\n', dict_path);
            load(dict_path);
        end

        % get_feat_dir : <config.paths.img_feats>/<hmp_name>/<type>/layer_<j>
        feat_dir = get_feat_dir(config.paths.img_feats, ...
                                     hmp_name, raw_feature_type, j);

        % Coding and pooling over data set
        % Saved features will be used as input at next layer
        fprintf('    - Code and Pool data in %s\n', feat_dir);
        code_and_pool_batch(feat_dir, file_info, dict, hmp_params(j), config);
    end

end

end

%% Helper functions to compute paths

% get_dict_path : <config.paths.hmp_params>/<hmp_name>/
%                 <type>_L<layer_num>_<dict_sz>_<patch_sz>.mat
%                 eg.  data_config/depth_L1_75_8.mat
function dict_path = get_dict_path(dir_path, feature_type, layer_num, params)
dict_path = fullfile(dir_path, ...
    [feature_type '_L' num2str(layer_num) '_' ...
    num2str(params.dict_sz) '_' num2str(params.patch_sz) '.mat']);
end

% get_feat_dir : <config.paths.img_feats>/<hmp_name>/<type>/layer_<j>.mat
%                eg. dataset_feats/hmp_path_01/depth/layer_1
function feat_dir = get_feat_dir(base_path, name, feature_type, j)
feat_dir = fullfile(base_path, name, feature_type, ['layer_' num2str(j)]);
end
