function [results, init_target_sz] = tracker(params)

%% Initialisation
% Get sequence information
[seq, im] = get_sequence_info(params.seq);
params = rmfield(params, 'seq');
if isempty(im)
    seq.rect_position = [];
    [~, results] = get_sequence_results(seq);
    return;
end

% Initialise position
pos = seq.init_pos(:)';
target_sz = seq.init_sz(:)';
params.init_sz = target_sz;

% Feature settings and default parameters
features = params.t_features;
params = init_default_params(params);
params.use_mexResize = true;

% Global feature parameters
if isfield(params, 't_global')
    global_fparams = params.t_global;
else
    global_fparams = [];
end
global_fparams.use_gpu = params.use_gpu;
global_fparams.gpu_id = params.gpu_id;
global_fparams.use_mexResize = true;

% Data types
if params.use_gpu
    params.data_type = zeros(1, 'single', 'gpuArray');
else
    params.data_type = zeros(1, 'single');
end
params.data_type_complex = complex(params.data_type);
global_fparams.data_type = params.data_type;

init_target_sz = target_sz;

% Check if color image
if size(im,3) == 3
    if all(all(im(:,:,1) == im(:,:,2)))
        is_color_image = false;
    else
        is_color_image = true;
    end
else
    is_color_image = false;
end

if size(im,3) > 1 && is_color_image == false
    im = im(:,:,1);
end

% Calculate search area and initial scale factor
search_area = prod(init_target_sz * params.search_area_scale);
if search_area > params.max_image_sample_size
    currentScaleFactor = sqrt(search_area / params.max_image_sample_size);
elseif search_area < params.min_image_sample_size
    currentScaleFactor = sqrt(search_area / params.min_image_sample_size);
else
    currentScaleFactor = 1.0;
end

% target size at the initial scale
base_target_sz = target_sz / currentScaleFactor;

% window size, taking padding into account
switch params.search_area_shape
    case 'proportional'
        img_sample_sz = floor(base_target_sz * params.search_area_scale);     % proportional area, same aspect ratio as the target
    case 'square'
        img_sample_sz = repmat(sqrt(prod(base_target_sz * params.search_area_scale)), 1, 2); % square area, ignores the target aspect ratio
    case 'fix_padding'
        img_sample_sz = base_target_sz + sqrt(prod(base_target_sz * params.search_area_scale) + (base_target_sz(1) - base_target_sz(2))/4) - sum(base_target_sz)/2; % const padding
    case 'custom'
        img_sample_sz = [base_target_sz(1)*2 base_target_sz(2)*2];
end

[features, global_fparams, feature_info] = init_features(features, global_fparams, is_color_image, img_sample_sz, 'exact');

% Set feature info
img_support_sz = feature_info.img_support_sz;
feature_sz = unique(feature_info.data_sz, 'rows', 'stable');
feature_cell_sz = unique(feature_info.min_cell_size, 'rows', 'stable');
num_feature_blocks = size(feature_sz, 1);
feature_extract_info = get_feature_extract_info(features);

% Size of the extracted feature maps
feature_sz_cell = mat2cell(feature_sz, ones(1,num_feature_blocks), 2);
filter_sz = feature_sz;
filter_sz_cell = permute(mat2cell(filter_sz, ones(1,num_feature_blocks), 2), [2 3 1]);

% The size of the label function DFT. Equal to the maximum filter size
[output_sz, k1] = max(filter_sz, [], 1);
k1 = k1(1);

% Get the remaining block indices
block_inds = 1:num_feature_blocks;
block_inds(k1) = [];

% Construct the Gaussian label function
yf = cell(numel(num_feature_blocks), 1);
for i = 1:num_feature_blocks
    sz = filter_sz_cell{i};
    output_sigma = sqrt(prod(floor(base_target_sz/feature_cell_sz(i)))) * params.output_sigma_factor;
    rg           = circshift(-floor((sz(1)-1)/2):ceil((sz(1)-1)/2), [0 -floor((sz(1)-1)/2)]);
    cg           = circshift(-floor((sz(2)-1)/2):ceil((sz(2)-1)/2), [0 -floor((sz(2)-1)/2)]);
    [rs, cs]     = ndgrid(rg,cg);
    y            = exp(-0.5 * (((rs.^2 + cs.^2) / output_sigma^2)));
    yf{i}           = fft2(y);
end

% Compute the cosine windows
cos_window = cellfun(@(sz) hann(sz(1))*hann(sz(2))', feature_sz_cell, 'uniformoutput', false);

% Define spatial regularization windows
reg_window = cell(num_feature_blocks, 1);
for i = 1:num_feature_blocks
    reg_scale = floor(1.3*base_target_sz/params.feature_downsample_ratio(i));
    use_sz = filter_sz_cell{i};
    reg_window{i} = ones(use_sz) * 1e5;
    range = zeros(numel(reg_scale), 2);

    % determine the target center and range in the regularization windows
    for j = 1:numel(reg_scale)
        range(j,:) = [0, reg_scale(j) - 1] - floor(reg_scale(j) / 2);
    end
    center = floor((use_sz + 1)/ 2) + mod(use_sz + 1,2);
    range_h = (center(1)+ range(1,1)) : (center(1) + range(1,2));
    range_w = (center(2)+ range(2,1)) : (center(2) + range(2,2));

    reg_window{i}(range_h, range_w) = 1e-3;
end
params.reg_window = reg_window;

% Pre-computes the grid that is used for socre optimization
ky = circshift(-floor((filter_sz_cell{1}(1) - 1)/2) : ceil((filter_sz_cell{1}(1) - 1)/2), [1, -floor((filter_sz_cell{1}(1) - 1)/2)]);
kx = circshift(-floor((filter_sz_cell{1}(2) - 1)/2) : ceil((filter_sz_cell{1}(2) - 1)/2), [1, -floor((filter_sz_cell{1}(2) - 1)/2)])';
newton_iterations = params.newton_iterations;

% Use the translation filter to estimate the scale
nScales = params.number_of_scales;
scale_step = params.scale_step;
scale_exp = (-floor((nScales-1)/2):ceil((nScales-1)/2));
scaleFactors = scale_step .^ scale_exp;

if nScales > 0
    min_scale_factor = scale_step ^ ceil(log(max(5 ./ img_support_sz)) / log(scale_step));
    max_scale_factor = scale_step ^ floor(log(min([size(im,1) size(im,2)] ./ base_target_sz)) / log(scale_step));
end

seq.time = 0;

% Define the learning variables
theta_pre_f = cell(num_feature_blocks, 1);
ctheta_f = cell(num_feature_blocks, 1);
L = cell(num_feature_blocks, 1);
scores_fs_feat = cell(1,1,num_feature_blocks);
while true
    % Read image
    if seq.frame > 0
        [seq, im] = get_sequence_frame(seq);
        if isempty(im)
            break;
        end
        if size(im,3) > 1 && is_color_image == false
            im = im(:,:,1);
        end
    else
        seq.frame = 1;
    end

    tic();

    %% Target localization stage

    if seq.frame > 1
        old_pos = inf(size(pos));
        iter = 1;

        %translation search
        while iter <= params.refinement_iterations && any(old_pos ~= pos)
            % Extract features at multiple resolutions
            sample_pos = round(pos);
            det_sample_pos = sample_pos;
            sample_scale = currentScaleFactor*scaleFactors;
            xt = extract_features(im, sample_pos, sample_scale, features, global_fparams, feature_extract_info);

            % Do windowing of features
            xtw = cellfun(@(feat_map, cos_window) bsxfun(@times, feat_map, sqrt(cos_window)), xt, cos_window, 'uniformoutput', false);

            % Compute the fourier series
            xtf = cellfun(@fft2, xtw, 'uniformoutput', false);

            scores_fs_feat{k1} = gather(sum(bsxfun(@times, conj(ctheta_f{k1}), xtf{k1}), 3));
            scores_fs_sum = scores_fs_feat{k1};
            for k = block_inds
                scores_fs_feat{k} = gather(sum(bsxfun(@times, conj(ctheta_f{k}), xtf{k}), 3));
                scores_fs_feat{k} = resizeDFT2(scores_fs_feat{k}, output_sz);
                scores_fs_sum = scores_fs_sum +  scores_fs_feat{k};
            end
            scores_fs = permute(gather(scores_fs_sum), [1 2 4 3]);

            responsef_padded = resizeDFT2(scores_fs, output_sz);
            response = ifft2(responsef_padded, 'symmetric');
            [disp_row, disp_col, sind] = resp_newton(response, responsef_padded, newton_iterations, ky, kx, output_sz);

            % Compute the translation vector in pixel-coordinates and round
            % to the closest integer pixel.
            translation_vec = [disp_row, disp_col] .* (img_support_sz./output_sz) * currentScaleFactor * scaleFactors(sind);
            scale_change_factor = scaleFactors(sind);

            % update position
            old_pos = pos;
            if sum(isnan(translation_vec))
                pos = sample_pos;
            else
                pos = sample_pos + translation_vec;
            end

            if params.clamp_position
                pos = max([1 1], min([size(im,1) size(im,2)], pos));
            end

            % Update the scale
            currentScaleFactor = currentScaleFactor * scale_change_factor;

            % Adjust to make sure we are not to large or to small
            if currentScaleFactor < min_scale_factor
                currentScaleFactor = min_scale_factor;
            elseif currentScaleFactor > max_scale_factor
                currentScaleFactor = max_scale_factor;
            end

            iter = iter + 1;
        end
    end

    %% Model learning and update stage

    % extract image region for training sample
    sample_pos = round(pos);
    xl = extract_features(im, sample_pos, currentScaleFactor, features, global_fparams, feature_extract_info);

    % do windowing of features
    xlw = cellfun(@(feat_map, cos_window) bsxfun(@times, feat_map, cos_window), xl, cos_window, 'uniformoutput', false);

    % compute the fourier series
    xlf = cellfun(@fft2, xlw, 'uniformoutput', false);

    [ctheta_f, theta_pre_f, L] = train_filter(ctheta_f, xlf, yf, theta_pre_f, params, output_sz, seq);

    % Update target size
    target_sz = base_target_sz * currentScaleFactor;

    % save position and time
    tracking_result.center_pos = double(pos);
    tracking_result.target_size = double(target_sz);
    seq = report_tracking_result(seq, tracking_result);

    seq.time = seq.time + toc();

    %% Visualization

    if params.visualization
        rect_position_vis = [pos([2,1]) - (target_sz([2,1]) - 1)/2, target_sz([2,1])];
        im_to_show = double(im)/255;
        if size(im_to_show,3) == 1
            im_to_show = repmat(im_to_show, [1 1 3]);
        end
        if seq.frame == 1
            fig_handle = figure('Name', 'Tracking');
            imagesc(im_to_show);
            hold on;
            rectangle('Position',rect_position_vis, 'EdgeColor','g', 'LineWidth',2);
            text(10, 10, int2str(seq.frame), 'color', [0 1 1]);
            hold off;
            axis off;axis image;set(gca, 'Units', 'normalized', 'Position', [0 0 1 1])

        else
            % Do visualization of the sampled confidence scores overlayed
%             resp_sz = round(img_support_sz*currentScaleFactor*scaleFactors(sind));
%             xs = floor(det_sample_pos(2)) + (1:resp_sz(2)) - floor(resp_sz(2)/2);
%             ys = floor(det_sample_pos(1)) + (1:resp_sz(1)) - floor(resp_sz(1)/2);
%             spatial_feature_display = circshift(imresize(L{1},[numel(xs),numel(ys)]);
            figure(fig_handle);
            imagesc(im_to_show);
%             hold on;
%             resp_handle = imagesc(xs, ys, spatial_feature_display); colormap hsv;
%             alpha(resp_handle, 0.5);
            rectangle('Position',rect_position_vis, 'EdgeColor','g', 'LineWidth',2);
            text(10, 10, int2str(seq.frame), 'color', [0 1 1]);
            hold off;

        end

        drawnow

    end

end

[seq, results] = get_sequence_results(seq);


function test_suite = test_intersectPlaneSphere
%TESTINTERSECTPLANESPHERE  One-line description here, please.
%
%   output = testIntersectPlaneSphere(input)
%
%   Example
%   testIntersectPlaneSphere
%
%   See also
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-06-21,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

test_suite = functiontests(localfunctions);

function testOx(testCase) %#ok<*DEFNU>
% Plane normal to direction [1 0 0]

center = [10 20 30];
radius = 50;
sphere = [center radius];

plane = createPlane(center, [6 0 0]);

circle = intersectPlaneSphere(plane, sphere);

exp = [center radius 90 0 0];
testCase.assertEqual(exp, circle);

function testOxShifted(testCase)
% Plane normal to direction [1 0 0]

center = [10 20 30];
radius = 50;
sphere = [center radius];

center2 = center + [radius/2 0 0];
plane = createPlane(center2, [6 0 0]);

circle = intersectPlaneSphere(plane, sphere);

radius2 = radius * sqrt(3) / 2;
exp = [center2 radius2 90 0 0];
testCase.assertEqual(exp, circle);

function testOy(testCase)
% Plane normal to direction [0 1 0]

center = [10 20 30];
radius = 50;
sphere = [center radius];

plane = createPlane(center, [0 6 0]);

circle = intersectPlaneSphere(plane, sphere);

exp = [center radius 90 90 0];
testCase.assertEqual(exp, circle, 'AbsTol', .01);

function testOyShifted(testCase)
% Plane normal to direction [0 1 0]

center = [10 20 30];
radius = 50;
sphere = [center radius];

center2 = center + [0 radius/2 0];
plane = createPlane(center2, [0 6 0]);

circle = intersectPlaneSphere(plane, sphere);

radius2 = radius * sqrt(3) / 2;
exp = [center2 radius2 90 90 0];
testCase.assertEqual(exp, circle, 'AbsTol', .01);

function testOz(testCase)
% Plane normal to direction [0 1 0]

center = [10 20 30];
radius = 50;
sphere = [center radius];

plane = createPlane(center, [0 0 6]);

circle = intersectPlaneSphere(plane, sphere);

exp = [center radius 0 0 0];
testCase.assertEqual(exp, circle, 'AbsTol', .01);

function testOzShifted(testCase)
% Plane normal to direction [0 0 1]

center = [10 20 30];
radius = 50;
sphere = [center radius];

center2 = center + [0 0 radius/2];
plane = createPlane(center2, [0 0 6]);

circle = intersectPlaneSphere(plane, sphere);

radius2 = radius * sqrt(3) / 2;
exp = [center2 radius2 0 0 0];
testCase.assertEqual(exp, circle, 'AbsTol', .01);


function output = calloptiqsopt(interfacedata)

% Standard input interface
options = interfacedata.options;
F_struc = interfacedata.F_struc;
c       = interfacedata.c;
K       = interfacedata.K;
lb      = interfacedata.lb;
ub      = interfacedata.ub;

showprogress('Calling QSOPT',options.showprogress);

if isempty(F_struc)
    A = [];
    b = [];
else
    A =[-F_struc(K.f+1:end,2:end);-F_struc(1:K.f,2:end)];
    b =[F_struc(K.f+1:end,1);F_struc(1:K.f,1)];
end

opts = options.qsopt;
opts.nin = length(b)-K.f;
opts.display = options.verbose;

if options.savedebug
    save qsoptdebug c A b  lb ub opts
end

solvertime = tic;
[x,fval,exitflag] = qsopt(full(c), A, full(b), full(lb), full(ub),opts);
solvertime = toc(solvertime);

% No duals
D_struc = [];

switch exitflag
    case 1
        problem = 0;
    case 0
        problem = 3;
    case -1
        problem = 1;
    case -2
        problem = 11;
    otherwise
        problem = -1;
end
infostr = yalmiperror(problem,'QSOPT');

% Save all data sent to solver?
if options.savesolverinput
    solverinput.A = A;
    solverinput.b = b;
    solverinput.f = c;
    solverinput.lb = lb;
    solverinput.ub = ub;
else
    solverinput = [];
end

% Save all data from the solver?
if options.savesolveroutput
    solveroutput.x = x;
    solveroutput.fval = fval;
    solveroutput.exitflag = exitflag;
else
    solveroutput = [];
end

% Standard interface
output = createOutputStructure(x,D_struc,[],problem,infostr,solverinput,solveroutput,solvertime);


function Rob = createRobots(Robot)

% CREATEROBOTS Create robots structure array.
%   Rob = CREATEROBOTS(Robot) creates the Rob() structure array to be used
%   as SLAM data. The input Robot{}  is a cell array of structures as
%   specified by the user in userData.m. There must be one Robot{} per each
%   robot considered in the simulation. See userData.m for details.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

for rob = 1:numel(Robot)

    Ri = Robot{rob}; % input robot structure

    % identification
    Ro.rob     = rob;
    Ro.id      = Ri.id;
    Ro.name    = Ri.name;
    Ro.type    = Ri.type;
    Ro.motion  = Ri.motion;

    Ro.sensors = [];

    % Robot frame in quaternion form
    ep = [Ri.position;deg2rad(Ri.orientationDegrees)];
    EP = diag([Ri.positionStd;deg2rad(Ri.orientationStd)].^2);
    [qp,QP] = propagateUncertainty(ep,EP,@epose2qpose); % frame and cov. in quaternion

    % control and rest of the state
    switch Ri.motion

        case {'constVel'}
            % control
            Ro.con.u    = [Ri.dv;deg2rad(Ri.dwDegrees)];
            Ro.con.uStd = [Ri.dvStd;deg2rad(Ri.dwStd)];
            Ro.con.U    = diag(Ro.con.uStd.^2);
            Ro.com.W    = 1/Ro.con.U;  % Information matrix

            % velocity states
            v = [Ri.velocity;deg2rad(Ri.angularVelDegrees)];
            V = diag([Ri.velStd;deg2rad(Ri.angVelStd)].^2);

            % state
            Ro.state.x    = [qp;v]; % state
            Ro.state.P    = blkdiag(QP,V);
            Ro.state.dx   = zeros(12,1);

        case {'odometry'}
            % control
            Ro.con.u    = [Ri.dx;deg2rad(Ri.daDegrees)];
            Ro.con.uStd = [Ri.dxStd;deg2rad(Ri.daStd)];
            Ro.con.U    = diag(Ro.con.uStd.^2);
            Ro.com.W    = Ro.con.U^-1;  % Information matrix

            % state
            Ro.state.x    = qp; % state
            Ro.state.P    = EP;
            Ro.state.dx   = zeros(6,1);

        otherwise
            error('Unknown motion model ''%s'' for robot %d.',Robot{rob}.motion,Robot{rob}.id);
    end

    Ro.state.r  = []; % Points  Map.x  into  state.dx
    Ro.state.size = numel(Ro.state.x);   % state size
    Ro.state.dsize = numel(Ro.state.dx);

    Ro.frame.r = [];
    Ro.frame.x = qp;
    Ro.frame.P = QP;
    Ro.frame = updateFrame(Ro.frame);

    Rob(rob) = Ro; % output robot structure

end

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB is free software: you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation, either version 3 of the License, or
%   (at your option) any later version.
%
%   SLAMTB is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You should have received a copy of the GNU General Public License
%   along with SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


clear;
addpath('../../CVPR16_VDSR/');
addpath('./matlabPyrTools-master/');
%% test
% load('DRRN_22C128_dataset_1_x3');
load('VDSR_20C64_dataset_1_x3');
path = ['../../SR Test dataset/Set5/'];
d = dir([path '*.bmp']);
up_scale = 3;
sum = 0 ;
for i=1:length(d)
    im = imread([path d(i).name]);
    %% work on illuminance only
    if size(im,3)>1
        im = rgb2ycbcr(im);
    end
    im = im2double(im(:,:,1));
    im_gnd = modcrop(im, up_scale);
    [hei,wid] = size(im_gnd);
    im_b = imresize(imresize(im_gnd,1/up_scale,'bicubic'),up_scale,'bicubic');
    %% remove border
    im_b1 = shave(uint8(single(im_b) * 255), [up_scale, up_scale]);
    im_gnd1 = shave(uint8(single(im_gnd) * 255), [up_scale, up_scale]);
    im_h1 = im_h_set{i};
    sum = sum+ifcvec(double(im_gnd1),double(im_h1));
end
ifc = sum/length(d)


function [costPatchCand, uvBiasCand] = ...
    sc_patch_cost(trgPatch, srcPatch, modelPlane, uvPlaneIDData, ...
    trgPos, srcTform, srcPosMap, bdPos, optS)

numUvPix      = size(srcPatch, 3);
costPatchCand = zeros(numUvPix, 4, 'single');

% Patch cost - appearance
[costApp, uvBiasCand] = sc_patch_cost_app(trgPatch, srcPatch, optS);

% Patch cost - planar guidance
srcPos = srcTform(:,7:8);
costPlane = sc_patch_cost_plane(modelPlane.mLogLPlaneProb, uvPlaneIDData, trgPos, srcPos);

if(optS.useCoherence) % Patch cost - coherence
    costCoherence = sc_patch_cost_coherence(trgPos, srcPosMap, srcTform, optS);
end

% Patch cost - directional guidance
costDirect = sc_patch_cost_direct(uvPlaneIDData, trgPos, srcPos, modelPlane, optS);

% Patch cost - proximity cost
costProx = sc_patch_cost_prox(srcPos, trgPos, bdPos, optS);

% costReg = double(uvPixUpdateSrc == 1);

% Weighted sum of the appearance cost and guidance cost
costPatchCand(:,1) = costApp;
costPatchCand(:,2) = optS.lambdaPlane * costPlane;

if(optS.useCoherence)
    costPatchCand(:,3) = optS.lambdaCoherence * costCoherence;
end

costPatchCand(:,4) = optS.lambdaDirect * costDirect;
costPatchCand(:,5) = optS.lambdaProx   * costProx;
% costPatchCand(3,:) = optS.lambdaReg    * costReg;

% [To-Do] Adaptive weighting for patch cost
% costPatchCand(2:5,:) = (iLvl/optS.numPyrLvl)*costPatchCand(2:5,:);

end

function [costApp, uvBias] = sc_patch_cost_app(trgPatch, srcPatch, optS)

% SC_PATCH_COST_APP
%
% Compute the weighted sum of the absolute difference between
% cost between source and target patches

% Input:
%   - trgPatch:  target patch
%   - srcPatch:  source patch
%   - optS:      parameter
% Output:
%   - costApp:   appearance cost
%   - uvBias     bias for the closet neighbor

% =========================================================================
% Apply bias correction
% =========================================================================

uvBias = [];
if(optS.useBiasCorrection)
    % Mean of source and target patch
    meanTrgPatch = mean(trgPatch, 1);
    meanSrcPatch = mean(srcPatch, 1);

    % Compute bias and clamp it to inteval [optS.minBias, optS.maxBias]
    uvBias = meanTrgPatch - meanSrcPatch;
    uvBias = sc_clamp(uvBias, optS.minBias, optS.maxBias);

    % Update the UV map for bias
    %     uvBias = reshape(biasPatch, 3, numUvValidPix);

    % Apply the bias correction to source patch
    srcPatch = bsxfun(@plus, srcPatch, uvBias);
end

% =========================================================================
% Compute weighted distance
% =========================================================================
% Compute distance
patchDist = trgPatch - srcPatch;

% Sum of absolute distance
if(strcmp(optS.costType, 'L1'))
    patchDist = abs(patchDist);
elseif(strcmp(optS.costType, 'L2'))
    patchDist = patchDist.^2;
end

% Apply weights
patchDist = bsxfun(@times, patchDist, optS.wPatch);
costApp  = squeeze(sum(sum(patchDist, 1),2));
end

function cost = sc_patch_cost_coherence(trgPos, srcPosMap, srcTform, opt)

% SC_PATCH_COST_COHERENCE: spatial coherence cost
%
% Input
%   - trgPos:    target patch positions [numPix] x [2]
%   - srcPosMap: source patch map [imgH] x [imgW] x [2]
%   - srcPos:    source patch positions [numPix] x [2]
%   - srcTfmG:   source patch geometric transformation [numPix] x [9]
%   - opt:       parameters
% Output:
%   - cost:      spatio-temporal coherence cost

numPix = size(trgPos,1);
[imgH, imgW, ~] = size(srcPosMap);

% initialize coherence cost
cost = zeros(numPix, 1, 'single');

% =========================================================================
% Compute spatial coherence cost
% =========================================================================
for i = 1:4
    % source patch position prediction
    v = opt.propDir(i,:);
    srcPosP  = sc_trans_tform(srcTform, v);
    srcPosP =  srcPosP(:,7:8);

    % source patch positions of neighboring target patches
    trgPosN = bsxfun(@plus, trgPos, v);
    trgIndN = uint32(sub2ind([imgH, imgW], trgPosN(:,2), trgPosN(:,1)));
    srcPosN = sc_uvMat_from_uvMap(srcPosMap,  trgIndN);

    validSrc = (srcPosN(:,1) ~= 0);

    % add cost if the differences are high
    diff           = zeros(numPix, 1, 'single');
    diff(validSrc) = sum(abs(srcPosP(validSrc,:) - srcPosN(validSrc,:)), 2) > 1;
    cost    = cost + diff;
end

% cost = opt.lambdaCoherence*cost;

end

function costPlane = sc_patch_cost_plane(mLogLPlaneProb, uvPlaneIDData, trgPixSub, srcPixSub)

% SC_PATCH_COST_PLANE
%
% Compute planar costs (See Eqn 11 in the paper)

[imgH, imgW, numPlane] = size(mLogLPlaneProb);

srcPixSub     = round(srcPixSub);
uvPlaneIDData = double(uvPlaneIDData);

trgPixIndCur = sub2ind([imgH, imgW, numPlane], trgPixSub(:,2), trgPixSub(:,1), uvPlaneIDData);
srcPixIndCur = sub2ind([imgH, imgW, numPlane], srcPixSub(:,2), srcPixSub(:,1), uvPlaneIDData);

costPlane = mLogLPlaneProb(trgPixIndCur) + mLogLPlaneProb(srcPixIndCur);

end

function costProx = sc_patch_cost_prox(srcPos, trgPos, uvDtBdPixPos, optS)

% SC_PATCH_COST_PROX

% Encourage to sample patches near to the target patch

d = srcPos - trgPos;
d = sqrt(sum(d.^2,2));

d = d/optS.imgSize;
uvDtBdPixPos = uvDtBdPixPos/optS.imgSize;

% costProx = max(0, d - optS.proxThres);
% Shrinkage thresholding
costProx = max(0, d - uvDtBdPixPos - optS.proxThres);
% costProx = max(0, d - optS.proxThres);

end

function costDirect = sc_patch_cost_direct(uvPlaneIDData, trgPos, srcPos, modelPlane, optS)

% SC_PATCH_COST_DIRECT
%
% Compute the directional cost (See Eqn 13 in the paper)
%
% Input
%   -
% Output
%   -

numUvPix = size(trgPos, 1);
costDirect = optS.lambdaDirect*ones(numUvPix, 2, 'single');

for indPlane = 1: modelPlane.numPlane
    % Retrieve the uv pixels that have the current plane label
    uvPlaneIndCur  = uvPlaneIDData == indPlane;
    numPlanePixCur = sum(uvPlaneIndCur);

    if(indPlane == modelPlane.numPlane)
        costDirect(uvPlaneIndCur, :) = optS.imgSize*optS.directThres;
    else
        % The rectifying transformation for the plane
        rectMat = modelPlane.rectMat{indPlane};
        h7 = rectMat(3,1);
        h8 = rectMat(3,2);

        if(numPlanePixCur~=0)
            trgPosCur = trgPos(uvPlaneIndCur, :) - 1;
            srcPosCur = srcPos(uvPlaneIndCur, :) - 1;

            for iTheta = 1:2
                rotMat = modelPlane.rotMat{indPlane, iTheta};

                rotRecMat = rotMat;
                rotRecMat(3,1) = h7;    rotRecMat(3,2) = h8;
                rotRecMat = rotRecMat';

                trgPosCurRect = cat(2, trgPosCur, ones(numPlanePixCur,1))*rotRecMat;
                trgPosCurRect = bsxfun(@rdivide, trgPosCurRect, trgPosCurRect(:,3));

                % Source patch center position in the rectified domain
                srcPosCurRect = cat(2, srcPosCur, ones(numPlanePixCur,1))*rotRecMat;
                srcPosCurRect = bsxfun(@rdivide, srcPosCurRect, srcPosCurRect(:,3));

                costDirect(uvPlaneIndCur, iTheta) = abs(srcPosCurRect(:,2) - trgPosCurRect(:,2));
            end
        end
    end
end

costDirect = min(costDirect, [], 2);
costDirect = min(costDirect/optS.imgSize, optS.directThres);

end


filename='RVE_Square_Triangle_FineFine';
ptype = 'MICRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'horizontal';
cost={'chomog_alphabeta'};
weights=[1 0.1];
constraint = {'volumeConstraint'};
optimizer = 'SLERP';
incrementFactor = 1;
designVariable = 'LevelSet';
filterType = 'P1';

nsteps = 1;
Vfrac_final = 0.5;
Perimeter_target=1;
optimality_final =1e-3;
constr_final =1e-3;

Vfrac_initial = 1;
optimality_initial = 1e-3;
constr_initial = 1e-3;

TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;

%Micro
epsilon_isotropy_initial=1e-1;
epsilon_isotropy_final = 1e-3;
micro.alpha =[1 1 0]';
micro.beta =[1 1 0]';

% For all tests
plotting = false;
printing = false;
monitoring = false;
maxiter = 3;


function [acc_stl] = STL(X_src,y_src,X_tar,y_tar,dim)
% Stratified Transfer Learning for Cross-domain Activity Recognition.
% Jindong Wang, Yiqiang Chen, Lisha hu, Xiaohui Peng, and Philip S. Yu.
% 2018 IEEE International Conference on Pervasive Computing and Communications (PerCom).

%% Inputs:
%%%% X_src : Source domain feature matrix, n_sample * n_dim
%%%% y_src : Source domain label vector, n_sample * 1
%%%% X_tar : Target domain feature matrix, n_sample * n_dim
%%%% y_src : Target domain label vector, n_sample * 1
%%%% dim   : Dimension after STL, an integer
%% Output:
%%%% acc_stl: accuracy of the algorithm

    label_set = unique(y_src(:));
    num_tree = 30;
    %voting
    %%RF
    [predict_label_rf,accuracy_rf] = jdrf(X_src,y_src,X_tar,y_tar,30);
    %%SVM
    [predict_label_svm,accuracy_svm,~] = jdsvm(X_src,y_src,X_tar,y_tar,100);
    %%KNN
    [predict_label_knn,accuracy_knn] = jdknn(X_src,y_src,X_tar,y_tar,5);
    %%voting
    label_voting = [];
    for i = 1 : size(y_tar,1)
        if predict_label_rf(i) == predict_label_svm(i)
            label_voting(i) = predict_label_rf(i);
        elseif predict_label_rf(i) == predict_label_knn(i)
            label_voting(i) = predict_label_rf(i);
        elseif predict_label_svm(i) == predict_label_knn(i)
            label_voting(i) = predict_label_svm(i);
        else
            label_voting(i) = -1;
        end
    end
    label_voting = label_voting';
    %get residual
    r_index = label_voting(:,1) == -1;
    X_tar_residual = X_tar(r_index,:);
    y_tar_residual = y_tar(r_index,:);

    %get candidate
    c_index = label_voting(:,1) ~= -1;
    X_tar_candidate = X_tar(c_index,:);
    y_tar_candidate = y_tar(c_index,:);
    label_candidate = label_voting(c_index);
    conmat1 = confusionmat(label_candidate,y_tar_candidate);
    %in-class transfer
    %%%new candidates and source domain
    X_tar_candidate_new = [];
    y_tar_candidate_new = [];
    X_src_new = [];
    y_src_new = [];
    X_tar_candidate_old = [];
    y_tar_candidate_old = [];
    for i = 1 : size(label_set,1)
        class_index = label_set(i);
        %source data in that class i
        src_index_i = y_src(:) == class_index;
        X_src_i = X_src(src_index_i,:);
        y_src_i = y_src(src_index_i,:);
        %candidate data in that class i
        tar_index_i = label_candidate(:) == class_index;
        X_tar_candidate_i = X_tar_candidate(tar_index_i,:);
        y_tar_candidate_i = y_tar_candidate(tar_index_i,:);
        X_tar_candidate_old = [X_tar_candidate_old;X_tar_candidate_i];
        y_tar_candidate_old = [y_tar_candidate_old;y_tar_candidate_i];
        %TCA
        [X_src_new_i,X_tar_candidate_new_i] = MyTCA(X_src_i,X_tar_candidate_i,dim);
        %merge
        X_src_new = [X_src_new;X_src_new_i];
        y_src_new = [y_src_new;y_src_i];
        X_tar_candidate_new = [X_tar_candidate_new;X_tar_candidate_new_i];
        y_tar_candidate_new = [y_tar_candidate_new;y_tar_candidate_i];
    end
    %train model on new candidate
    [predicted_label_candidate,acc_candidate] = ...
        jdrf(X_src_new,y_src_new,X_tar_candidate_new,y_tar_candidate_new,num_tree);
    conmat2 = confusionmat(predicted_label_candidate,y_tar_candidate_new);
    %train model on old candidate and predict on residual
    [predicted_label_residual,acc_residual] = jdrf(X_tar_candidate_old,predicted_label_candidate,X_tar_residual,y_tar_residual,num_tree);
    %calculate accuracy
    acc_stl = mean([predicted_label_candidate;predicted_label_residual] == [y_tar_candidate_new;y_tar_residual]);

end


% op_getcoilcombos_specReg.m
% Jamie Near, McGill University 2014.
%
% USAGE:
% coilcombos=op_getcoilcombos_specReg(file_or_struct,tmin,tmax,point);
%
% DESCRIPTION:
% This funciton finds the relative coil phases and amplitudes.  Coil phases
% are found by fitting in the time domain. (In the original
% op_getcoilcombos, the phases were determined simply by observation of the
% pointth point in the time domain).  The "Base" receiver channel is
% Determined as the one with the highest signal (all other coil channels
% will be registered to that channel.
%
% INPUTS:
% file_or_struct     = this function will accept either a string filename or
%                     the name of a structure.  If the input is a string,
%                     the program will read in the data corresponding to
%                     that filename.  If the input is a structure, it will
%                     operate on that structure.
% tmin               = The earliest timepoint in the fid to be used for
%                     spectral registration.  (Optional.  Default=0 sec);
% tmax               = The latest timepoint in the fid to be used for
%                     spectral registration.  (Optional.  Default=0.2 sec);
% point              = The index of the datapoint in the fid that is used
%                     for determination of Signal intensity. (Optional.
%                     Default = 1);
%
% OUTPUTS:
% coilcombos         = Structure containing the calculated coil weights and phases.

function coilcombos=op_getcoilcombos_specReg(file_or_struct,tmin,tmax,point);

if isstr(file_or_struct)
    in=io_loadspec_twix(file_or_struct);
else
    in=file_or_struct;
end

if in.flags.addedrcvrs || ~in.dims.coils
    %If there is only one coil element, do nothing:
    disp('WARNING:  Only one receiver channel found!  Coil phase will be 0.0 and coil amplitude will be 1.0.');
    coilcombos.ph=0;
    coilcombos.sig=1;
else
    %If there are multiple coil elements (most cases), find the complex
    %weightings

    if nargin<4
        point=1;
        if nargin<3
            tmax=0.2;
            if nargin<2
                tmin=0;
            end
        end
    end

    B=in.sz(in.dims.coils);

    coilcombos.ph=zeros(B,1);
    coilcombos.sig(:,1)=abs(in.fids(point,:,1,1));
    bestSNRindex=find(coilcombos.sig(:,1)==max(coilcombos.sig(:,1)))
    phGuess=0;

    disp('aligning all coils to the first coil');
    base=phase(in.fids(in.t>=tmin & in.t<tmax,bestSNRindex,1,1));
    begin=1;
    for n=begin:B
        %disp(['Fitting coil number ' num2str(n) 'to first coil']);
        phFit=nlinfit(in.fids(in.t>=tmin & in.t<tmax,n,1,1)/coilcombos.sig(n,1),base,@op_phaseShiftRealNest,phGuess);
        coilcombos.ph(n,1)=(-1*phFit*pi/180);
        %     subplot(1,2,1);
        %     plot(in.ppm,in.specs(:,1,1,1)/coilcombos.sig(1,1),in.ppm,fftshift(ifft(addphase(in.fids(:,n,1,1),phFit)))/coilcombos.sig(n,1));xlim([4 5.5]);
        %     subplot(1,2,2);
        %     plot(in.t,in.fids(:,1,1,1)/coilcombos.sig(1,1),in.t,addphase(in.fids(:,n,1,1),phFit)/coilcombos.sig(n,1));xlim([0 tmax*2]);
        %     pause;

    end

    coilcombos.ph=coilcombos.ph+(phase(in.fids(point,bestSNRindex,1,1)));
    %Now normalize the coilcombos.sig so that the max amplitude is 1;
    coilcombos.sig=coilcombos.sig/max(coilcombos.sig);

end

    function y=op_phaseShiftRealNest(pars,input);
        p=pars(1);     %Phase Shift [deg]

        fid=input(:);
        y=phase(addphase(fid,p));

    end
end


function imageHandle = prtPlotUtilImageEvaledClassifier(DS,linGrid,gridSize,cMap)
% Internal function,
% xxx Need Help xxx

nDims = size(linGrid,2);

switch nDims
    case 1
        imageHandle = imagesc(linGrid(:,1),linGrid(:,2),DS);
        set(gca,'YTickLabel',[])
        colormap(cMap)
    case 2
        xx = reshape(linGrid(:,1),gridSize);
        yy = reshape(linGrid(:,2),gridSize);
        imageHandle = imagesc(xx(1,:),yy(:,1),DS);
        colormap(cMap)
    case 3
        xx = reshape(linGrid(:,1),gridSize);
        yy = reshape(linGrid(:,2),gridSize);
        zz = reshape(linGrid(:,3),gridSize);
        imageHandle = slice(xx,yy,zz,DS,max(xx(:)),max(yy(:)),[min(zz(:)),mean(zz(:))]);
        view(3)
        colormap(cMap)
end
axis tight;
axis xy;


classdef prtClassLibSvm < prtClass
    % prtClassLibSvm  Support vector machine classifier using LibSvm
    %
    %   CLASSIFIER = prtClassLibSvm returns a SVM Classifier using the
    %   SVM toolbox "LibSvm" which provides a fast interface to training
    %   and testing support vector machines.
    %
    %   Note: requires libSvm, which should be in nfPrt\util\libsvm-mat-2.91-1
    %   On linux, you may need to re-build the LibSVM Binaries.  See the
    %   documentation for LibSvm (link below) for more information.
    %
    %    A prtClassLibSvm object inherits all properties from the abstract class
    %    prtClass. In addition is has the following properties; complete
    %    documentation for these properties can be found here:
    %
    %       http://www.csie.ntu.edu.tw/~cjlin/libsvm/
    %
    %         svmType       - Whether to use a C-SVM, nu-SVM, one-class
    %                        SVM, epsilon-SVR, or nu-SVR
    %         kernelType    - Kernel type to use - linear (0), polynomial (1),
    %                         rbf (2, default), sigmoid (3), or
    %                         user-defined (4) - see below
    %         degree        - Kernel function parameter (some kernels)
    %         gamma         - Kernel function parameter (some kernels)
    %         coef0         - Kernel function parameter (some kernels)
    %         cost          - Cost parameter
    %         nu            - nu parameter (nu-SVM's)
    %         pEpsilon      - Loss function parameter (epsilon-SVMs)
    %         cachesize     - Memory cache in MB (can affect speed,
    %                        computer dependent)
    %         eEpsilon      - Termination tolerance
    %         shrinking     - Use shrinking heuristic?
    %         probabilityEstimates - Output probability estimates?
    %         weight        - Class-specific weight parameter in C-SCM
    %
    %   Default values are:
    %     svmType = 0;
    %     kernelType = 2;
    %     degree = 3;
    %     gamma = nan;
    %     coef0 = 0;
    %     cost = 1;
    %     nu = .5;
    %     pEpsilon = .1;
    %     cachesize = 100;
    %     eEpsilon = 0.001;
    %     shrinking = 1;
    %     probabilityEstimates = 0;
    %     weight = [1 1];
    %
    %     userSpecKernel = [];  %only for kernelType = 4, see below
    %
    %   prtClassLibSvm allows the specification of user-defined kernels by
    %   setting svm.kernelType to 4.  This requires further specification
    %   of svm.userSpecKernel.  svm.userSpecKernel must be either a
    %   function handle, fn(x,y) which outputs a matrix of size
    %   size(x,1) x size(y,1), or userSpecKernel can be a prtKernel object.
    %
    %   For example:
    %     svm.kernelType = 4;
    %     svm.userSpecKernel = @(x,y) (x*y'); % correlation kernel
    %
    %     svm.kernelType = 4;
    %     svm.userSpecKernel = prtKernelHyperbolicTangent;
    %
    %
    %   Additional options can be specified by modifying the field
    %   obj.libSvmOptions using the format found here:
    %   http://www.csie.ntu.edu.tw/~cjlin/libsvm/
    %
    %   More documentation can be found here:
    %   http://www.csie.ntu.edu.tw/~cjlin/papers/libsvm.pdf
    %
    %   Note: the LibSvm will output estimated percent correct values to
    %   the screen during processing; because of the way the PRT trains and
    %   tests, these should be ignored during training and plotting. (To be
    %   fixed)
    %
    %   %Example usage:
    %     TestDataSet = prtDataGenUnimodal;       % Create some test and
    %     TrainingDataSet = prtDataGenUnimodal;   % training data
    %     classifier = prtClassLibSvm;              % Create a classifier
    %     classifier = classifier.train(TrainingDataSet);    % Train
    %     classified = run(classifier, TestDataSet);         % Test
    %     percentCorr = prtScorePercentCorrect(classified,TestDataSet);
    %     subplot(2,1,1);
    %     classifier.plot;
    %     subplot(2,1,2);
    %     [pf,pd] = prtScoreRoc(classified,TestDataSet);
    %     h = plot(pf,pd,'linewidth',3);
    %     title('ROC'); xlabel('Pf'); ylabel('Pd');

    %   Notes for doc:
    %       1) The LIBSVM Matlab interface always outputs something like:
    %   Accuracy = 62.63% (6263/10000) (classification)
    %   when you try and run it on an unlabeled data set (in testing) or
    %   when you plot it.  This is because whoever made the interface
    %   didn't think to give us a way that I can see to turn off that
    %   output. (Actually this has now been disabled.)
    %
    %       2) All the parameters that you set below actually get set for
    %       real when we call libSvmOptionString and libSvmOptionStringTest
    %       in train.  The calling syntax is command-line-esque, but I
    %       think I check for all the right requirements.
    %
    %

    properties (SetAccess=private)
        name = 'LibSVM Support Vector Machine'  % Support Vector Machine
        nameAbbreviation = 'LibSVM'         % SVM
        isNativeMary = false;  % False
    end

    properties

        svmType = 0;
        kernelType = 2;
        degree = 3;
        gamma = nan;
        coef0 = 0;
        cost = 1;
        nu = .5;
        pEpsilon = .1;
        cachesize = 100;
        eEpsilon = 0.001;
        shrinking = 1;
        probabilityEstimates = 0;
        weight = [1 1];

        libSvmOptions = '';

        userSpecKernel = [];
    end
    properties (Hidden = true)
        %Note, the libSvm has different opinions of what classes 1 and 0
        %mean than we do; gain takes care of the difference.
        gain = 1;
        trainedSvm
        libSvmOptionsTest
    end

    methods
        function obj = set.svmType(obj,val)
            assert(isscalar(val) && ismember(val,[0 1 2 3 4]),'svmType must be one of 0,1,2,3,4; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.svmType = val;
        end
        function obj = set.kernelType(obj,val)
            assert(isscalar(val) && ismember(val,[0 1 2 3 4]),'kernelType must be one of 0,1,2,3,4; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.kernelType = val;
        end
        function obj = set.degree(obj,val)
            assert(isscalar(val) && prtUtilIsPositiveInteger(val),'degree must be a positive integer; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.degree = val;
        end
        function obj = set.gamma(obj,val)
            if isnan(val)
                return
            end
            if ischar(val)
                obj.gamma = val;
            else
                assert(isscalar(val) && val > 0,'gamma must be a positive value; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
                obj.gamma = val;
            end
        end
        function obj = set.coef0(obj,val)
            assert(isscalar(val),'coef0 must be a scalar; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.coef0 = val;
        end
        function obj = set.cost(obj,val)
            assert(isscalar(val) && val > 0,'cost must be a positive value; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.cost = val;
        end
        function obj = set.nu(obj,val)
            assert(isscalar(val) && val > 0,'nu must be a positive value; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.nu = val;
        end
        function obj = set.pEpsilon(obj,val)
            assert(isscalar(val) && val > 0,'pEpsilon must be a positive value; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.pEpsilon = val;
        end
        function obj = set.cachesize(obj,val)
            assert(isscalar(val) && val > 0,'cachesize must be a positive value; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.cachesize = val;
        end
        function obj = set.eEpsilon(obj,val)
            assert(isscalar(val) && val > 0,'eEpsilon must be a positive value; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.eEpsilon = val;
        end
        function obj = set.shrinking(obj,val)
            val = double(val);
            assert(isscalar(val) && ismember(val,[0 1]),'shrinking must be one of 0,1; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.shrinking = val;
        end
        function obj = set.probabilityEstimates(obj,val)
            val = double(val);
            assert(isscalar(val) && ismember(val,[0 1]),'probabilityEstimates must be one of 0,1; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.probabilityEstimates = val;
        end
        function obj = set.weight(obj,val)
            assert(numel(val)==2 && all(val > 0),'weight must be a positive 2-element vector; see the instructions at http://www.csie.ntu.edu.tw/~cjlin/libsvm/ for more information');
            obj.weight = val;
        end

        function self = prtClassLibSvm(varargin)
            self = prtUtilAssignStringValuePairs(self,varargin{:});
        end
    end

    methods (Access=protected, Hidden = true)

        function self = trainAction(self,dataSet)

            % Its ok to have 1 class if its a 1 class classifier
            if dataSet.nClasses ~= 2 && self.svmType ~=2
                error('prt:prtClassLibSvm:UnaryData','prtClassLibSvm requires binary data for training');
            end
            if dataSet.nClasses ~= 1 && self.svmType ==2
                % You can avoid this warning using
                % prtOutlierRemovalFnTargets in your algorithm spec.
                warning('prt:prtClassLibSvm:UnaryData','prtClassLibSvm requires unary data for training when svmType = 2; using max(dataSet.uniqueClasses) as the default single class.');
                dataSet = dataSet.retainClasses(max(dataSet.uniqueClasses));
            end

            training_label_vector = dataSet.getTargetsAsBinaryMatrix;
            training_label_vector = double(training_label_vector(:,end)); %zeros and ones
            training_instance_matrix = dataSet.getObservations;
            self.libSvmOptions = self.libSvmOptionString(dataSet);
            self.libSvmOptionsTest = self.libSvmOptionStringTest(dataSet);

            if self.kernelType == 4
                %self.userSpecKernel = prtKernelRbfNdimensionScale;
                if ~isa(self.userSpecKernel,'prtKernel') && ~isa(self.userSpecKernel,'function_handle')
                    error('prtClassLibSvm:KernelType4','For kernelType = 4 (user-specified kernel), svm.userSpecKernel must be a prtKernel or function handle');
                end
                if isa(self.userSpecKernel,'prtKernel')
                    self.userSpecKernel = self.userSpecKernel.train(dataSet);
                    kernelMat = self.userSpecKernel.run(dataSet);
                    training_instance_matrix = kernelMat.data;
                else
                    training_instance_matrix = self.userSpecKernel(dataSet.X,dataSet.X);
                end
                training_instance_matrix = cat(2,(1:size(training_instance_matrix,1))',training_instance_matrix);
            end
            self.trainedSvm = prtExternal.libsvm.svmtrain(training_label_vector, training_instance_matrix, self.libSvmOptions);

            %Need to figure out whether to flip SVM outputs:
            yOut = runAction(self,dataSet);
            auc = prtScoreAuc(yOut.retainLabeled);

            %libSVM has some weird rules about target names.  the first target type it finds is called H1...
            % We can fix this either above, or here
            if auc < .5
                self.gain = -1;
            end
        end

        function DataSetOut = runAction(self,dataSet)

            testing_label_vector = double(dataSet.getTargets);
            if isempty(testing_label_vector)
                testing_label_vector = zeros(dataSet.nObservations,1);
            end

            if self.kernelType == 4
                if ~isa(self.userSpecKernel,'prtKernel') && ~isa(self.userSpecKernel,'function_handle')
                    error('prtClassLibSvm:KernelType4','For kernelType = 4 (user-specified kernel), svm.userSpecKernel must be a prtKernel or function handle');
                end
                if isa(self.userSpecKernel,'prtKernel')
                    kernelMat = self.userSpecKernel.run(dataSet);
                    testing_instance_matrix = kernelMat.data;
                else
                    %Function handle:
                    testing_instance_matrix = self.userSpecKernel(dataSet.X,self.dataSet.X);
                end
                testing_instance_matrix = cat(2,(1:size(testing_instance_matrix,1))',testing_instance_matrix);
            else
                testing_instance_matrix = dataSet.getObservations;
            end

            [dontNeed, dontNeed, decision_values] = prtExternal.libsvm.svmpredict(testing_label_vector, testing_instance_matrix, self.trainedSvm, self.libSvmOptionsTest); %#ok<ASGLU>

            DataSetOut = dataSet;
            DataSetOut = DataSetOut.setObservations(decision_values*self.gain);
        end

        function dataSetOut = runActionFast(self,x,ds)

            switch self.kernelType
                case 2
                    nFeats = size(x,2);
                    f = full(self.trainedSvm.SVs);
                    gram = prtKernelRbf.kernelFn(f,x,sqrt(nFeats));
                    yOut = ((self.trainedSvm.sv_coef'*gram)-self.trainedSvm.rho)';
                otherwise
                    error('prt:prtClassLibSvm','Unsupported kernel type for runActionFast');
            end
            dataSetOut = yOut(:)*self.gain;
        end

    end
    methods (Hidden = true)

        function str = textSummary(self)
            str = sprintf('%s: \n',class(self));
            str2 = evalc('disp(self.trainedSvm)');
            str = sprintf('%s%s',str,str2);
        end
        function optionString = libSvmOptionString(obj,dataSet)
            if isnan(obj.gamma)
                obj.gamma = 1./dataSet.nFeatures;
            end
            if ischar(obj.gamma)
                optionString = sprintf('-s %d -t %d -d %d -g %s -r %f -c %f -n %f -p %f -m %f -e %f -h %d -b %d -w0 %f -w+1 %f',...
                    obj.svmType,obj.kernelType,obj.degree,obj.gamma,obj.coef0,obj.cost,obj.nu,...
                    obj.pEpsilon,obj.cachesize,obj.eEpsilon,obj.shrinking,obj.probabilityEstimates,obj.weight(1),obj.weight(2));
            else
                optionString = sprintf('-s %d -t %d -d %d -g %f -r %f -c %f -n %f -p %f -m %f -e %f -h %d -b %d -w0 %f -w+1 %f',...
                    obj.svmType,obj.kernelType,obj.degree,obj.gamma,obj.coef0,obj.cost,obj.nu,...
                    obj.pEpsilon,obj.cachesize,obj.eEpsilon,obj.shrinking,obj.probabilityEstimates,obj.weight(1),obj.weight(2));
            end
        end
        function optionString = libSvmOptionStringTest(obj,dataSet) %#ok<INUSD>
            optionString = sprintf('-b %d',obj.probabilityEstimates);
        end
    end

    methods (Hidden)
        function str = exportSimpleText(self) %#ok<MANU>
            titleText = sprintf('%% prtClassLibSvm\n');
            svmSvText = prtUtilMatrixToText(full(self.trainedSvm.SVs),'varName','supportVectors');
            svmSvCoeffText = prtUtilMatrixToText(full(self.trainedSvm.sv_coef),'varName','svCoefficients');
            svmSigmaText = prtUtilMatrixToText(sqrt(size(self.trainedSvm.SVs,2)),'varName','sigma');
            svmRhoText = prtUtilMatrixToText(self.trainedSvm.rho,'varName','rho');
            str = sprintf('%s%s%s%s%s',titleText,svmSvText,svmSvCoeffText,svmSigmaText,svmRhoText);
        end
    end
end


% colony_count.m demo script
% Runs colony_count on example image and displays segmentation results.

% Load image.
I = imread('plate_example.jpg');

% Call function.
% Count is number of colonies, markers is the colony markers and mask is
% the colony segmentation. Count == # of components in markers.

% Optional parameter, this is the default.
% Should encompass internal radius of Petri dish.
radii = 115:1:130;

[count,markers,mask] = colony_count(I,radii);

disp([num2str(count) ' colonies detected.']);

% Overlay image with markers and mask.
J = rgb2gray(I);
R = J; G = J; B = J;
R(mask) = 255; R(markers) = 0;
G(mask) = 0; G(markers) = 255;
B(mask) = 0; B(markers) = 0;
RGB = cat(3,R,G,B);
figure();imshow(RGB);

% Overlay image with just markers.
R = J; G = J; B = J;
R(markers) = 0;
G(markers) = 255;
B(markers) = 0;
RGB = cat(3,R,G,B);
figure();imshow(RGB);


function [status, results] = mrtrix_tensor_generate (in_file, out_file, b_file, verbose)

%
% Calculate diffusion tensors.
%
% Parameters
% ----------
% in_file: The name of a diffusion file in .mif format
% out_file: The name of the resulting dti file in .mif format
% b_file: The name of a mrtrix format gradient vector file (default: 'encoding.b')
%
% Returns
% -------
% status: whether (0) or not (1) the operation succeeded
% results: the results of the operation in the terminal
%
% Notes
% -----
% http://www.brain.org.au/software/mrtrix/tractography/preprocess.html

if notDefined('verbose')
   verbose = true;
end
if notDefined('b_file')
    b_file = 'encoding.b';
end

% This command generates  tensors:
cmd_str = sprintf('dwi2tensor %s %s -grad %s',in_file, outfile, b_file);

% Send it to mrtrix:
[status,results] = mrtrix_cmd(cmd_str,verbose);


%h = guidata(6);
h = guidata(gcf);
fg = h.fiberGroups(h.curFiberGroup);
% interp method can be 'nearest'|'trilin'|'spline'. If you are going to
% just average a bunch of these values, it's probably best to use nearest.
interp = 'nearest';
md = dtiGetValFromFibers(h.dt6, fg, inv(dtiGet(h,'dt6xform')),'md',interp);
fa = dtiGetValFromFibers(h.dt6, fg, inv(dtiGet(h,'dt6xform')),'fa',interp);
ln = dtiGetValFromFibers(h.dt6, fg, inv(dtiGet(h,'dt6xform')),'linearity',interp);

%alignSlice = [nan -55 nan]; % the alignment position (in mm from AC)
alignSlice = [nan nan 28]; % the alignment position (in mm from AC)
ax = find(~isnan(alignSlice));
sl = alignSlice(ax);
if(length(ax)~=1) error('specify just one alignment axis!'); end
if(ax==1) axName='LR'; elseif(ax==2) axName='AP'; else axName='SI'; end
nPts = 20;
nFibers = length(fg.fibers);
fiberFa = zeros(nFibers, nPts*2+1)*nan;
fiberMd = fiberFa; fiberLn = fiberFa;
fiberCoords = zeros(nFibers, nPts*2+1,3)*nan;
for(ii=1:length(fg.fibers))
    d = abs(fg.fibers{ii}(ax,:)-alignSlice(ax));
    nearInd = find(d==min(d));
    if(nearInd-nPts<=1 | nearInd+nPts>=length(fg.fibers{ii}))
        continue;
    end
    fDir = fg.fibers{ii}(ax,[nearInd-1,nearInd+1]);
    inds = [nearInd-nPts:nearInd+nPts];
    % We skip the fiber end-points, since the FA there can be misleading
    if(fDir(2)<fDir(1)) inds = fliplr(inds); end
    goodInds = inds>1 & inds<length(d);
    fiberFa(ii,goodInds) = fa{ii}(inds(goodInds));
    fiberMd(ii,goodInds) = md{ii}(inds(goodInds));
    fiberLn(ii,goodInds) = ln{ii}(inds(goodInds));
    fiberCoord(ii,goodInds,:) = fg.fibers{ii}(:,inds(goodInds))';
end

xlab = [axName ' step (mm)'];
x = [sl-nPts:sl+nPts];
%x = mean(fiberCoord(:,:,ax),1);

mnFa = nanmean(fiberFa);
sdFa = nanstd(fiberFa);
figure;errorbar(x,mnFa,sdFa,sdFa);
hold on;
plot(x,min(fiberFa),'c');
hold off;
y = get(gca,'YLim');
line([sl,sl],y,'color','r');
xlabel(xlab); ylabel('Mean FA');

mnMd = nanmean(fiberMd);
sdMd = nanstd(fiberMd);
figure;errorbar(x,mnMd,sdMd,sdMd);
y = get(gca,'YLim');
line([sl,sl],y,'color','r');
xlabel(xlab); ylabel('Mean Diffusivity (mm^2/s*10^-^6)');

mnLn = nanmean(fiberLn);
sdLn = nanstd(fiberLn);
figure;errorbar(x,mnLn,sdLn,sdLn);
y = get(gca,'YLim');
line([sl,sl],y,'color','r');
xlabel(xlab); ylabel('Linearity Index');

error('stop here');

tdir = '/biac2/wandell2/data/reading_longitude/templates/child/SIRL53warp3';
h = guidata(1);
fg = h.fiberGroups(h.curFiberGroup);
alignSlice = [nan nan 28]; % the alignment position (in mm from AC)
ax = find(~isnan(alignSlice));
sl = alignSlice(ax);
if(length(ax)~=1) error('specify just one alignment axis!'); end
if(ax==1) axName='LR'; elseif(ax==2) axName='AP'; else axName='SI'; end
nPts = 20;
nFibers = length(fg.fibers);
% interp method can be 'nearest'|'trilin'|'spline'. If you are going to
% just average a bunch of these values, it's probably best to use nearest.
interp = 'nearest';

snFiles = findSubjects(tdir, '*_sn*',{});
N = length(snFiles);
gFiberFa = zeros(nFibers, nPts*2+1, N)*nan;
gFiberMd = fiberFa; fiberLn = fiberFa;
gFiberCoords = zeros(nFibers, nPts*2+1,3)*nan;
for(subNum=1:N)
    disp(['Loading ' snFiles{subNum} '...']);
    dt = load(snFiles{subNum});
    dt.dt6(isnan(dt.dt6)) = 0;
    md = dtiGetValFromFibers(dt.dt6, fg, inv(dt.xformToAcPc), 'md', interp);
    fa = dtiGetValFromFibers(dt.dt6, fg, inv(dt.xformToAcPc), 'fa', interp);
    ln = dtiGetValFromFibers(dt.dt6, fg, inv(dt.xformToAcPc), 'linearity', interp);

    for(ii=1:length(fg.fibers))
        d = abs(fg.fibers{ii}(ax,:)-alignSlice(ax));
        nearInd = find(d==min(d));
        fDir = fg.fibers{ii}(ax,[nearInd-1,nearInd+1]);
        inds = [nearInd-nPts:nearInd+nPts];
        % We skip the fiber end-points, since the FA there can be misleading
        if(fDir(2)<fDir(1)) inds = fliplr(inds); end
        goodInds = inds>1 & inds<length(d);
        gFiberFa(ii,goodInds,subNum) = fa{ii}(inds(goodInds));
        gFiberMd(ii,goodInds,subNum) = md{ii}(inds(goodInds));
        gFiberLn(ii,goodInds,subNum) = ln{ii}(inds(goodInds));
        gFiberCoord(ii,goodInds,:) = fg.fibers{ii}(:,inds(goodInds))';
    end
end

ssMnFa = nanmean(fiberFa, 1);
%sdFa = nanstd(fiberFa);
gMnFa = squeeze(nanmean(gFiberFa, 1));
mnGMnFa = nanmean(gMnFa, 2);
sdGMnFa = nanstd(gMnFa, 0, 2);
semGMnFa = sdGMnFa/sqrt(N-1);
figure;errorbar(x, mnGMnFa, semGMnFa, semGMnFa);
hold on;
plot(x,ssMnFa,'r');
hold off;
y = get(gca,'YLim');
line([sl,sl],y,'color','r');
xlabel(xlab); ylabel('Mean FA');

ssMnMd = nanmean(fiberMd, 1);
%sdFa = nanstd(fiberFa);
gMnMd = squeeze(nanmean(gFiberMd, 1));
mnGMnMd = nanmean(gMnMd, 2);
sdGMnMd = nanstd(gMnMd, 0, 2);
semGMnMd = sdGMnMd/sqrt(N-1);
figure;errorbar(x, mnGMnMd, semGMnMd, semGMnMd);
hold on;
plot(x,ssMnMd,'r');
hold off;
y = get(gca,'YLim');
line([sl,sl],y,'color','r');
xlabel(xlab); ylabel('Mean MD (mm^2/s*10^-^6)');


function cx = cscal ( n, ca, cx, incx )

%*****************************************************************************80
%
%% CSCAL scales a complex vector by a constant.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 April 2006
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
%    Basic Linear Algebra Subprograms for Fortran Usage,
%    Algorithm 539,
%    ACM Transactions on Mathematical Software,
%    Volume 5, Number 3, September 1979, pages 308-323.
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Input, complex CA, the multiplier.
%
%    Input, complex CX(*), the vector to be scaled.
%
%    Input, integer INCX, the increment between successive entries of CX.
%
%    Output, complex CX(*), the scaled vector.
%
  cx(1:incx:1+(n-1)*incx) = ca * cx(1:incx:1+(n-1)*incx);

  return
end


function foot_clearance(nlp, bounds, frame)
    % constraints for swing foot clearance

    domain = nlp.Plant;
    x = domain.States.x;

    pos = getCartesianPosition(domain, frame);
    constraint_func = SymFunction(['foot_clearance_',domain.Name], pos(3), {x});

    % Foot Clearance Middle
    numNode = nlp.NumNode;
    addNodeConstraint(nlp, constraint_func, {'x'}, 'first', 0, 0, 'Nonlinear');
    addNodeConstraint(nlp, constraint_func, {'x'}, floor(numNode/2)+1, ...
        bounds.constrBounds.foot_clearance.lb, ...
        bounds.constrBounds.foot_clearance.ub,'Nonlinear');
    addNodeConstraint(nlp, constraint_func, {'x'}, 'last', 0, 0, 'Nonlinear');
end


function imout=padimage(im, sizeimout)

sizeim = size(im);

sizedifhalf = floor((sizeimout-sizeim)/2);

imout = padarray(im, sizedifhalf);

sizedif = sizeimout-size(imout);

if sizedif(1)>0
    imout = [imout; zeros(1,size(imout,2))];
end
if sizedif(2)>0
    imout = [imout, zeros(size(imout,1),1)];
end


function f=fun1(p)
f=1.0/(p^2);


function rgb = oklab2rgb(ok)
  % OKLAB2RGB Convert colors stored in OKLab color space to RGB color space
  %
  % rgb = oklab2rgb(ok)
  %
  % Inputs:
  %   ok  #h by #w by 3 image of colors or #ok by 3 list of colors
  % Outputs:
  %   rgb  converted ok colors (same size as ok)
  %
  % See also: rgb2lin, lin2rgb, oklab2lin , rgb2oklab, lin2oklab
  lin = oklab2lin(ok);
  rgb = lin2rgb(lin);
end


function varargout = biharm(varargin)
%BIHARM   Biharmonic operator of a CHEBFUN2.
%   B = BIHARM(F) returns a CHEBFUN2 representing the biharmonic operator
%   applied to F.
%
%   This is shorthand for BIHARMONIC(F).
%
% See also CHEBFUN2/BIHARMONIC.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Call SEPARABLEAPPROX/BIHARM:
[varargout{1:nargout}] = biharm@separableApprox(varargin{:});

end


function PD = pwrDiagramPD(T, PC)
% function PD = pwrDiagramPD(T, PC)
%
% T: triangulation
% PC: power centers of triangles in T
%
% The output cell PD contains pieces of the power diagram, indexed by
% dimension. PD{mP} contains pieces of dimension zero (power centers that
% correspond to fully-dimensional pieces of the triangulation T) and PD{1}
% contains fully-dimensional regions of the power diagram (corresponding to
% vertices of the triangulation).

P = piecesPD(T);
mP = size(P,1);
PD = cell(mP,1);

for i=1:mP
    EA = edgeAttPD(T, P{i});
    for j=1:size(EA,1);
        EA{j} = PC(EA{j},:);
    end
    PD{i} = EA;
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Spherical Harmonic Modeling and Analysis Toolkit (SPHARM-MAT) is a 3D
% shape modeling and analysis toolkit.
% It is a software package developed at Shenlab in Center for Neuroimaging,
% Indiana University (SpharmMat@gmail.com, http://www.iupui.edu/~shenlab/)
% It is available to the scientific community as copyright freeware
% under the terms of the GNU General Public Licence.
%
% Copyright 2009, 2010, ShenLab, Center for Neuroimaging, Indiana University
%
% This file is part of SPHARM-MAT.
%
% SPHARM-MAT is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% SPHARM-MAT is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with SPHARM-MAT. If not, see <http://www.gnu.org/licenses/>.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Goal: Fix a binary image by removing bad connectivities
% inObject: filename string of a binary object in .MAT format
% info = varargin{1}: connectivity
% info can be one of four values between 1 and 4 - '1=(6+,18), 2=(18,6+),
% 3=(6,26), 4=(26,6)'
% epsilon = varargin{2}: hole size, holes bigger than epsilon won't be
% filled
%
% 04/15/2002 - created by Li Shen
% Modified by Sungeun Kim (10-09-08)

function [bim, origin, vxsize, new_name] = fix_bad_topology(inObject, confs)

epsilon = confs.Epsilon;
switch deblank(char(confs.Connectivity))
    case '(6+,18)'
        conn = 1;
    case '(18,6+)'
        conn = 2;
    case '(6,26)'
        conn = 3;
    case '(26,6)'
        conn = 4;
end

% Read input object dataset
if ischar(inObject)
    [path,name,ext] = fileparts(inObject);

    if ~strcmp(ext, '.mat')
        disp('Input object data should be Matlab data file (*.mat)');
        return;
    end

    load(inObject);
    roi = bim;
else
    disp('Input Object should be the filename of a binary object (_bim.mat).');
    return;
end

tic;

infostr{1} = 'outlier or hole';
infostr{2} = 'vertex conn.';
infostr{3} = 'edge conn.';
infostr{4} = 'ring or hole';
infostr{5} = 'single ring';

% display information
disp('Make a simply connected volume by removing bad voxels');
disp(sprintf('(1) %s, (2) %s, (3) %s, (4) %s, (5) s', ...
              infostr{1}, infostr{2}, infostr{3}, infostr{4}, infostr{5}));

% Make binary image, in case reslice generates 2's
ind = find(roi>0); roi(ind) = 1;
vol = length(ind);
ind = find(roi<1); roi(ind) = 0;

% routine fix
roi = routine_fix(roi);
[vertices, faces] = gen_surf_data(roi,origin,vxsize);

% fill 3d holes
for k=1:3
    if (size(vertices,1)-size(faces,1)==2)
        disp('===> No 3D holes, skip');
        break;
    end
    disp('===> fixing 3D holes ...');
    roi = fill3dholes(roi,conn,epsilon,name);
    disp('===> routine fix again ...');
    roi = routine_fix(roi);
    [vertices, faces] = gen_surf_data(roi,origin,vxsize);
end

fvn = length(find(roi~=bim));
bim = roi;

disp(sprintf('fix_vox_num (%d) / vol (%d) = %f%%, save ...', ...
                      fvn, vol, fvn*100/vol));

% Save surface object to a new file
postfix = name(end-2:end);
if strcmp(postfix, 'bim') | strcmp(postfix,'fix')
    new_name = [confs.OutDirectory '/' name(1:end-3) 'fix'];
else
    new_name = [confs.OutDirectory '/' name '_fix'];
end

if exist(new_name,'file')
    prompt = {'Enter new filename:'};
    dlg_title = 'New File Name';
    num_lines = 1;
    def = {new_name};
    answer = inputdlg(prompt,dlg_title,num_lines,def);
    new_name = answer{1};
end

save(new_name, 'bim', 'origin', 'vxsize');

seconds = toc;
hours = seconds/3600;
disp(['seconds=', num2str(seconds), ' hours=', num2str(hours)]);

return;

%
% routine fix
%

function roi = routine_fix(roi)

DIM = size(roi);

fixset = [];

for j = 1:10
    [roi, fs1] = outl_hole(roi, DIM,1);
    [roi, fs2] = vertex_conn(roi, DIM,2);
    [roi, fs3] = edge_conn(roi, DIM,3);
    if (isempty(fs1) & isempty(fs2) & isempty(fs3))
        break;
    else
        if (~isempty(fs1))
            fixset(end+1:end+size(fs1,1),:) = fs1;
        end
        if (~isempty(fs2))
            fixset(end+1:end+size(fs2,1),:) = fs2;
        end
        if (~isempty(fs3))
            fixset(end+1:end+size(fs3,1),:) = fs3;
        end
    end
end

[roi, fs4] = ring_hole(roi, DIM, 4);
if (~isempty(fs4))
    fixset(end+1:end+size(fs4,1),:) = fs4;
    for j = 1:10
        [roi, fs1] = outl_hole(roi, DIM,1);
        [roi, fs2] = vertex_conn(roi, DIM,2);
        [roi, fs3] = edge_conn(roi, DIM,3);
        [roi, fs4] = ring_hole(roi, DIM,4);
        if (isempty(fs1) & isempty(fs2) & isempty(fs3) & isempty(fs4))
            break;
        else
            if (~isempty(fs1))
                fixset(end+1:end+size(fs1,1),:) = fs1;
            end
            if (~isempty(fs2))
                fixset(end+1:end+size(fs2,1),:) = fs2;
            end
            if (~isempty(fs3))
                fixset(end+1:end+size(fs3,1),:) = fs3;
            end
            if (~isempty(fs4))
                fixset(end+1:end+size(fs4,1),:) = fs4;
            end
        end
    end
end

fix_vox_num = size(fixset,1);

return;

%
% remove disconnected small components and holes
%

function [roi, fixset] = outl_hole(roi, d, infoid)

roi = reshape(roi,d);

fixset = [];

% check seperated small components (k=1)
% and then check holes
val = [0 1];
for k = 1:2
	[L, num] = bwlabeln(roi,6);

	if num>1
		% find the background
		for i = 1:num
            cnt(i) = length(find(L == i));
		end
		[bkgd_size, bkgd_ind] = max(cnt);
        sigind = find(L~=0 & L~=bkgd_ind);
        roi(sigind) = 0;
        [xs,ys,zs] = ind2sub(d, sigind);
        fixset(end+1:end+length(xs),:) = [[xs,ys,zs], xs*0+val(k), xs*0+infoid];
	end

	roi = 1-roi;
end

return;

%
% fix bad vertex connectivities
%

function [roi, fixset] = vertex_conn(roi, d, infoid)

roi = reshape(roi,d);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% work on 0 vertex connectivies
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% make a work area so that all border voxels belong to the background
w = ones(d+2);
w(2:d(1)+1,2:d(2)+1,2:d(3)+1) = roi;
wd = d+2;
ind = find(w == 0);
w = zeros(d+2);
w(2:d(1)+1,2:d(2)+1,2:d(3)+1) = roi;

[xs,ys,zs] = ind2sub(wd,ind);

h = sum([w(sub2ind(wd,xs-1,ys,zs)), ...
         w(sub2ind(wd,xs+1,ys,zs)), ...
         w(sub2ind(wd,xs,ys-1,zs)), ...
         w(sub2ind(wd,xs,ys+1,zs)), ...
         w(sub2ind(wd,xs,ys,zs-1)), ...
         w(sub2ind(wd,xs,ys,zs+1))]')';

fixset = [];

% fix ring 0 voxels (single ring)
ind1 = ind(find(h==4 & ...
                w(sub2ind(wd,xs-1,ys,zs))==0 & ...
                w(sub2ind(wd,xs+1,ys,zs))==0 ...
           ));
ind2 = ind(find(h==4 & ...
                w(sub2ind(wd,xs,ys-1,zs))==0 & ...
                w(sub2ind(wd,xs,ys+1,zs))==0 ...
           ));
ind3 = ind(find(h==4 & ...
                w(sub2ind(wd,xs,ys,zs-1))==0 & ...
                w(sub2ind(wd,xs,ys,zs+1))==0 ...
           ));
ind1 = [ind1;ind2;ind3];
n4 = length(ind1);
if (n4~=0)
	w(ind1) = 1;
    [a, b, c] = ind2sub(wd,ind1);
	fixset(end+1:end+n4,:) = [[a, b, c]-1, ind1*0+1, ind1*0+5];
end

% right up forward, right up backward, right down forward, right down backward
ruf = find(w(sub2ind(wd,xs-1,ys+1,zs+1)) == 0 & ...
           sum([w(sub2ind(wd,xs-1,ys,zs)), ...
                w(sub2ind(wd,xs,ys+1,zs)), ...
                w(sub2ind(wd,xs-1,ys+1,zs)), ...
                w(sub2ind(wd,xs,ys,zs+1)), ...
                w(sub2ind(wd,xs-1,ys,zs+1)), ...
                w(sub2ind(wd,xs,ys+1,zs+1))]')' == 6);

rub = find(w(sub2ind(wd,xs-1,ys+1,zs-1)) == 0 & ...
           sum([w(sub2ind(wd,xs-1,ys,zs)), ...
                w(sub2ind(wd,xs,ys+1,zs)), ...
                w(sub2ind(wd,xs-1,ys+1,zs)), ...
                w(sub2ind(wd,xs,ys,zs-1)), ...
                w(sub2ind(wd,xs-1,ys,zs-1)), ...
                w(sub2ind(wd,xs,ys+1,zs-1))]')' == 6);

rdf = find(w(sub2ind(wd,xs+1,ys+1,zs+1)) == 0 & ...
           sum([w(sub2ind(wd,xs+1,ys,zs)), ...
                w(sub2ind(wd,xs,ys+1,zs)), ...
                w(sub2ind(wd,xs+1,ys+1,zs)), ...
                w(sub2ind(wd,xs,ys,zs+1)), ...
                w(sub2ind(wd,xs+1,ys,zs+1)), ...
                w(sub2ind(wd,xs,ys+1,zs+1))]')' == 6);

rdb = find(w(sub2ind(wd,xs+1,ys+1,zs-1)) == 0 & ...
           sum([w(sub2ind(wd,xs+1,ys,zs)), ...
                w(sub2ind(wd,xs,ys+1,zs)), ...
                w(sub2ind(wd,xs+1,ys+1,zs)), ...
                w(sub2ind(wd,xs,ys,zs-1)), ...
                w(sub2ind(wd,xs+1,ys,zs-1)), ...
                w(sub2ind(wd,xs,ys+1,zs-1))]')' == 6);

cube = [];

if (~isempty(ruf))
    cube(end+1:end+length(ruf),:) = ...
        [xs(ruf),ys(ruf),zs(ruf), ...
         xs(ruf)-1,ys(ruf)+1,zs(ruf)+1];
end

if (~isempty(rub))
    cube(end+1:end+length(rub),:) = ...
        [xs(rub),ys(rub),zs(rub), ...
         xs(rub)-1,ys(rub)+1,zs(rub)-1];
end

if (~isempty(rdf))
    cube(end+1:end+length(rdf),:) = ...
        [xs(rdf),ys(rdf),zs(rdf), ...
         xs(rdf)+1,ys(rdf)+1,zs(rdf)+1];
end

if (~isempty(rdb))
    cube(end+1:end+length(rdb),:) = ...
        [xs(rdb),ys(rdb),zs(rdb), ...
         xs(rdb)+1,ys(rdb)+1,zs(rdb)-1];
end

% adjust according to cube (3: fix bad 0 vertex connectivities)
if (~isempty(cube))
    len = size(cube,1);
    for i = 1:len
        k = cube(i,:);
        if (w(k(1),k(2),k(3))==0 & w(k(4),k(5),k(6))==0)
            if (nb_sum(w,k(1),k(2),k(3)) >= nb_sum(w,k(4),k(5),k(6)))
                w(k(1),k(2),k(3)) = 1;
                fixset(end+1,:) = [[k(1), k(2), k(3)]-1, 1, infoid];
            else
                w(k(4),k(5),k(6)) = 1;
                fixset(end+1,:) = [[k(4), k(5), k(6)]-1, 1, infoid];
            end
        end
    end
end

cnts = [length(ruf), length(rub), length(rdf), length(rdb)];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% work on 1 vertex connectivies
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ind = find(w);
[xs,ys,zs] = ind2sub(wd,ind);

% right up forward, right up backward, right down forward, right down backward
ruf = find(w(sub2ind(wd,xs-1,ys+1,zs+1)) == 1 & ...
           sum([w(sub2ind(wd,xs-1,ys,zs)), ...
                w(sub2ind(wd,xs,ys+1,zs)), ...
                w(sub2ind(wd,xs-1,ys+1,zs)), ...
                w(sub2ind(wd,xs,ys,zs+1)), ...
                w(sub2ind(wd,xs-1,ys,zs+1)), ...
                w(sub2ind(wd,xs,ys+1,zs+1))]')' == 0);

rub = find(w(sub2ind(wd,xs-1,ys+1,zs-1)) == 1 & ...
           sum([w(sub2ind(wd,xs-1,ys,zs)), ...
                w(sub2ind(wd,xs,ys+1,zs)), ...
                w(sub2ind(wd,xs-1,ys+1,zs)), ...
                w(sub2ind(wd,xs,ys,zs-1)), ...
                w(sub2ind(wd,xs-1,ys,zs-1)), ...
                w(sub2ind(wd,xs,ys+1,zs-1))]')' == 0);

rdf = find(w(sub2ind(wd,xs+1,ys+1,zs+1)) == 1 & ...
           sum([w(sub2ind(wd,xs+1,ys,zs)), ...
                w(sub2ind(wd,xs,ys+1,zs)), ...
                w(sub2ind(wd,xs+1,ys+1,zs)), ...
                w(sub2ind(wd,xs,ys,zs+1)), ...
                w(sub2ind(wd,xs+1,ys,zs+1)), ...
                w(sub2ind(wd,xs,ys+1,zs+1))]')' == 0);

rdb = find(w(sub2ind(wd,xs+1,ys+1,zs-1)) == 1 & ...
           sum([w(sub2ind(wd,xs+1,ys,zs)), ...
                w(sub2ind(wd,xs,ys+1,zs)), ...
                w(sub2ind(wd,xs+1,ys+1,zs)), ...
                w(sub2ind(wd,xs,ys,zs-1)), ...
                w(sub2ind(wd,xs+1,ys,zs-1)), ...
                w(sub2ind(wd,xs,ys+1,zs-1))]')' == 0);

cube = [];

if (~isempty(ruf))
    cube(end+1:end+length(ruf),:) = ...
        [xs(ruf),ys(ruf),zs(ruf), ...
         xs(ruf)-1,ys(ruf)+1,zs(ruf)+1];
end

if (~isempty(rub))
    cube(end+1:end+length(rub),:) = ...
        [xs(rub),ys(rub),zs(rub), ...
         xs(rub)-1,ys(rub)+1,zs(rub)-1];
end

if (~isempty(rdf))
    cube(end+1:end+length(rdf),:) = ...
        [xs(rdf),ys(rdf),zs(rdf), ...
         xs(rdf)+1,ys(rdf)+1,zs(rdf)+1];
end

if (~isempty(rdb))
    cube(end+1:end+length(rdb),:) = ...
        [xs(rdb),ys(rdb),zs(rdb), ...
         xs(rdb)+1,ys(rdb)+1,zs(rdb)-1];
end

% adjust according to cube (4: remove bad 1 voxel connectivities)
if (~isempty(cube))
    len = size(cube,1);
    for i = 1:len
        k = cube(i,:);
        if (w(k(1),k(2),k(3))==1 & w(k(4),k(5),k(6))==1)
            if (nb_sum(w,k(1),k(2),k(3)) <= nb_sum(w,k(4),k(5),k(6)))
                w(k(1),k(2),k(3)) = 0;
                fixset(end+1,:) = [[k(1), k(2), k(3)]-1, 0, infoid];
            else
                w(k(4),k(5),k(6)) = 0;
                fixset(end+1,:) = [[k(4), k(5), k(6)]-1, 0, infoid];
            end
        end
    end
end

cnts = [length(ruf), length(rub), length(rdf), length(rdb)];

% make roi consistent with w
roi = w(2:d(1)+1,2:d(2)+1,2:d(3)+1);

return;

%
% fix bad edge connectivities
%

function [roi, fixset] = edge_conn(roi, d, infoid)

roi = reshape(roi,d);

% make a work area so that all border voxels belong to the background
w = zeros(d+2);
w(2:d(1)+1,2:d(2)+1,2:d(3)+1) = roi;
wd = d+2;

ind = find(w);
[xs,ys,zs] = ind2sub(wd,ind);

squa = [];

% right up and right down
ru = find(w(sub2ind(wd,xs-1,ys,zs))   == 0 & ...
          w(sub2ind(wd,xs,ys+1,zs))   == 0 & ...
          w(sub2ind(wd,xs-1,ys+1,zs)) == 1);

if (~isempty(ru))
    squa(end+1:end+length(ru),:) = ...
                [xs(ru),ys(ru),zs(ru),...
                 xs(ru)-1,ys(ru)+1,zs(ru),...
                 xs(ru)-1,ys(ru),zs(ru),...
                 xs(ru),ys(ru)+1,zs(ru)];
end

rd = find(w(sub2ind(wd,xs+1,ys,zs))   == 0 & ...
          w(sub2ind(wd,xs,ys+1,zs))   == 0 & ...
          w(sub2ind(wd,xs+1,ys+1,zs)) == 1);

if (~isempty(rd))
    squa(end+1:end+length(rd),:) = ...
                [xs(rd),ys(rd),zs(rd),...
                 xs(rd)+1,ys(rd)+1,zs(rd),...
                 xs(rd)+1,ys(rd),zs(rd),...
                 xs(rd),ys(rd)+1,zs(rd)];
end

% forward up and forward down
fu = find(w(sub2ind(wd,xs-1,ys,zs))   == 0 & ...
          w(sub2ind(wd,xs,ys,zs+1))   == 0 & ...
          w(sub2ind(wd,xs-1,ys,zs+1)) == 1);

if (~isempty(fu))
    squa(end+1:end+length(fu),:) = ...
                [xs(fu),ys(fu),zs(fu),...
                 xs(fu)-1,ys(fu),zs(fu)+1,...
                 xs(fu)-1,ys(fu),zs(fu),...
                 xs(fu),ys(fu),zs(fu)+1];
end

fd = find(w(sub2ind(wd,xs+1,ys,zs))   == 0 & ...
          w(sub2ind(wd,xs,ys,zs+1))   == 0 & ...
          w(sub2ind(wd,xs+1,ys,zs+1)) == 1);

if (~isempty(fd))
    squa(end+1:end+length(fd),:) = ...
                [xs(fd),ys(fd),zs(fd),...
                 xs(fd)+1,ys(fd),zs(fd)+1,...
                 xs(fd)+1,ys(fd),zs(fd),...
                 xs(fd),ys(fd),zs(fd)+1];
end

% left forward and right forward
lf = find(w(sub2ind(wd,xs,ys-1,zs))   == 0 & ...
          w(sub2ind(wd,xs,ys,zs+1))   == 0 & ...
          w(sub2ind(wd,xs,ys-1,zs+1)) == 1);

if (~isempty(lf))
    squa(end+1:end+length(lf),:) = ...
                [xs(lf),ys(lf),zs(lf),...
                 xs(lf),ys(lf)-1,zs(lf)+1,...
                 xs(lf),ys(lf)-1,zs(lf),...
                 xs(lf),ys(lf),zs(lf)+1];
end

rf = find(w(sub2ind(wd,xs,ys+1,zs))   == 0 & ...
          w(sub2ind(wd,xs,ys,zs+1))   == 0 & ...
          w(sub2ind(wd,xs,ys+1,zs+1)) == 1);

if (~isempty(rf))
    squa(end+1:end+length(rf),:) = ...
                [xs(rf),ys(rf),zs(rf),...
                 xs(rf),ys(rf)+1,zs(rf)+1,...
                 xs(rf),ys(rf)+1,zs(rf),...
                 xs(rf),ys(rf),zs(rf)+1];
end

% adjust according to squa (5: remove bad edge connectivities)
fixset = [];
if (~isempty(squa))
    len = size(squa,1);
    for i = 1:len
        k = squa(i,:);
        if (sum([w(k(1),k(2),k(3)) ...
                 w(k(4),k(5),k(6)) ...
                 w(k(7),k(8),k(9)) ...
                 w(k(10),k(11),k(12)) ...
                 ]==[1 1 0 0])==4)
            [start, val] = decide_squa(w,k);
            w(k(start),k(start+1),k(start+2)) = val;
            fixset(end+1,:) = [[k(start), k(start+1), k(start+2)]-1, val, infoid];
        end
    end
end

cnts = [length(ru),length(rd),length(fu),length(fd),length(lf),length(rf)];

% make roi consistent with w
roi = w(2:d(1)+1,2:d(2)+1,2:d(3)+1);

return;

%
% check ring on one slice, and hole between two slices
%

function [roi, fixset] = ring_hole(roi, d, infoid)

roi = reshape(roi,d);

% make a work area so that all border voxels belong to the background
w = zeros(d+2);
w(2:d(1)+1,2:d(2)+1,2:d(3)+1) = roi;
wd = d+2;

% exchange background and object
w = 1-w;

fixset = [];

for k = 1:3
    % label each slice
	for i = 1:wd(k)
        switch k
        case 1
            im = reshape(w(i,:,:),wd(2),wd(3));
        case 2
            im = reshape(w(:,i,:),wd(1),wd(3));
        case 3
            im = reshape(w(:,:,i),wd(1),wd(2));
        end
        [lab, num(i)] = bwlabel(im,4);
        L{i} = lab;
	end
    % original roi background should be labeled as '1'
    ind = find(num>1);
    for i = 1:length(ind);
        lab = L{ind(i)};
        for j = 1:num(ind(i))
            cnt(j) = length(find(lab == j));
        end
        [mval, mind] = max(cnt);
        if (mind > 1)
            disp('Make background labeled as 1');
            ind1 = find(lab == 1);
            ind2 = find(lab == mind);
            lab(ind2) = 1; % background
            lab(ind1) = mind;
            L{ind(i)} = lab;
        end
    end
    % check multiple component slices
    for i = 1:length(ind);
        lab = L{ind(i)};
        for j = 2:num(ind(i))
            % connect to background in the previous slice
            con_prev = find(lab == j & L{ind(i)-1} == 1);
            % connect to background in the next slice
            con_next = find(lab == j & L{ind(i)+1} == 1);
            if (~isempty(con_prev) & ~isempty(con_next))
                [xs, ys] = find(lab == j);
                switch k
                case 1
                    im = reshape(w(ind(i),:,:),wd(2),wd(3));
                    sigind = sub2ind(wd,xs*0+ind(i),xs,ys);
                case 2
                    im = reshape(w(:,ind(i),:),wd(1),wd(3));
                    sigind = sub2ind(wd,xs,xs*0+ind(i),ys);
                case 3
                    im = reshape(w(:,:,ind(i)),wd(1),wd(2));
                    sigind = sub2ind(wd,xs,ys,xs*0+ind(i));
                end
                w(sigind) = 0; % note that really it is assigned 1 to roi
                [xs,ys,zs] = ind2sub(wd,sigind);
                fixset(end+1:end+length(xs),:) = [[xs,ys,zs]-1, xs*0+1, xs*0+infoid];
            end
        end
    end
    % check hole between slices
    for i = 2:(wd(k)-2)
        overlap = L{i}*0;
        overlap_bkgd = find(L{i} == 1 & L{i+1} == 1);
        overlap(overlap_bkgd) = 1;
        [lab, m] = bwlabel(overlap,4);
        if (m>1)
            % deal with only the minimum one;
            for j = 1:m
                cnt(j) = length(find(lab == j));
            end
            [mval, mind] = min(cnt);
            % connect to background in the previous slice
            con_prev = find(lab == mind & L{i-1} == 1);
            % connect to background in the current slice
            con_curr = find(lab == mind & L{i} == 1);
            % connect to background in the next slice
            con_next = find(lab == mind & L{i+1} == 1);
            % connect to background in the next next slice
            con_next_next = find(lab == mind & L{i+2} == 1);
            if ((~isempty(con_curr) | ~isempty(con_prev)) & ...
                (~isempty(con_next) | ~isempty(con_next_next)))
                [xs, ys] = find(lab == mind);
                switch k
                case 1
                    sigind = [sub2ind(wd,xs*0+i,xs,ys);sub2ind(wd,xs*0+i+1,xs,ys)];
                case 2
                    sigind = [sub2ind(wd,xs,xs*0+i,ys);sub2ind(wd,xs,xs*0+i+1,ys)];
                case 3
                    sigind = [sub2ind(wd,xs,ys,xs*0+i);sub2ind(wd,xs,ys,xs*0+i+1)];
                end
                w(sigind) = 0; % note that really it is assigned 1 to roi
                [xs,ys,zs] = ind2sub(wd,sigind);
                fixset(end+1:end+length(xs),:) = [[xs,ys,zs]-1, xs*0+1, xs*0+infoid];
            end
        end
    end
    L = [];
    num = [];
end

% make roi consistent with w
roi = 1 - w(2:d(1)+1,2:d(2)+1,2:d(3)+1);

return;

%
% select a point to change its value
% according to maximum number of different neighbours
%

function [start, val] = decide_squa(w,k)

for i = 1:3:10
    cnt((i-1)/3+1) = nb_sum(w, k(i), k(i+1), k(i+2));
end

cnt(1:2) = 6 - cnt(1:2);

[v, in] = max(cnt);

start = (in-1)*3+1;
if (in < 3)
    val = 0;
else
    val = 1;
end

return;

%
% calculate the sum of the direct neighbour
%
function b = nb_sum(w, x, y, z)

b = sum([w(x-1,y,z), ...
         w(x+1,y,z), ...
         w(x,y-1,z), ...
         w(x,y+1,z), ...
         w(x,y,z-1), ...
         w(x,y,z+1)]);

return;


function [net, info] = cnn_mnist(varargin)
% CNN_MNIST  Demonstrated MatConNet on MNIST

run(fullfile(fileparts(mfilename('fullpath')),...
  '..', 'matlab', 'vl_setupnn.m')) ;

opts.expDir = fullfile('data','mnist-baseline') ;
opts.gpus = [];
opts.pushbullet = []; % usage : pbNotify('accessToken'); from https://www.pushbullet.com/account
[opts, varargin] = vl_argparse(opts, varargin) ;

opts.dataDir = fullfile('data','mnist') ;
opts.imdbPath = fullfile(opts.expDir, 'imdb.mat');
opts.useBnorm = false ;
opts.train.batchSize = 100 ;
opts.train.numEpochs = 20 ;
opts.train.continue = true ;
opts.train.gpus = opts.gpus;
opts.train.learningRate = 0.001 ;
opts.train.expDir = opts.expDir ;
opts.train.pushbullet = opts.pushbullet ;
opts = vl_argparse(opts, varargin) ;

% --------------------------------------------------------------------
%                                                         Prepare data
% --------------------------------------------------------------------

if exist(opts.imdbPath, 'file')
  imdb = load(opts.imdbPath) ;
else
  imdb = getMnistImdb(opts) ;
  mkdir(opts.expDir) ;
  save(opts.imdbPath, '-struct', 'imdb') ;
end

net = cnn_mnist_init('useBnorm', opts.useBnorm) ;

% --------------------------------------------------------------------
%                                                                Train
% --------------------------------------------------------------------
% b = [10 10] + [10 10 10] ; error test
[net, info] = cnn_train(net, imdb, @getBatch, ...
    opts.train, ...
    'val', find(imdb.images.set == 3)) ;

if ~isempty(opts.pushbullet)
    opts.pushbullet.notify('training complete') ;
end
% --------------------------------------------------------------------
function [im, labels] = getBatch(imdb, batch)
% --------------------------------------------------------------------
im = imdb.images.data(:,:,:,batch) ;
labels = imdb.images.labels(1,batch) ;

% --------------------------------------------------------------------
function imdb = getMnistImdb(opts)
% --------------------------------------------------------------------
% Preapre the imdb structure, returns image data with mean image subtracted
files = {'train-images-idx3-ubyte', ...
         'train-labels-idx1-ubyte', ...
         't10k-images-idx3-ubyte', ...
         't10k-labels-idx1-ubyte'} ;

if ~exist(opts.dataDir, 'dir')
  mkdir(opts.dataDir) ;
end

for i=1:4
  if ~exist(fullfile(opts.dataDir, files{i}), 'file')
    url = sprintf('http://yann.lecun.com/exdb/mnist/%s.gz',files{i}) ;
    fprintf('downloading %s\n', url) ;
    gunzip(url, opts.dataDir) ;
  end
end

f=fopen(fullfile(opts.dataDir, 'train-images-idx3-ubyte'),'r') ;
x1=fread(f,inf,'uint8');
fclose(f) ;
x1=permute(reshape(x1(17:end),28,28,60e3),[2 1 3]) ;

f=fopen(fullfile(opts.dataDir, 't10k-images-idx3-ubyte'),'r') ;
x2=fread(f,inf,'uint8');
fclose(f) ;
x2=permute(reshape(x2(17:end),28,28,10e3),[2 1 3]) ;

f=fopen(fullfile(opts.dataDir, 'train-labels-idx1-ubyte'),'r') ;
y1=fread(f,inf,'uint8');
fclose(f) ;
y1=double(y1(9:end)')+1 ;

f=fopen(fullfile(opts.dataDir, 't10k-labels-idx1-ubyte'),'r') ;
y2=fread(f,inf,'uint8');
fclose(f) ;
y2=double(y2(9:end)')+1 ;

set = [ones(1,numel(y1)) 3*ones(1,numel(y2))];
data = single(reshape(cat(3, x1, x2),28,28,1,[]));
dataMean = mean(data(:,:,:,set == 1), 4);
data = bsxfun(@minus, data, dataMean) ;

imdb.images.data = data ;
imdb.images.data_mean = dataMean;
imdb.images.labels = cat(2, y1, y2) ;
imdb.images.set = set ;
imdb.meta.sets = {'train', 'val', 'test'} ;
imdb.meta.classes = arrayfun(@(x)sprintf('%d',x),0:9,'uniformoutput',false) ;


validInputSize = [3,3,18,1];
layer = yolov3Layer('yolov3', rand(3,2),1,1,[416,416],'default');
checkLayer(layer,validInputSize,'ObservationDimension' ,4)

%%
layer = mishLayer('mishACT');
validInputSize = [24 24 20];
checkLayer(layer,validInputSize,'ObservationDimension',4)


filename='ImprovedCantilever_hexahedra';
 ptype = 'MACRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'full';
cost = {'compliance'};
weights = [1, 0.1];
constraint = {'volumeConstraint'};
optimizer = 'SLERP'; incrementFactor = 1;
filterType = 'P1';

nsteps = 1;
Vfrac_final = 0.1;
Perimeter_target = 1;
optimality_final = 1e-3;
constr_final =1e-3;

Vfrac_initial = 1;
optimality_initial = 1e-2;
constr_initial = 1e-3;
TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;


function varargout = spm_render_vol(varargin)
% surface render a memory mapped 8 bit image - a compiled routine
% FORMAT [REN, ZBUF, X, Y, Z] = spm_render_vol(V, A, [i j], [u n])
% V       -  is the memory mapped volume
% A       -  {4 x 4} affine transformation matrix
% [i j]   -  dimensions of REN
% [u n]   -  u is threhsold at which voxels are 'solid'
%            n is the number of nearest neighbours to use to determine the
%            surface orientation
% REN     -  is the rendered image
% ZBUF    -  distance from the view plane to the object's surface
% X, Y, Z -  are images containing the coordinates of the voxels on the
%            surface of the volume.
%_______________________________________________________________________
%
% [i j] defines the two dimensions of the output image. The coordinates
% in 3-D space of the voxels in this image are assumed to range from
% 1,1,0 to i,j,0.
%
% For each pixel in the volume, the coordinates (x,y,z & 1) are
% multiplied by the matrix A, to give the image coordinates that these
% voxels map to.
%
% The threshold at which voxels are assumed to be solid pertains to the
% 8-bit data i.e. {0 - 255}
%
% Illumination is assumed to be from the viewplane
%
%_______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_render_vol.m 1143 2008-02-07 19:33:33Z spm $

%-This is merely the help file for the compiled routine
error('spm_render_vol.c not compiled - see Makefile')


function  res = SPIRiT(kernel,method, imSize)
%res = SPIRiT(kernel [,method, imSize])
%	Implementation of the SPIRiT kernel operator
%
%
%   Constructor inputs:
%       kernel: [kx,ky,nCoils, nCoils] the spirit 2D convolution kernel.
%               See corrMatrix.m, calibrate.m and the demos on how to
%               generate a kernel.
%       method: implementation type of the operator. There are three
%               'conv'  is a k-space convolution implementation (slowest)
%                       that operates on k-space data and produces k-space data.
%               'fft'   is an fft based implementation of the k-space
%                       convolution through image domain multiplication.
%                       It operates on k-sapce data and produces k-space data.
%               'image' The SPIRiT operator is applied to image space data.
%                       This is useful when using image-based non-cartesian
%                       reconstruction. In this case the SPIRiT operator
%                       operates on image data and produces image data.
%
%       imSize:  Size of the resulting image (only needed for 'fft' and
%                'image' modes
%
%
%   Example:
%
%   [x,y] = meshgrid(linspace(0,1,128));
%   % Generate fake Sensitivity maps
%   sMaps = cat(3,x.^2,1-x.^2,y.^2,1-y.^2);
%   % generate 4 coil phantom
%   imgs = repmat(phantom(128),[1,1,4]).*sMaps;
%   DATA = fft2c(imgs);
%   % crop 20x20 window from the center of k-space for calibration
%   kCalib = crop(DATA,[20,20,4]);
%
%   %calibrate a kernel
%   kSize = [5,5];
%   coils = 4;
%   kernel = zeros([kSize,coils,coils]);
%   [AtA,] = corrMatrix(kCalib,kSize);
%   for n=1:coils
%       kernel(:,:,:,n) = calibrate(AtA,kSize,coils,n,0.01);
%   end
%   GOP = SPIRiT(kernel, 'fft',[128,128]);
%
%   % undersample by a factor of 2
%   DATA(1:2:end,2:2:end,:) = 0;
%   DATA(2:2:end,1:2:end,:) = 0;
%
%   %reconstruct:
%   [res] = cgSPIRiT(DATA,GOP, 20, 1e-5, DATA);
%   figure, imshow(cat(2,sos(imgs), 2*sos(ifft2c(DATA)), sos(ifft2c(res))),[]);
%   title('full,  zero-fill,   result')
%
%   See Also:
%               calibrate.m, corrMatrix.m
%
% (c) Michael Lustig 2007

    if nargin < 2
	    method = 'conv';
	    KERNEL = [];
    end

    if strcmp(method,'conv')==1
	    KERNEL = [];
    end

    if strcmp(method,'fft')==1 & nargin < 3
	    error('must provide image size');
    end

    % for methods 'fft' and 'image' precompute the image domain kernel by
    % zero-padding and inverse fft

    if strcmp(method,'fft')==1 | strcmp(method,'image')==1
	    for n=1:size(kernel,4)
            KERNEL(:,:,:,n) = ifftnshift(zpad(kernel(end:-1:1,end:-1:1,:,n), imSize(1), imSize(2), size(kernel,3)),1:2);
%             KERNEL(:,:,:,n) = (ifft2c(zpad(kernel(end:-1:1,end:-1:1,:,n)*sqrt(imSize(1)*imSize(2)), imSize(1), imSize(2), size(kernel,3))));
        end
    end

    if strcmp(method,'fft')==0 & strcmp(method,'conv')==0 & strcmp(method,'image')==0
	    eror('no such method');
    end

    res.kernel = kernel;
    res.adjoint = 0;
    res.KERNEL = KERNEL;
    res.method = method;
    res.imSize = imSize;
    res = class(res,'SPIRiT');


function [hc] = read_ctf_hc(filename);

% READ_CTF_HC reads the MEG headcoil marker positions from an ascii file
% and computes the coordinate transformation required to get from from
% dewar to head-coordinates
%
% the definition of head coordinates is according to CTF standard:
% - the origin is exactly between LPA and RPA
% - the positive x-axis goes throught NAS
% - the positive y-axis goes (approximately) through LPA
% - the positive z-axis goes up, orthogonal to the x- and y-axes
%
% hc = read_ctf_hc(filename)
%
% returns a structure with the following fields
%   hc.dewar.nas	marker positions relative to dewar
%   hc.dewar.lpa
%   hc.dewar.rpa
%   hc.head.nas		marker positions relative to head (measured)
%   hc.head.lpa
%   hc.head.rpa
%   hc.standard.nas	marker positions relative to head (expected)
%   hc.standard.lpa
%   hc.standard.rpa
% and
%   hc.affine		parameter for affine transformation (1x12)
%   hc.homogenous	homogenous transformation matrix (4x4, see warp3d)
%   hc.translation	translation vector (1x3)
%   hc.rotation		rotation matrix (3x3)
%
% Gradiometer positions can be transformed into head coordinates using the
% homogeneous transformation matrix, or using the affine parameters and
% the warp3d function from the WARPING toolbox
%
% WARNING: all returned positions are in mm, and the transformation matrices
% also should be applied on channel positions that are in mm.

% Copyright (C) 2002, Robert Oostenveld
%
global fb

hc.standard.nas = [0 0 0];
hc.standard.lpa = [0 0 0];
hc.standard.rpa = [0 0 0];
hc.dewar.nas    = [0 0 0];
hc.dewar.lpa    = [0 0 0];
hc.dewar.rpa    = [0 0 0];
hc.head.nas     = [0 0 0];
hc.head.lpa     = [0 0 0];
hc.head.rpa     = [0 0 0];

fid = fopen(filename, 'r');
if fid==-1
  error(sprintf('could not open file %s', filename));
end

fseek(fid, 0, 'bof');
line = [];

if fb
  fprintf('reading standard coil positions with respect to the dewar\n');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% standard coil positions with respect to the dewar
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
while ~strcmp(line, 'standard nasion coil position relative to dewar (cm):')
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.nas(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.nas(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.nas(3) = str2num(r(2:end));
% NOTE THAT THERE IS AN TYPING ERROR IN SOME CTF FILES WHICH I HAVE TO REPRODUCE HERE (staNdard)
while ~(strcmp(line, 'stadard left ear coil position relative to dewar (cm):') | ...
        strcmp(line, 'standard left ear coil position relative to dewar (cm):'))
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.lpa(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.lpa(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.lpa(3) = str2num(r(2:end));
while ~strcmp(line, 'standard right ear coil position relative to dewar (cm):')
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.rpa(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.rpa(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.standard.rpa(3) = str2num(r(2:end));

if fb
  fprintf('reading measured coil positions with respect to the dewar\n');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% measured coil positions with respect to the dewar
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
while ~strcmp(line, 'measured nasion coil position relative to dewar (cm):')
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.nas(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.nas(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.nas(3) = str2num(r(2:end));
while ~strcmp(line, 'measured left ear coil position relative to dewar (cm):')
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.lpa(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.lpa(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.lpa(3) = str2num(r(2:end));
while ~strcmp(line, 'measured right ear coil position relative to dewar (cm):')
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.rpa(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.rpa(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.dewar.rpa(3) = str2num(r(2:end));

if fb
  fprintf('reading measured coil positions with respect to the head\n');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% measured coil positions with respect to the head
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
while ~strcmp(line, 'measured nasion coil position relative to head (cm):')
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.nas(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.nas(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.nas(3) = str2num(r(2:end));
while ~strcmp(line, 'measured left ear coil position relative to head (cm):')
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.lpa(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.lpa(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.lpa(3) = str2num(r(2:end));
while ~strcmp(line, 'measured right ear coil position relative to head (cm):')
  line = fgetl(fid);
  if ~ischar(line) & line==-1, error('premature end of file'), end
end
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.rpa(1) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.rpa(2) = str2num(r(2:end));
line = fgetl(fid); [t, r] = strtok(line, '='); hc.head.rpa(3) = str2num(r(2:end));

fclose(fid);

if fb
  fprintf('computing transformation matrix\n');
end

% change the marker positions from cm to mm
hc.standard.nas = 10*hc.standard.nas;
hc.standard.lpa = 10*hc.standard.lpa;
hc.standard.rpa = 10*hc.standard.rpa;
hc.dewar.nas    = 10*hc.dewar.nas;
hc.dewar.lpa    = 10*hc.dewar.lpa;
hc.dewar.rpa    = 10*hc.dewar.rpa;
hc.head.nas     = 10*hc.head.nas;
hc.head.lpa     = 10*hc.head.lpa;
hc.head.rpa     = 10*hc.head.rpa;

% compute the direction of the head coordinate axes in dewar coordinates
d_x = hc.dewar.nas - (hc.dewar.lpa + hc.dewar.rpa)/2;
d_z = cross(d_x, hc.dewar.lpa - hc.dewar.rpa);
d_y = cross(d_z, d_x);
d_x = d_x / norm(d_x);
d_y = d_y / norm(d_y);
d_z = d_z / norm(d_z);

% compute the translation and rotation which are neccessary to transform
% any given location from the dewar to the head coordinate system
hc.translation = -(hc.dewar.lpa + hc.dewar.rpa)/2;
hc.rotation = inv([d_x' d_y' d_z']);

% construct the homogenous coordinate transformation matrix
% from the subsequent translation and rotation
hc.homogenous = eye(4,4);
hc.homogenous(1:3,4)   = hc.rotation * hc.translation';
hc.homogenous(1:3,1:3) = hc.rotation;

% construct a vector with the 12 parameters for an affine warp
hc.affine = hc.homogenous';
hc.affine = hc.affine(1:12);