function net=train_denoising_mini(source_1, source_2, context_win, hidden_units, num_layers, isdropout, ...
    isRNN, iscleanonly, circular_step , isinputL1, MFCCorlogMelorSpectrum, ...
    framerate, pos_neg_r, outputnonlinear, opt, act, train_mode, const,  ...
    const2, isGPU, max_iter, batchsize, lbfgs_iter, grad_clip, wdecay)
% Copyright (c) 2014-present University of Illinois at Urbana-Champaign
% All rights reserved.
%
% Developed by:     Po-Sen Huang, Paris Smaragdis
%                   Department of Electrical and Computer Engineering
%                   Department of Computer Science
%
% Demo Denoising training ---------------------------------------------
% context_win - context window size
% hidden_units - hidden units
% num_layers - layer number
% isdropout - 1: use dropout, 0: no dropout
% isRNN - RNN temporal connection
% iscleanonly - One output source or two
% circular_step - Circular shift step
% isinputL1 - normalize input as L1 norm = 1
% MFCCorlogMelorSpectrum - 0: MFCC, 1: logmel, 2: spectra
% framerate - feature frame rate
% pos_neg_r - discriminative training gamma parameter
% outputnonlinear - Last layer - linear or nonlinear
% softabs - soft mask obj
% act - 0: logistic, 1: tanh, 2: RELU
% const - constant for avoiding numerical problems
% const2- constant for avoiding numerical problems
% isGPU - 0: not using GPU, 1: using GPU
% train_mode - 0
% max_iter - max LBFGS iterations

rand('state',0)
randn('state',0)

%% setup paths for code. assumed this script runs in its own directory
% CHANGE baseDir to the top of code directory
baseDir= ['..',filesep, '..',  filesep];
codeDir = [baseDir,'codes', filesep];
minFuncDir = [baseDir, 'tools', filesep, 'minFunc_2012', filesep];

saveDir = [codeDir,filesep,'denoising',filesep,'discrim_joint_offset_results'];

%% add paths
addpath([baseDir, filesep,'tools', filesep,'labrosa']);
% addpath([baseDir, filesep,'tools', filesep,'bss_eval']);
addpath([baseDir, filesep,'tools', filesep,'bss_eval_2.1']);
% addpath([baseDir, filesep,'tools', filesep,'bss_eval_3']);
addpath(baseDir);
addpath(genpath(minFuncDir));
addpath(codeDir);
addpath([codeDir,'denoising']);

CFGPath=[baseDir,'tools',filesep,'htk_features', filesep];
addpath(CFGPath);

%% setup network architecture
setup_architecture;

%% initialize weights
[stack_i, W_t_i] = initialize_weights(eI);
[theta] = rnn_stack2params(stack_i, eI, W_t_i);

%% Directory of features
eI.featInBase =baseDir;

%% load data
eI.useCache = 0;

%% setup minFunc
options.Diagnostics = 'on';
options.Display = 'iter';
% options.MaxIter = 400;

options.MaxIter = lbfgs_iter;
options.MaxFunEvals = 2500;
options.Corr = 50;
options.DerivativeCheck = 'off';
% options.DerivativeCheck = 'on';
options.outputFcn = @save_callback_denoising_general;

% eI.DataPath=[codeDir,'mir1k', filesep, 'Wavfile',filesep];
eI.iterStart=-batchsize;

%% feed data
for ii= 1: max_iter
    fprintf('Global iterations: %d\n', ii);
    eI.iterStart=eI.iterStart+batchsize;

    batch_cell_idx = randperm(numel(source_1), min(batchsize, numel(source_1)));
    source_1_mini = cell(1, numel(batch_cell_idx)); source_2_mini = cell(1, numel(batch_cell_idx));
    for jj=1:numel(batch_cell_idx)
        source_1_mini{jj} = source_1{batch_cell_idx(jj)};
        source_2_mini{jj} = source_2{batch_cell_idx(jj)};
    end
    % train_files= dir( [eI.DataPath, 'train',filesep,'*wav']);
    % 0 -- chunk, 2--no chunk
    [data_cell, targets_cell, mixture_spectrum] = ...
                formulate_data(source_1_mini, source_2_mini, eI, eI.train_mode);

    %% BSS EVAL setting
    eI.writewav=0;

    %% run optimizer
    if isfield(eI,'cleanonly') && eI.cleanonly==1,
        % % for non joint training
        eI.isdiscrim=1;
        [theta,val]=minFunc(@drdae_discrim_obj, theta, options, eI, data_cell, ...
                            targets_cell, false, false);
    else
       if isGPU==1 && strcmpi(eI.activationFn,'RELU') && opt==1
          [theta,val]=minFunc(@drdae_discrim_joint_kl_obj_gpu_relu, theta, options, eI, ...
           data_cell, targets_cell, mixture_spectrum, false, false);
       elseif isGPU==1
          [theta,val]=minFunc(@drdae_discrim_joint_kl_obj_gpu, theta, options, eI, ...
            data_cell, targets_cell, mixture_spectrum, false, false);
       else
          [theta,val]=minFunc(@drdae_discrim_joint_kl_obj, theta, options, eI, ...
            data_cell, targets_cell, mixture_spectrum, false, false);
       end
    end

end

net.theta = theta;
net.eI = eI;

return;

%% unit test - small example
% context window size
context_win = 1;
% hidden units
hidden_units = 16;
num_layers = 1;
isdropout = 0;
% RNN temporal connection
isRNN = 2;
% One output source or two
iscleanonly = 0;
% Circular shift step
circular_step = 1000000;
% normalize input as L1 norm = 1
isinputL1 = 0;
% 0: MFCC, 1: logmel, 2: spectra
MFCCorlogMelorSpectrum = 2;
% feature frame rate
framerate = 64;

% discriminative training gamma parameter
pos_neg_r = 0.05;
% Last layer - linear or nonlinear
outputnonlinear = 0;
% soft mask obj
softabs = 1;
% 0: logistic, 1: tanh, 2: RELU
act = 2;
% constant for avoiding numerical problems
const = 1e-10;
% constant for avoiding numerical problems
const2 = 0.001;
% 0: not using GPU, 1: using GPU
isGPU = 0;

train_mode = 0;
% 0:'softlinear',1:'softabs', 2:'softquad', 3:'softabs_const',
% 4:'softabs_kl_const'
opt = 1;

[train1, fs, nbits]=wavread('female_train.wav');
[train2, fs, nbits]=wavread('male_train.wav');
maxLength=max([length(train1), length(train2)]);
train1(end+1:maxLength)=eps;
train2(end+1:maxLength)=eps;

max_iter = 30;

train_denoising({train1'}, {train2'}, context_win, hidden_units, num_layers, isdropout, ...
    isRNN, iscleanonly, circular_step , isinputL1, MFCCorlogMelorSpectrum, ...
    framerate, pos_neg_r, outputnonlinear, opt, act, train_mode, const,  ...
    const2, isGPU, max_iter)

%% unit test 2 - best setting:
% context window size
context_win = 3;
% hidden units
hidden_units = 1000;
num_layers = 3;
isdropout = 0;
% RNN temporal connection
isRNN = 2;
% One output source or two
iscleanonly = 0;
% Circular shift step
circular_step = 10000;
% normalize input as L1 norm = 1
isinputL1 = 0;
% 0: MFCC, 1: logmel, 2: spectra
MFCCorlogMelorSpectrum = 2;
% feature frame rate
framerate = 64;
% discriminative training gamma parameter
pos_neg_r = 0.05;
% Last layer - linear or nonlinear
outputnonlinear = 0;
% soft mask obj
softabs = 1;
% 0: logistic, 1: tanh, 2: RELU
act = 2;
% constant for avoiding numerical problems
const = 1e-10;
% constant for avoiding numerical problems
const2 = 0.001;
% 0: not using GPU, 1: using GPU
isGPU = 0;

train_mode = 0;
% 0:'softlinear',1:'softabs', 2:'softquad', 3:'softabs_const',
% 4:'softabs_kl_const'
opt = 1;

[train1, fs, nbits]=wavread('female_train.wav');
[train2, fs, nbits]=wavread('male_train.wav');
maxLength=max([length(train1), length(train2)]);
train1(end+1:maxLength)=eps;
train2(end+1:maxLength)=eps;

max_iter = 30;

train_denoising({train1'}, {train2'}, context_win, hidden_units, num_layers, isdropout, ...
    isRNN, iscleanonly, circular_step , isinputL1, MFCCorlogMelorSpectrum, ...
    framerate, pos_neg_r, outputnonlinear, opt, act, train_mode, const,  ...
    const2, isGPU, max_iter)


function obj = updateBar3h(obj, surfaceIndex)

%-AXIS INDEX-%
axIndex = obj.getAxisIndex(obj.State.Plot(surfaceIndex).AssociatedAxis);

%-CHECK FOR MULTIPLE AXES-%
[xsource, ysource] = findSourceAxis(obj,axIndex);

%-SURFACE DATA STRUCTURE- %
bar_data = get(obj.State.Plot(surfaceIndex).Handle);
figure_data = get(obj.State.Figure.Handle);

%-AXIS STRUCTURE-%
axis_data = get(ancestor(bar_data.Parent,'axes'));

%-GET SCENE-%
eval(['scene = obj.layout.scene' num2str(xsource) ';']);

%-------------------------------------------------------------------------%

%-associate scene-%
obj.data{surfaceIndex}.scene = sprintf('scene%d', xsource);

%-------------------------------------------------------------------------%

%-surface type-%
obj.data{surfaceIndex}.type = 'mesh3d';

%-------------------------------------------------------------------------%

%-FORMAT DATA-%
xdata = bar_data.XData;
ydata = bar_data.ZData;
zdata = bar_data.YData;
cdata = bar_data.CData;

%-parse xedges-%
xedges = xdata(2, 1:2:end);

%-parse yedges-%
yedges = ydata(2:6:end, 2);
yedges = [yedges', mean(diff(yedges(1:2)))];

%-parse values-%
values = [];
for n = 1:6:size(zdata, 1)
    values = [values, diff(zdata(n:n+1, 2))];
end

%-parse offsets-%
offsets = zdata(1:6:end, 2)';

%-------------------------------------------------------------------------%

%-get the values to use plotly's mesh3D-%
bargap = diff(yedges(1:2)) - diff(ydata(2:3));
[X, Y, Z, I, J, K] = get_plotly_mesh3d(xedges, yedges, values, bargap);

%---------------------------------------------------------------------%

%-reformat Z according to offsets-%
m = 1;
lz2 = 0.5*length(Z);

for n = 1:4:lz2
    Z(n:n+3) = Z(n:n+3)+offsets(m);
    Z(n+lz2:n+lz2+3) = Z(n+lz2:n+lz2+3)+offsets(m);
    m = m + 1;
end

%-------------------------------------------------------------------------%

%-set mesh3d data-%
obj.data{surfaceIndex}.x = X;
obj.data{surfaceIndex}.y = Z;
obj.data{surfaceIndex}.z = Y;
obj.data{surfaceIndex}.i = int16(I-1);
obj.data{surfaceIndex}.j = int16(J-1);
obj.data{surfaceIndex}.k = int16(K-1);

%-------------------------------------------------------------------------%

%-coloring-%
cmap = figure_data.Colormap;

if isnumeric(bar_data.FaceColor)

    %-paper_bgcolor-%
    col = 255*bar_data.FaceColor;
    col = sprintf('rgb(%f,%f,%f)', col);

else
    switch bar_data.FaceColor

        case 'none'
            col = 'rgba(0,0,0,0)';

        case {'flat','interp'}

            switch bar_data.CDataMapping

                case 'scaled'
                    capCD = max(min(cdata(1,1),axis_data.CLim(2)),axis_data.CLim(1));
                    scalefactor = (capCD - axis_data.CLim(1))/diff(axis_data.CLim);
                    col =  255*(cmap(1+ floor(scalefactor*(length(cmap)-1)),:));
                case 'direct'
                    col =  255*(cmap(cdata(1,1),:));

            end

            col = sprintf('rgb(%f,%f,%f)', col);

        case 'auto'
            col = 'rgb(0,113.985,188.955)';
    end
end

obj.data{surfaceIndex}.color = col;

%-------------------------------------------------------------------------%

%-some settings-%
obj.data{surfaceIndex}.contour.show = true;
obj.data{surfaceIndex}.contour.width = 6;
obj.data{surfaceIndex}.contour.color='rgb(0,0,0)';
obj.data{surfaceIndex}.flatshading = false;

%-------------------------------------------------------------------------%

%-lighting settings-%
obj.data{surfaceIndex}.lighting.diffuse = 0.8;
obj.data{surfaceIndex}.lighting.ambient = 0.65;
obj.data{surfaceIndex}.lighting.specular = 1.42;
obj.data{surfaceIndex}.lighting.roughness = 0.52;
obj.data{surfaceIndex}.lighting.fresnel = 0.2;
obj.data{surfaceIndex}.lighting.vertexnormalsepsilon = 1e-12;
obj.data{surfaceIndex}.lighting.facenormalsepsilon = 1e-6;

obj.data{surfaceIndex}.lightposition.x = 0;
obj.data{surfaceIndex}.lightposition.y = 0;
obj.data{surfaceIndex}.lightposition.z = 0;

%-------------------------------------------------------------------------%

%-surface name-%
obj.data{surfaceIndex}.name = bar_data.DisplayName;

%-------------------------------------------------------------------------%

%-surface visible-%
obj.data{surfaceIndex}.visible = strcmp(bar_data.Visible,'on');

%-------------------------------------------------------------------------%

leg = get(bar_data.Annotation);
legInfo = get(leg.LegendInformation);

switch legInfo.IconDisplayStyle
    case 'on'
        showleg = true;
    case 'off'
        showleg = false;
end

obj.data{surfaceIndex}.showlegend = showleg;

%-------------------------------------------------------------------------%

%-SETTING SCENE-%

%-------------------------------------------------------------------------%

%-aspect ratio-%
ar = obj.PlotOptions.AspectRatio;

if ~isempty(ar)
    if ischar(ar)
        scene.aspectmode = ar;
    elseif isvector(ar) && length(ar) == 3
        xar = ar(1);
        yar = ar(2);
        zar = ar(3);
    end
else

    %-define as default-%
    xar = max(xedges(:));
    zar = max(yedges(:));
    yar = 0.7*max([xar, zar]);
end

scene.aspectratio.x = xar;
scene.aspectratio.y = yar;
scene.aspectratio.z = zar;

%-------------------------------------------------------------------------%

%-camera eye-%
ey = obj.PlotOptions.CameraEye;

if ~isempty(ey)
    if isvector(ey) && length(ey) == 3
        scene.camera.eye.x = ey(1);
        scene.camera.eye.y = ey(2);
        scene.camera.eye.z = ey(3);
    end
else

    %-define as default-%
    scene.camera.eye.x = xar + 7;
    scene.camera.eye.y = yar + 0;
    scene.camera.eye.z = zar + 0.5;
end

%-------------------------------------------------------------------------%

%-axis configuration-%
scene.xaxis.range = axis_data.XLim(end:-1:1);
scene.yaxis.range = axis_data.YLim;
scene.zaxis.range = axis_data.ZLim;

scene.xaxis.tickvals = axis_data.XTick;
scene.xaxis.ticktext = axis_data.XTickLabel;

scene.yaxis.tickvals = axis_data.YTick;
scene.yaxis.ticktext = axis_data.YTickLabel;

scene.zaxis.tickvals = axis_data.ZTick;
scene.zaxis.ticktext = axis_data.ZTickLabel;

scene.xaxis.zeroline = false;
scene.yaxis.zeroline = false;
scene.zaxis.zeroline = false;

scene.xaxis.showline = true;
scene.yaxis.showline = true;
scene.zaxis.showline = true;

scene.xaxis.tickcolor = 'rgba(0,0,0,1)';
scene.yaxis.tickcolor = 'rgba(0,0,0,1)';
scene.zaxis.tickcolor = 'rgba(0,0,0,1)';

scene.xaxis.ticklabelposition = 'outside';
scene.yaxis.ticklabelposition = 'outside';
scene.zaxis.ticklabelposition = 'outside';

scene.xaxis.title = axis_data.XLabel.String;
scene.yaxis.title = axis_data.YLabel.String;
scene.zaxis.title = axis_data.ZLabel.String;

%-------------------------------------------------------------------------%

%-SET SCENE TO LAYOUT-%
obj.layout = setfield(obj.layout, sprintf('scene%d', xsource), scene);

%-------------------------------------------------------------------------%

end

function bar_ = bar_data(position3d, size_)
    % position3d - 3-list or array of shape (3,) that represents the point of coords (x, y, 0), where a bar is placed
    % size = a 3-tuple whose elements are used to scale a unit cube to get a paralelipipedic bar
    % returns - an array of shape(8,3) representing the 8 vertices of  a bar at position3d

    if nargin < 2
        size_ = [1, 1, 1];
    end

    bar_ = [...
            0, 0, 0; ...
            1, 0, 0; ...
            1, 1, 0; ...
            0, 1, 0; ...
            0, 0, 1; ...
            1, 0, 1; ...
            1, 1, 1; ...
            0, 1, 1 ...
            ]; % the vertices of the unit cube

    for n =1:size(bar_, 1)
        bar_(n,:) = bar_(n,:) .* size_; % scale the cube to get the vertices of a parallelipipedic bar_
    end

    bar_ = bar_ + position3d; %translate each  bar_ on the directio OP, with P=position3d
end

function [vertices, I, J, K] = triangulate_bar_faces(positions, sizes)
    % positions - array of shape (N, 3) that contains all positions in the plane z=0, where a histogram bar is placed
    % sizes -  array of shape (N,3); each row represents the sizes to scale a unit cube to get a bar
    % returns the array of unique vertices, and the lists i, j, k to be used in instantiating the go.Mesh3d class

    if nargin < 2
        sizes = ones(size(positions,1), 3); %[(1,1,1)]*len(positions)
    else
        sizes;
        % if isinstance(sizes, (list, np.ndarray)) and len(sizes) != len(positions):
        %     raise ValueError('Your positions and sizes lists/arrays do not have the same length')
    end

    c = 1;
    for n = 1:size(positions, 1)
        if sizes(n, 3) ~= 0
            all_bars(:,:,c) = bar_data(positions(n,:), sizes(n,:))';
            c = c+1;
        end
    end

    % all_bars = [bar_data(pos, size)  for pos, size in zip(positions, sizes) if size[2]!=0]
    [r, q, p] = size(all_bars);

    % extract unique vertices from the list of all bar vertices
    all_bars = reshape(all_bars, [r, p*q])';
    [vertices, ~, ixr] = unique(all_bars, 'rows');

    %for each bar, derive the sublists of indices i, j, k assocated to its chosen  triangulation
    I = [];
    J = [];
    K = [];

    for k = 0:p-1
        aux = ixr([1+8*k, 1+8*k+2,1+8*k, 1+8*k+5,1+8*k, 1+8*k+7, 1+8*k+5, 1+8*k+2, 1+8*k+3, 1+8*k+6, 1+8*k+7, 1+8*k+5]);
        I = [ I;  aux(:)];
        aux = ixr([1+8*k+1, 1+8*k+3, 1+8*k+4, 1+8*k+1, 1+8*k+3, 1+8*k+4, 1+8*k+1, 1+8*k+6, 1+8*k+7, 1+8*k+2, 1+8*k+4, 1+8*k+6]);
        J = [ J;  aux(:)];
        aux = ixr([1+8*k+2, 1+8*k, 1+8*k+5, 1+8*k, 1+8*k+7, 1+8*k, 1+8*k+2, 1+8*k+5, 1+8*k+6, 1+8*k+3, 1+8*k+5, 1+8*k+7]);
        K = [ K;  aux(:)];
    end

end

function [X, Y, Z, I, J, K] = get_plotly_mesh3d(xedges, yedges, values, bargap)
    % x, y- array-like of shape (n,), defining the x, and y-ccordinates of data set for which we plot a 3d hist

    xsize = xedges(2)-xedges(1)-bargap;
    ysize = yedges(2)-yedges(1)-bargap;
    [xe, ye]= meshgrid(xedges(1:end-1), yedges(1:end-1));
    ze = zeros(size(xe));

    positions = zeros([size(xe), 3]);
    positions(:,:,1) = xe;
    positions(:,:,2) = ye;
    positions(:,:,3) = ze;

    [m, n, p] = size(positions);
    positions = reshape(positions, [m*n, p]);

    h = values'; h = h(:);
    sizes = [];
    for n = 1:length(h)
        sizes = [sizes; ysize, ysize, h(n)];
    end

    [vertices, I, J, K]  = triangulate_bar_faces(positions, sizes);
    X = vertices(:,1);
    Y = vertices(:,2);
    Z = vertices(:,3);

end


function [cov] = mne_pick_channels_cov(orig,include,exclude)
%
% [cov] = mne_pick_channels_cov(orig,include,exclude)
%
% Pick desired channels from a covariance matrix
%
% orig      - The original covariance matrix
% include   - Channels to include (if empty, include all available)
% exclude   - Channels to exclude (if empty, do not exclude any)
%
%

%
%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%
%   Revision 1.9  2006/11/21 12:53:49  msh
%   Fixed error in picking
%
%   Revision 1.8  2006/06/29 22:12:28  msh
%   Fixed errors in channel picking
%
%   Revision 1.7  2006/05/03 18:53:05  msh
%   Approaching Matlab 6.5 backward compatibility
%
%   Revision 1.6  2006/04/23 15:29:40  msh
%   Added MGH to the copyright
%
%   Revision 1.5  2006/04/18 20:44:46  msh
%   Added reading of forward solution.
%   Use length instead of size when appropriate
%
%   Revision 1.4  2006/04/15 12:21:00  msh
%   Several small improvements
%
%   Revision 1.3  2006/04/14 15:49:49  msh
%   Improved the channel selection code and added ch_names to measurement info.
%
%   Revision 1.2  2006/04/14 00:45:42  msh
%   Added channel picking and fiff_invert_transform
%
%   Revision 1.1  2006/04/13 17:05:45  msh
%   Added reading of bad channels to fiff_read_meas_info.m
%   Added mne_pick_channels_cov.m
%
%

me='MNE:mne_pick_channels_cov';

if nargin == 1
    cov = orig;
    if isempty(cov.eig) || isempty(cov.eigvec)
        decompose_eigen;
    end
    return;
elseif nargin == 2
    exclude = [];
elseif nargin ~= 3
    error(me,'Incorrect number of arguments');
end

if isempty(include) && isempty(exclude)
    cov = orig;
    if isempty(cov.eig) || isempty(cov.eigvec)
        decompose_eigen;
    end
    return;
end

if isempty(orig.names)
    error(me,'Cannot pick from a covariance matrix without channel names');
end

cov  = orig;
%
%   First do the channels to be included
%
sel = fiff_pick_channels(cov.names,include,exclude);
if isempty(sel)
   error(me,'Nothing remains after picking');
end
%
%   Select the desired stuff
%
if cov.diag
   cov.data = cov.data(sel);
else
   cov.data = cov.data(:,sel);
   cov.data = cov.data(sel,:);
end
for p = 1:size(sel,2)
   names{p} = cov.names{sel(p)};
end
cov.names = names;
cov.dim   = length(cov.names);
%
%   Eigenvalues and vectors are no longer valid
%
decompose_eigen;
%
return;

    function decompose_eigen
        if cov.diag
            cov.eig    = cov.data;
            cov.eigvec = eye(cov.dim);
        else
            [ cov.eigvec, cov.eig ] = eig(cov.data);
            %
            %   We use the convention that rows of eigvec are the
            %   eigenvectors
            %
            cov.eigvec = cov.eigvec';
            cov.eig    = diag(cov.eig);
        end
    end

end


%% Example: Proton Treatment Plan with Manipulated CT values
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright 2017 the matRad development team.
%
% This file is part of the matRad project. It is subject to the license
% terms in the LICENSE file found in the top-level directory of this
% distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part
% of the matRad project, including this file, may be copied, modified,
% propagated, or distributed except according to the terms contained in the
% LICENSE file.
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%
% In this example we will show
% (i) how to load patient data into matRad
% (ii) how to setup a proton dose calculation
% (iii) how to inversely optimize the pencil beam intensities directly from command window in MATLAB.
% (iv) how to re-optimize a treatment plan
% (v) how to manipulate the CT cube by adding noise to the cube
% (vi) how to recalculate the dose considering the manipulated CT cube and the previously optimized pencil beam intensities
% (vii) how to compare the two results

%% Patient Data Import
% Let's begin with a clear Matlab environment and import the prostate
% patient into your workspace.

matRad_rc; %If this throws an error, run it from the parent directory first to set the paths

load('PROSTATE.mat');

%% Treatment Plan
% The next step is to define your treatment plan labeled as 'pln'. This
% structure requires input from the treatment planner and defines
% the most important cornerstones of your treatment plan.

pln.radiationMode           = 'protons';
pln.machine                 = 'generic_MCsquare';
pln.numOfFractions          = 30;
pln.propOpt.bioOptimization = 'const_RBExD';
pln.propStf.gantryAngles    = [90 270];
pln.propStf.couchAngles     = [0 0];
pln.propStf.bixelWidth      = 3;
pln.propStf.numOfBeams      = numel(pln.propStf.gantryAngles);
pln.propStf.isoCenter       = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct,0);
pln.propOpt.runDAO          = 0;
pln.propOpt.runSequencing   = 0;

% dose calculation settings
pln.propDoseCalc.doseGrid.resolution.x = 3; % [mm]
pln.propDoseCalc.doseGrid.resolution.y = 3; % [mm]
pln.propDoseCalc.doseGrid.resolution.z = 3; % [mm]

%% Generate Beam Geometry STF
stf = matRad_generateStf(ct,cst,pln);

%% Dose Calculation
dij = matRad_calcParticleDoseMC(ct,stf,pln,cst);

%% Inverse Optimization for IMPT
resultGUI = matRad_fluenceOptimization(dij,cst,pln);

%% Calculate quality indicators
[dvh,qi]       = matRad_indicatorWrapper(cst,pln,resultGUI);
ixRectum       = 1;
display(qi(ixRectum).D_5);

%%
% Let's change the optimization parameter of the rectum in such a way that it
% will be better spared. We increase the penalty and lower the threshold
% of the squared overdose objective function. Afterwards we re-optimize
% the treatment plan and evaluate dose statistics one more time.

objective = cst{ixRectum,6}{1}; %This gives a struct
objective = matRad_DoseOptimizationFunction.createInstanceFromStruct(objective); %Now we turn it into a class
objective = objective.setDoseParameters(40); %We can simply call this function to change the/all dose parameter(s)
cst{ixRectum,6}{1} = struct(objective); % We put it back as struct

cst{ixRectum,6}{1}.parameters{1} = 40;
cst{ixRectum,6}{1}.penalty = 500;
resultGUI               = matRad_fluenceOptimization(dij,cst,pln);
[dvh2,qi2]              = matRad_indicatorWrapper(cst,pln,resultGUI);
display(qi2(ixRectum).D_5);

%% Plot the Resulting Dose Slice
% Let's plot the transversal iso-center dose slice
slice = round(pln.propStf.isoCenter(1,3)./ct.resolution.z);
figure
imagesc(resultGUI.RBExDose(:,:,slice)),colorbar, colormap(jet)

%%
% Now let's simulate a range undershoot by scaling the relative stopping power cube by 3.5% percent
ct_manip         = ct;
ct_manip.cubeHU{1} = 1.035*ct_manip.cubeHU{1};

%% Recalculate Plan with MC square
% Let's use the existing optimized pencil beam weights and recalculate the RBE weighted dose
resultGUI_noise = matRad_calcDoseDirectMC(ct_manip,stf,pln,cst,resultGUI.w);

%%  Visual Comparison of results
% Let's compare the new recalculation against the optimization result.
plane      = 3;
doseWindow = [0 max([resultGUI.RBExDose(:); resultGUI_noise.RBExDose(:)])];

figure,title('original plan')
matRad_plotSliceWrapper(gca,ct,cst,1,resultGUI.RBExDose,plane,slice,[],0.75,colorcube,[],doseWindow,[]);
figure,title('manipulated plan')
matRad_plotSliceWrapper(gca,ct_manip,cst,1,resultGUI_noise.RBExDose,plane,slice,[],0.75,colorcube,[],doseWindow,[]);

% Let's plot single profiles along the beam direction
ixProfileY = round(pln.propStf.isoCenter(1,1)./ct.resolution.x);

profileOrginal = resultGUI.RBExDose(:,ixProfileY,slice);
profileNoise   = resultGUI_noise.RBExDose(:,ixProfileY,slice);

figure,plot(profileOrginal,'LineWidth',2),grid on,hold on,
       plot(profileNoise,'LineWidth',2),legend({'original profile','noise profile'}),
       xlabel('mm'),ylabel('Gy(RBE)'),title('profile plot')

%% Quantitative Comparison of results
% Compare the two dose cubes using a gamma-index analysis.

doseDifference   = 2;
distToAgreement  = 2;
n                = 1;

[gammaCube,gammaPassRateCell] = matRad_gammaIndex(...
    resultGUI_noise.RBExDose,resultGUI.RBExDose,...
    [ct.resolution.x, ct.resolution.y, ct.resolution.z],...
    [doseDifference distToAgreement],slice,n,'global',cst);


% epoch() - Extract epochs time locked to specified events from continuous EEG data.
%
% Usage:
%   >> epocheddata = epoch( data, events, timelim);
%   >> [epocheddata, newtime, indices, rerefevent, rereflatencies ] = ...
%                      epoch( data, events, timelim, 'key1', value1, ... );
%
% Inputs:
%   data       - input data (chan,frames). In the case, data is a
%                3D array (chan, frames, epochs), epochs are extracted
%                only if their time windows fall within existing
%                pre-existing epochs.
%   events     - vector events (expressed in seconds or points)
%   timelim    - [init end] in second or points centered
%                on the events (i.e. [-1 2])
%
% Optional inputs:
%   'srate'      - sampling rate in Hz for events expressed in seconds
%   'valuelim'   - upper and lower limit of values that a trial should not
%                overpass. If one positive value is given, consider the
%                opposite for lower bound. Given values are also consider
%                outlier (if equal the trial is rejected). Default: none.
%   'verbose'    - ['on'|'off']. Default is 'on'.
%   'allevents'  - event vector containing the latencies of all events
%                (not only those used for epoching). The function
%                return an array 'rerefevent' which contain the latency
%                of these events in each trials (assuming the events are
%                included in the trial time window). These events can
%                be in point or second but they must be in the same format
%                as the events used for epoching.
%   'alleventrange' - for event selection, defines a time range [start end] (in
%                seconds or data points) relative to the time-locking events.
%                Default is same as 'timelim'.
%
% Outputs:
%   epocheddata - output (chan, frames, epochs)
%   indices     - indices of accepted events
%   newtime     - new time limits. See notes.
%   rerefevent  - re-referenced event cell array (size nbepochs) of array
%                 indices for each epochs (note that the number of events
%                 per trial may vary).
%   rereflatencies - re-referenced latencies event cell array (same as above
%                 but indicates event latencies in epochs instead of event
%                 indices).
%
% Note: maximum time limit will be reduced by one point with comparison to the
%       input time limits. For instance at 100 Hz, 3 seconds last 300 points,
%       but if we assign time 0 to the first point, then we must assign time
%       299 to the last point.
%
% Author: Arnaud Delorme, CNL / Salk Institute, 2001
%
% See also: pop_epoch(), eeglab()

% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This program 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 2 of the License, or
% (at your option) any later version.
%
% This program 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 this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function [epochdat, newtime, indexes, alleventout, alllatencyout, reallim] = epoch( data, events, lim, varargin );

if nargin < 2
   help epoch;
	return;
end;
alleventout = {};

% create structure
% ----------------
if ~isempty(varargin)
   try, g = struct(varargin{:});
   catch, error('Epoch: wrong syntax in function arguments'); end;
else
    g = [];
end;

try, g.srate; 	 	     catch, g.srate = 1; end;
try, g.valuelim; 	     catch, g.valuelim =  [-Inf Inf]; end;
try, g.verbose; 	     catch, g.verbose = 'on'; end;
try, g.allevents; 	     catch, g.allevents = []; end;
try, g.alleventrange; 	 catch, g.alleventrange = lim; end;

% computing point limits
% ----------------------
reallim(1) = round(lim(1)*g.srate);   % compute offset
reallim(2) = round(lim(2)*g.srate-1); % compute offset

% epoching
% --------
fprintf('Epoching...\n');
newdatalength = reallim(2)-reallim(1)+1;

epochdat = zeros( size(data,1), newdatalength, length(events) );
g.allevents =  g.allevents(:)';
datawidth  = size(data,2)*size(data,3);
dataframes = size(data,2);
indexes = zeros(length(events),1);
alleventout = {};
alllatencyout = {};
for index = 1:length(events)
	pos0 = floor(events(index)*g.srate); % offset of time locking event
	posinit = pos0+reallim(1); % compute offset
	posend  = pos0+reallim(2); % compute offset

   if floor((posinit-1)/dataframes) == floor((posend-1)/dataframes) & posinit >= 1 & posend <= datawidth % test if within boundaries
      epochdat(:,:,index) = data(:,posinit:posend);
      if ~isinf(g.valuelim(1)) | ~isinf(g.valuelim(2))
          if (max(epochdat(:,:,index)) > g.valuelim(1)) & ...
                  (max(epochdat(:,:,index)) < g.valuelim(2))
              indexes(index) = 1;
          else
              switch g.verbose, case 'on', fprintf('Warning: event %d out of value limits\n', index); end;
          end;
      else
          indexes(index) = 1;
      end;
   else
      switch g.verbose, case 'on', fprintf('Warning: event %d out of data boundary\n', index); end;
   end;

   % rereference events
   % ------------------
   if ~isempty(g.allevents)
        posinit = pos0 + g.alleventrange(1)*g.srate; % compute offset
        posend  = pos0 + g.alleventrange(2)*g.srate; % compute offset
        eventtrial = intersect( find(g.allevents*g.srate >= posinit),  find(g.allevents*g.srate <= posend) );
        alleventout{index} = eventtrial;
        alllatencyout{index} = g.allevents(eventtrial)*g.srate-pos0;
   end;
end;
newtime(1) = reallim(1)/g.srate;
newtime(2) = reallim(2)/g.srate;

indexes = find(indexes == 1);
epochdat = epochdat(:,:,indexes);
if ~isempty(alleventout)
    alleventout = alleventout(indexes);
    alllatencyout= alllatencyout(indexes);
end;
reallim = reallim*g.srate;
return;

%% GENERATION OF NAN IN ARRAYS (old implementation)
%% ------------------------------------------------
%alleventout(index,1:length(eventtrial) ) = eventtrial+1000000;
%%then replace all zeros by Nan and subtract 1000000
%if ~isempty(alleventout)
%    alleventout( find( alleventout == 0) ) = nan;
%    alleventout = alleventout(indexes,:) - 1000000;
%   alllatencyout( find( alllatencyout == 0) ) = nan;
%   alllatencyout = alllatencyout(indexes,:) - 1000000;
%end;

function res = lat2point( lat, srate, pnts);

res = lat*srate+1 + (epoch_array-1)*pnts;


function I = eye(d)
%EYE       Identity operator.
%   This function is deprecated. Use OPERATORBLOCK.EYE.

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

I = linop( operatorBlock.eye(double(d)) );

end


function jed = nyt_to_jed ( volume, issue )

%*****************************************************************************80
%
%% NYT_TO_JED converts an NYT date to a JED.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer VOLUME, ISSUE, the New York Times
%    volume and issue.
%
%    Output, real JED, the Julian Ephemeris Date.
%
  jed_epoch_50000 = 2449790.5;

  if ( 149 < volume )

    jed = jed_epoch_50000 + issue - 50000 + 500;
%
%  Take care of the bizarre case of the second half of Volume 149,
%  Jan 1 2000 to Sep 17 2000, issues 51254 through ?, which were also
%  lowered by 500.
%
  elseif ( volume == 149 && issue < 51600 )
    jed = jed_epoch_50000 + issue - 50000 + 500;
  elseif ( 44028 <= issue )
    jed = jed_epoch_50000 + issue - 50000;
%
%  Factor in the strike of 1978.
%
  else
    jed = jed_epoch_50000 + issue - 50000 - 88;
  end

  return
end


function idxs = get_unary_idxs_global_sort(unProb,max_detections)

unProbThresh = unProb;
scores = sort(reshape(unProb, size(unProb,1)*size(unProb,2),1));
j = 1;
while (length(find(sum(unProbThresh,2) > 0)) > max_detections && j <= length(scores))
    unProbThresh = unProb;
    for m = 1:size(unProb,2)
        unProbThresh(unProb(:,m) < scores(j),m) = 0;
    end
    j = j + 1;
end

min_det_score_found = scores(j);
fprintf('found min_det_score: %1.2f\n',min_det_score_found);

idxs = find(sum(unProbThresh,2) > 0);
end


function best_acc = LCKSVD_top(dataset, N_train, k, ...
        sparsitythres, valpha, vbeta)
    % Syntax: LCKSVD_top(dataset, N_train, k, sparsitythres, valpha, vbeta)
    addpath(genpath('utils'));  % add K-SVD box
    addpath(genpath('LCKSVD'));  % add K-SVD box
    addpath('build_spams');
    addpath('utils');
    best_acc = zeros(1, 2);
    if nargin == 0
        dataset = 'myYaleB';
        N_train = 10;
        k = 8;
        sparsitythres = 10;
        valpha = 0.01;
        vbeta = 0.01;
    end
    %% get data
    [dataset, Y_train, Y_test, label_train, label_test] = train_test_split(...
        dataset, N_train);
    %% main
    [acc, rt] = LCKSVD_wrapper(Y_train, label_train, Y_test, label_test,...
                    k, sparsitythres, valpha, vbeta);
    %% save data
    if ~exist('results', 'dir')
        mkdir('results');
    end
    if ~exist(fullfile('results', 'LCKSVD'), 'dir')
            mkdir('results', 'LCKSVD');
        end
    fn1 = fullfile('results', 'LCKSVD', strcat(dataset, '_N_', ...
        num2str(N_train), '_k_', num2str(k), '_a_', num2str(valpha), '_b_', ...
        num2str(vbeta), '_', getTimeStr(), '_1.mat'));
    disp(fn1);
    fn2 = fullfile('results', 'LCKSVD', strcat(dataset, '_N_', ...
        num2str(N_train), '_k_', num2str(k), '_a_', num2str(valpha), ...
        '_b_', num2str(vbeta), '_', getTimeStr(), '_2.mat'));
    best_acc = acc;
    rrt = rt;
    acc = best_acc(1);
    rt = rrt(1);
    save(fn1, 'acc', 'rt');
    acc = best_acc(2);
    rt = rrt(2);
    save(fn2, 'acc', 'rt');
end


function [f,A,b,sdcone] = optiReadSDPA(filename,dense,print)
%OPTIREADSDPA  Read an SDPA (.dat-s or .dat) file and convert to Matlab Values
%
% [f,A,b,sdcone] = optiReadSDPA(filename) reads the sparse file specified by
% filename and return the semidefinite problem in OPTI format. If you do
% not specify a file a extension, it will default to .dat-s.
%
% [f,A,b,sdcone] = optReadSDPA(filename,dense) allows the user to specify
% whether the file is dense or not. dense = 1 indicates a dense SDPA file,
% and the file extensions will default to .dat if not provided. The default
% is sparse.
%
% [f,A,b,sdcone] = optiReadSDPA(filename,dense,print) allows print out of
% reading progress.
%
%
% *sdcone will be a cell array, where each cell is a sparse matrix of the
% form [C(:) A0(:) A1(:) ... ], containing symmetric matrices.

%   Copyright (C) 2013 Jonathan Currie (I2C2)
%#ok<*AGROW>

if(nargin < 2), dense = 0; end
if(nargin < 3), print = 0; end

% Make sure we have file extension!
if(isempty(strfind(filename,'.')))
    filename = [filename '.dat-s'];
end

%Open File
fid = fopen(filename);
if(fid == -1)
    error('Error opening file %s',filename);
end

%States
sNCON = 1;
sNBLOCKS = 2;
sSIZES = 3;
sRHS = 4;
sDNDATA = 5;
sSPDATA = 6;

%Default Internals
eof = 0;
state = sNCON; cind = 0; bind = 1; rind = 1;
f = []; A = []; b = []; sdcone = [];

if(print)
    ind = strfind(filename,filesep);
    if(isempty(ind))
        file = filename;
    else
        file = filename(ind(end)+1:end);
    end
    if(dense)
        fprintf('Reading Dense SDPA File ''%s''...\n',file);
    else
        fprintf('Reading Sparse SDPA File ''%s''...\n',file);
    end
end
try
    %Main Loop
    while(~eof)
        %Read DAT File String
        str = fgetl(fid);
        %Check for comment, skip if found
        if(str(1) == '*' || str(1) == '"')
            continue;
        end
        %Replace { } ( ) [ ] , ; : with spaces
        str = regexprep(str,{'[',']',',','{','}','(',')'},' ');
        %Decode based on state
        switch(state)
            case sNCON
                M = sscanf(str,'%d',1);
                %Check for errors
                if(M < 1 || M > 1e9), error('The number of constraints is negative or > 1e9'); end
                %Print what we found
                if(print), fprintf('Variables:              %6d\n',M); end
                state = sNBLOCKS;
            case sNBLOCKS
                N = sscanf(str,'%d',1);
                %Check for errors
                if(N < 1 || N > 1e9), error('The number of blocks is negative or > 1e9'); end
                %Print what we found
                if(print), fprintf('Number of Blocks:       %6d\n',N); end
                state = sSIZES;
            case sSIZES
                blocksize = sscanf(str,'%d');
                %Check length = number of blocks
                if(length(blocksize) ~= N), error('The number of blocks does not match the number of entries of block sizes'); end
                if(any(blocksize == 0) || any(blocksize > 1e9)), error('A block size is 0 or > 1e9'); end
                %Print Total Dims
                if(print)
                    fprintf('  Linear:               %6d\n',length(blocksize(blocksize < 0)));
                    fprintf('  Semidefinite:         %6d\n',length(blocksize(blocksize > 0)));
                    fprintf('Total Block Dimension:  %6d\n',sum(abs(blocksize)));
                end
                %Allocate problem data
                sdcone = cell(sum(blocksize > 0),1); j = 1;
                for i = 1:N
                    if(blocksize(i) > 0)
                        if(dense)
                            sdcone{j} = zeros(blocksize(i)^2,M+1);
                        else
                            sdcone{j} = sparse(blocksize(i)^2,M+1); %not the greatest...
                        end
                        j = j + 1;
                    end
                end
                %Create linear part
                ind = blocksize < 0;
                if(any(ind))
                    if(dense)
                        A = zeros(sum(abs(blocksize(ind))),M);
                    else
                        A = sparse(sum(abs(blocksize(ind))),M);
                    end
                    b = zeros(sum(abs(blocksize(ind))),1);
                end
                %Create index vector
                blockindex = zeros(N,1);  lp = 1; sdp = 1;
                for i = 1:N
                    if(blocksize(i) < 0)
                        blockindex(i) = lp; lp  = lp + 1;
                    else
                        blockindex(i) = sdp; sdp = sdp + 1;
                    end
                end
                state = sRHS;
            case sRHS
                f = sscanf(str,'%f'); f = -f;
                %Check length = number of constraints
                if(length(f) ~= M), error('The number of RHS elements does not match the number of constraints'); end
                if(dense)
                    state = sDNDATA;
                else
                    state = sSPDATA;
                end
            %Sparse Data File
            case sSPDATA
                data = sscanf(str,'%d %d %d %d %f');
                if(~isempty(data)) %could be {}
                    %Check for C matrix
                    if(data(1) == 0)
                        %Check block for linear
                        if(blocksize(data(2)) < 0)
                            if(data(3) ~= data(4)), error('A diagonal entry in C is not on the diagonal!'); end
                            %Find start index by determining sizes of previous LP blocks encountered
                            bsizes = blocksize(1:data(2)-1);
                            stIndex = abs(sum(bsizes(bsizes < 0)));
                            b(stIndex + data(3)) = -data(5);
                        else %semidef
                            sdcone{blockindex(data(2))}(data(3) + (data(4) - 1)*blocksize(data(2)),1) = data(5);
                            %if off-diagonal, place in transposed position (build symmetric matrices)
                            if(data(3) ~= data(4))
                                sdcone{blockindex(data(2))}(data(4) + (data(3) - 1)*blocksize(data(2)),1) = data(5);
                            end
                        end
                    else
                        %Check block for linear
                        if(blocksize(data(2)) < 0)
                            if(data(3) ~= data(4)), error('A diagonal entry in A is not on the diagonal!'); end
                            %Find start index by determining sizes of previous LP blocks encountered
                            bsizes = blocksize(1:data(2)-1);
                            stIndex = abs(sum(bsizes(bsizes < 0)));
                            A(stIndex + data(3),data(1)) = data(5);
                        else %semidef
                            sdcone{blockindex(data(2))}(data(3) + (data(4) - 1)*blocksize(data(2)),data(1)+1) = -data(5);
                            %if off-diagonal, place in transposed position (build symmetric matrices)
                            if(data(3) ~= data(4))
                                sdcone{blockindex(data(2))}(data(4) + (data(3) - 1)*blocksize(data(2)),data(1)+1) = -data(5);
                            end
                        end
                    end
                end
            %Dense Data File
            case sDNDATA
                data = sscanf(str,'%f');
                if(~isempty(data)) %could be {}
                    %Check for C matrix
                    if(cind == 0)
                        %Check block for linear
                        if(blocksize(bind) < 0)
                            if(length(data) ~= abs(blocksize(bind))), error('Data read in dense entry C (diagonal) is not the correct length!'); end
                            %Find start index by determining sizes of previous LP blocks encountered
                            bsizes = blocksize(1:bind-1);
                            stIndex = abs(sum(bsizes(bsizes < 0)))+1;
                            b(stIndex:stIndex+abs(blocksize(bind))-1) = -data;
                        else
                            if(length(data) == blocksize(bind))
                                sdcone{blockindex(bind)}(rind:blocksize(bind):blocksize(bind)^2) = data;
                                rind = rind + 1;
                            elseif(length(data) == blocksize(bind)^2)
                                %Create matrix and transpose it
                                temp = reshape(data,blocksize(bind),blocksize(bind))';
                                sdcone{blockindex(bind)}(:,1) = temp(:);
                                rind = rind + blocksize(bind);
                            else
                                error('Data read in dense entry C matrix is not the correct length. Expected first row of a matrix, or the entire matrix (all rows and columns, row major).');
                            end
                        end
                    else
                        %Check block for linear
                        if(blocksize(bind) < 0)
                            if(length(data) ~= abs(blocksize(bind))), error('Data read in dense entry A%d (diagonal) is not the correct length!',cind); end
                            %Find start index by determining sizes of previous LP blocks encountered
                            bsizes = blocksize(1:bind-1);
                            stIndex = abs(sum(bsizes(bsizes < 0)))+1;
                            A(stIndex:stIndex+abs(blocksize(bind))-1,cind) = data;
                        else
                            if(length(data) == blocksize(bind))
                                sdcone{blockindex(bind)}(rind + (cind)*blocksize(bind)^2:blocksize(bind):blocksize(bind)^2 + (cind)*blocksize(bind)^2) = -data;
                                rind = rind + 1;
                            elseif(length(data) == blocksize(bind)^2)
                                %Create matrix and transpose it
                                temp = reshape(data,blocksize(bind),blocksize(bind))';
                                sdcone{blockindex(bind)}(:,cind+1) = -temp(:);
                                rind = rind + blocksize(bind);
                            else
                                error('Data read in dense entry A%d matrix is not the correct length. Expected first row of a matrix, or the entire matrix (all rows and columns, row major).',cind);
                            end
                        end
                    end
                    %Increment pointers
                    if(blocksize(bind) < 0 || rind > blocksize(bind))
                        rind = 1;
                        bind = bind + 1;
                    end
                    if(bind > N)
                        bind = 1;
                        cind = cind + 1;
                    end
                end
        end
        eof = feof(fid);
    end
catch ME
    fclose(fid);
    rethrow(ME);
end

%Ensure sparse return args
if(~isempty(sdcone))
    for i = 1:length(sdcone)
        if(~issparse(sdcone{i}))
            sdcone{i} = sparse(sdcone{i});
        end
    end
end
if(~isempty(A))
    if(~issparse(A)), A = sparse(A); end
end
if(print)
    nz = 0;
    if(~isempty(sdcone))
        for i = 1:length(sdcone)
            nz = nz + nnz(sdcone{i});
        end
    end
    fprintf('Total Semidefinite NZs: %6d\n',nz);
    fprintf('Finished Reading SDPA File\n\n');
end
%Close
fclose(fid);


function r = minus(p,q)
%MINUS: this function subtracts the x, y, and z values of the structures that I use in
% the FVtool.
%
% SYNOPSIS:
%
%
% PARAMETERS:
%
%
% RETURNS:
%
%
% EXAMPLE:
%
% SEE ALSO:
%

% Copyright (c) 2012-2016 Ali Akbar Eftekhari
% See the license file

% First implementation:
% m = size(p.xvalue);
% d = ndims(p.xvalue);
% if (min(m) == 1) % 1D: only x value
%     r.xvalue = p.xvalue-q.xvalue;
% elseif (d == 2) % 2D: x and y values
%     r.xvalue = p.xvalue-q.xvalue;
%     r.yvalue = p.yvalue-q.yvalue;
% else % 3D:x, y, and z values
%     r.xvalue = p.xvalue-q.xvalue;
%     r.yvalue = p.yvalue-q.yvalue;
%     r.zvalue = p.zvalue-q.zvalue;
% end
r = p+(-q);


function [a]=minus(b,c)
%A=B-C
%   [A]=MINUS(B,C) Subtraction of two TT-matrices, B and C
%
%
% TT-Toolbox 2.2, 2009-2012
%
%This is TT Toolbox, written by Ivan Oseledets et al.
%Institute of Numerical Mathematics, Moscow, Russia
%webpage: http://spring.inm.ras.ru/osel
%
%For all questions, bugs and suggestions please mail
%ivan.oseledets@gmail.com
%---------------------------
a=b+(-1.0)*c;
return
end


function Xrle=rle(XZv)
L=length(XZv);
j=1;
k=1;
i=1;
while i<2*L
    comp=1;
    for j=j:L
        if j==L
            break
        end;
         if XZv(j)==XZv(j+1)
            comp=comp+1;
        else
            break
        end;
    end;
        Xrle(k+1)=comp;
        Xrle(k)=XZv(j);
        if j==L & XZv(j-1)==XZv(j)
            break
        end;
        i=i+1;
        k=k+2;
        j=j+1;
        if j==L
            if mod(L,2)==0
            Xrle(k+1)=1;
            Xrle(k)=XZv(j);
            else
            Xrle(k+1)=1;
            Xrle(k)=XZv(j);
                       end;
             break
        end;
    end;


function X = abs(X)
%ABS (overloaded)

X = reshape(abs(reshape(X,prod(X.dim),1)),X.dim);


function pts2annotations(directory)
% pts2annotations(directory)
%
% Converts annotations from pts format to our native .mat format.
%
%                         PARAMETERS
%
% directory Path to directory where the .pts files are stored,
%           along with the associated images.
%
% Author: Luca Vezzaro (elvezzaro@gmail.com)

landmark_files = dir(sprintf('%s/*.pts', directory));

app = imread(sprintf('%s/%s', directory, landmark_files(1).name(1:end-4)));

for i=1:numel(landmark_files)
	fid = fopen(sprintf('%s/%s', directory, landmark_files(i).name), 'r');

	% First line must be "version: 1"
	data = fgetl(fid);
	assert(strcmp(data, 'version: 1'));

	% Second line must be "n_points: <n>"
	num_points = fscanf(fid, 'n_points: %d\n');
	data = fgetl(fid);

	% Third line is "{"
	assert(strcmp(data, '{'));

	% Read annotation data
	for j=1:num_points
		P = fscanf(fid, '%f', 2);
		shape(j,1) = P(1);
		shape(j,2) = P(2);
	end

	% Match end of line
	data = fgetl(fid);
  assert(strcmp(data, ''));

  % Last line is "}"
  data = fgetl(fid);
	assert(strcmp(data, '}'));

	fclose(fid);

	% Convert to cartesian coordinates
	annotations(:,1) = shape(:,1);
	annotations(:,2) = repmat(size(app, 1), [num_points 1]) - shape(:,2);

	save(sprintf('%s/%s.mat', directory, landmark_files(i).name(1:end-4)), 'annotations');
end


function disp_(p)
%DISP_        Display of polynom in "disp_" mode
%

% written  07/22/02     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
%

  olddisp = intvalinit('display',0);
  intvalinit('display_',0);
  display(p,inputname(1));
  intvalinit(olddisp,0);


function [Data]=ReconstructImage(amp,phi,nb)
if (max(size(size(amp)))~=3)
    error('amp and phi must be three dimensional [nf,lat,lon]')
end

[~,ny,nx]=size(amp);

Data=zeros(nb,ny,nx);

h= waitbar(0,'Total Progress:');
WBarOuterPosition=get(h,'OuterPosition');
WBarOuterPosition(2)=WBarOuterPosition(2)-WBarOuterPosition(4);
h2=waitbar(0,'Calculating, please wait ...');
set(h2,'OuterPosition',WBarOuterPosition);

for Sample=1:nx
    waitbar(Sample/nx,h);
    for Line=1:ny
        waitbar(Line/ny,h2,['Line:' num2str(Line) ', Sample:' num2str(Sample)]);
        amp_Pixel=squeeze(amp(:,Line,Sample));
        phi_Pixel=squeeze(phi(:,Line,Sample));
        Data(:,Line,Sample)=ReconHANTSData(amp_Pixel,phi_Pixel,nb);
    end
end
close(h);
close(h2);
end


function summarize(X,Time,Spec,vintage)
%summarize Display the detail table for data entering the DFM
%
% Description:
%   Display the detail table for the nowcast, decomposing nowcast changes
%   into news and impacts for released data series.

% Print results to command window
fprintf('\n\n\n');
fprintf('Table 2: Data Summary \n');

[T,N] = size(X);
%fprintf('Vintage: %s \n',datestr(datenum(vintage,'yyyy-mm-dd'),'mmmm dd, yyyy'));
fprintf('N = %4d data series \n',N);
fprintf('T = %4d observations from %10s to %10s \n',T,datestr(Time(1),'yyyy-mm-dd'),datestr(Time(end),'yyyy-mm-dd'));

fprintf('%30s | %17s    %12s    %10s    %8s    %8s    %8s    %8s \n',...
        'Data Series','Observations','Units','Frequency','Mean','Std. Dev.','Min','Max');
fprintf([repmat('-',1,130) '\n']);

for i = 1:N

    % time indexes for which there are observed values for series i
    t_obs = ~isnan(X(:,i));

    data_series = Spec.SeriesName{i};
    if length(data_series) > 30
        data_series = [data_series(1:27) '...'];
    end
    series_id   = Spec.SeriesID{i};
    if length(series_id) > 28
        series_id = [series_id(1:25) '...'];
    end
    series_id   = ['[' series_id ']'];
    num_obs     = length(X(t_obs,i));
    freq        = Spec.Frequency{i};
    if strcmp('m',freq)
        format_date = 'mmm yyyy';
        frequency   = 'Monthly';
    elseif strcmp('q',freq)
        format_date = 'QQ yyyy';
        frequency   = 'Quarterly';
    end
    units       = Spec.Units{i};
    transform   = Spec.Transformation{i};
    % display transformed units
    if strfind(units,'Index')
        units_transformed = 'Index';
    elseif strcmp('chg',transform)
        if strfind(units,'%')
            units_transformed = 'Ppt. change';
        else
            units_transformed = 'Level change';
        end
    elseif strcmp('pch',transform) && strcmp('m',freq)
        units_transformed = 'MoM%';
    elseif strcmp('pca',transform) && strcmp('q',freq)
        units_transformed = 'QoQ% AR';
    else
        if length([units ' (' transform ')']) > 12
            units_transformed = [units(1:6) ' (' transform ')'];
        else
            units_transformed = [units ' (' transform ')'];
        end
    end
    t_obs_start = find(t_obs,1,'first');
    t_obs_end   = find(t_obs,1,'last');
    obs_date_start  = datestr(Time(t_obs_start),format_date);
    obs_date_end    = datestr(Time(t_obs_end  ),format_date);
    date_range  = [obs_date_start '-' obs_date_end];
    y           = X(t_obs,i);
    d           = Time(t_obs);
    mean_series = mean(y,'omitnan');
    stdv_series = std(y,'omitnan');
    [min_series,t_min] = min(y);
    [max_series,t_max] = max(y);
    min_date = datestr(d(t_min),format_date);
    max_date = datestr(d(t_max),format_date);
    fprintf('%30s | %17d    %12s    %10s    %8.1f    %8.1f    %8.1f    %8.1f \n',...
            data_series,num_obs,units_transformed,frequency,mean_series,stdv_series,min_series,max_series);
    fprintf('%30s | %17s    %12s    %10s    %8s    %8s    %8s    %8s \n',...
            series_id,date_range,'','','','',min_date,max_date);

end

fprintf('\n\n\n');

end


classdef TestSuperpixelSEEDS
    %TestSuperpixelSEEDS

    methods (Static)
        function test_1
            img = cv.imread(fullfile(mexopencv.root(),'test','fruits.jpg'), ...
                'Color',true, 'ReduceScale',2);
            lab = cv.cvtColor(img, 'RGB2Lab');

            superpix = cv.SuperpixelSEEDS(size(lab), 150, 4);
            superpix.iterate(lab);

            num = superpix.getNumberOfSuperpixels();
            validateattributes(num, {'numeric'}, ...
                {'scalar', 'integer', 'nonnegative'});

            L = superpix.getLabels();
            validateattributes(L, {'int32'}, ...
                {'size',[size(img,1) size(img,2)], '>=',0, '<',num});

            mask = superpix.getLabelContourMask();
            validateattributes(mask, {'logical'}, ...
                {'size',[size(img,1) size(img,2)]});
        end
    end

end


function NewCalls = SeperateLong22s_Callback(hObject, eventdata, handles, inputfile, Calls)
%% Get if clicked through menu, or using the long call network
if nargin == 3
    [trainingdata, trainingpath] = uigetfile([handles.data.settings.detectionfolder '/*.mat'],'Select Detection File','MultiSelect', 'off');
    [audioname, audiopath] = uigetfile({
        '*.wav;*.ogg;*.flac;*.UVD;*.au;*.aiff;*.aif;*.aifc;*.mp3;*.m4a;*.mp4' 'Audio File'
        '*.wav' 'WAVE'
        '*.flac' 'FLAC'
        '*.ogg' 'OGG'
        '*.UVD' 'Ultravox File'
        '*.aiff;*.aif', 'AIFF'
        '*.aifc', 'AIFC'
        '*.mp3', 'MP3 (it''s probably a bad idea to record in MP3'
        '*.m4a;*.mp4' 'MPEG-4 AAC'
        }, ['Select Corresponding Audio File for ' trainingdata], handles.data.settings.audiofolder);

    inputfile = fullfile(audiopath, audioname);
    hc = waitbar(0,'Loading File');
    Calls = loadCallfile([trainingpath trainingdata],handles);

end

audiodata = audioinfo(inputfile);
if audiodata.NumChannels > 1
    warning('Audio file contains more than one channel. Use channel 1...')
end

newBoxes = [];
newScores = [];
newPower = [];

%% First, find all the overlapping calls

% Get the oldBoxes
oldBoxes = Calls.Box;

% Pad the oldBoxes so that all of the audio is contained within the box
oldBoxes(:,1) = oldBoxes(:,1) - 0.5;
oldBoxes(:,2) = oldBoxes(:,2) - 2.0;
oldBoxes(:,3) = oldBoxes(:,3) + 1.0;
oldBoxes(:,4) = oldBoxes(:,4) + 4.0;

% Calculate overlap ratio
overlapRatio = bboxOverlapRatio(oldBoxes, oldBoxes);

g = graph(overlapRatio);

% Make new oldBoxes from the minimum and maximum start and end time of each
% overlapping box.
componentIndices = conncomp(g);
begin_time = accumarray(componentIndices', oldBoxes(:,1), [], @min);
lower_freq = accumarray(componentIndices', oldBoxes(:,2), [], @min);
end_time__ = accumarray(componentIndices', oldBoxes(:,1)+oldBoxes(:,3), [], @max);
high_freq_ = accumarray(componentIndices', oldBoxes(:,2)+oldBoxes(:,4), [], @max);

merged_scores = accumarray(componentIndices', Calls.Score, [], @mean);

call_duration = end_time__ - begin_time;
call_bandwidth = high_freq_ - lower_freq;

%% Now, extract the spectrogram from each box, and find the calls within the box by using tonality
for i=1:length(begin_time)

    % If ran through the menu
    if nargin == 3
        waitbar(i/height(Calls),hc,'Splitting Calls');
    end

    % Get the audio
    WindL=round((begin_time(i)-0.1) .* audiodata.SampleRate);
    pad = [];
    if WindL<=1
        pad=zeros(abs(WindL),1);
        WindL = 1;
    end
    WindR=round((end_time__(i)+0.1) .* audiodata.SampleRate);
    WindR = min(WindR,audiodata.TotalSamples); % Prevent WindR from being greater than total samples

    audio = audioread(inputfile,[WindL WindR]); % Take channel 1
    audio = [pad; mean(audio - mean(audio,1),2)];

    % Make the spectrogram
    windowsize = round(audiodata.SampleRate * 0.02);
    noverlap = round(audiodata.SampleRate * 0.01);
    nfft = round(audiodata.SampleRate * 0.02);

    [s, fr, ti] = spectrogram(audio,windowsize,noverlap,nfft,audiodata.SampleRate,'yaxis');

    % Get the part of the spectrogram within the frequency bandwidth
    x1 = axes2pix(length(ti),ti,call_duration(i));
    x2 = axes2pix(length(ti),ti,call_duration(i));
    lowfreq = axes2pix(length(fr),fr./1000,lower_freq(i));
    hi_freq = axes2pix(length(fr),fr./1000,high_freq_(i));
    I = abs(s(round(lowfreq:hi_freq),:));
    % Calculate the entropy
    entropy = 1 - (geomean(I,1) ./ mean(I,1));

    % Tonality of the upper region
    I2 = abs(s(round(hi_freq:min(2*hi_freq-lowfreq,size(s,1))),:));
    UpperEntropy = 1 - (geomean(I2,1) ./ mean(I2,1));
    % Use MAD to estimate mean and sd of entropy
    EntropyMedian = median(UpperEntropy);
    EntropySD = 1.4826 * median(abs(EntropyMedian - UpperEntropy));

    CallRegions = entropy > EntropyMedian + EntropySD*3;
    %CallRegions = entropy > EntropyMedian + 0.1;
    % Calls must have continuously high tonality
    radius = find(ti>0.1,1);
    CallRegions = movmean(CallRegions,radius);

    CallRegions = [0, CallRegions, 0];
    startime = find(CallRegions(1:end-1) < 0.5 & CallRegions(2:end) >= 0.5);
    stoptime = find(CallRegions(1:end-1) >= 0.5 & CallRegions(2:end) < 0.5);

    newBoxes = [newBoxes
        ti(startime)' + (WindL ./ audiodata.SampleRate),...
        repmat(lower_freq(i),length(startime),1),...
        ti(stoptime - startime)',...
        repmat(high_freq_(i)-lower_freq(i),length(startime),1)];

    newScores = [newScores; repmat(merged_scores(i),length(startime),1)];
end

%%

% Now that we have new boxes of high tonality regions, exclude the new
% boxes that don't overlap with the old boxes.
overlapRatio = bboxOverlapRatio(newBoxes, oldBoxes);
OverlapsWithOld = any(overlapRatio,2);

% Re Make Call Structure
for i=1:size(newBoxes,1)
    if nargin == 3
        waitbar(i/length(newBoxes),hc,'Remaking Structure');
    end

    if ~OverlapsWithOld; continue; end

    % Final Structure
    NewCalls(i).Box=newBoxes(i,:);
    NewCalls(i).Score=newScores(i);
    NewCalls(i).Type=categorical({'USV'});
    NewCalls(i).Accept=1;

end
    NewCalls = struct2table(NewCalls);

if nargin == 3
    [FileName,PathName] = uiputfile(fullfile(handles.data.settings.detectionfolder,trainingdata),'Save Merged Detections');
    waitbar(i/length(newBoxes),hc,'Saving...');
    Calls = NewCalls;
    save(fullfile(PathName, FileName), 'Calls', 'audiodata', '-v7.3');
    update_folders(hObject, eventdata, handles);
    close(hc);
end


% This function selects events around a seismic
% station that fullfill certain criteria;

report_this_filefun(mfilename('fullpath'));

load /Seis/obelix/stefan/split_data2/ak8897.mat
ty1 = '+'
ty2 = 'o'
ty2 = 'x'
par1 = 100;minmag = 4;

los = input('Longitude: ')
las = input('Latitude: ')

pl = plot(los,las,'rs')
set(pl,'LineWidth',1.0,'MarkerSize',10,...
    'MarkerFaceColor','y','MarkerEdgeColor','k');

l = sqrt(((a.Longitude-los)*cos(pi/180*las)*111).^2 + ((a.Latitude-las)*111).^2) ;
l2 = a.Magnitude >= 0.0 & a.Depth >= l;
%l2 = a.Magnitude >=2.0 & a.Depth <= 30 & l < 100;
a = a.subset(l2);
update(mainmap())
pl = plot(los,las,'rs')
set(pl,'LineWidth',1.0,'MarkerSize',10,...
    'MarkerFaceColor','r','MarkerEdgeColor','y');


function spm_preproc_write(p,opts)
% Write out VBM preprocessed data
% FORMAT spm_preproc_write(p,opts)
% p    - results from spm_prep2sn
% opts - writing options.  A struct containing these fields:
%        biascor - write bias corrected image
%        cleanup - level of brain segmentation cleanup
%        GM      - flags for which images should be written
%        WM      - similar to GM
%        CSF     - similar to GM
%__________________________________________________________________________
% Copyright (C) 2005-2016 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_preproc_write.m 6894 2016-09-30 16:48:46Z spm $

if ischar(p), p = cellstr(p); end

if nargin==1
    opts = spm_get_defaults('old.preproc.output');
end

for i=1:numel(p)
    if iscellstr(p), q = load(p{i}); else q = p(i); end
    if i==1, b0 = spm_load_priors(q.VG); end
    preproc_apply(q,opts,b0);
end

%==========================================================================
% function preproc_apply(p,opts,b0)
%==========================================================================
function preproc_apply(p,opts,b0)

nclasses = size(fieldnames(opts),1) - 2 ;
switch nclasses
    case 3
        sopts = [opts.GM ; opts.WM ; opts.CSF];
    case 4
        sopts = [opts.GM ; opts.WM ; opts.CSF ; opts.EXTRA1];
    case 5
        sopts = [opts.GM ; opts.WM ; opts.CSF ; opts.EXTRA1 ; opts.EXTRA2];
    otherwise
        error('Unsupported number of classes.')
end

T    = p.flags.Twarp;
bsol = p.flags.Tbias;
d2   = [size(T) 1];
d    = p.VF.dim(1:3);

[x1,x2,o] = ndgrid(1:d(1),1:d(2),1);
x3  = 1:d(3);
d3  = [size(bsol) 1];
B1  = spm_dctmtx(d(1),d2(1));
B2  = spm_dctmtx(d(2),d2(2));
B3  = spm_dctmtx(d(3),d2(3));
bB3 = spm_dctmtx(d(3),d3(3),x3);
bB2 = spm_dctmtx(d(2),d3(2),x2(1,:)');
bB1 = spm_dctmtx(d(1),d3(1),x1(:,1));

mg  = p.flags.mg;
mn  = p.flags.mn;
vr  = p.flags.vr;
K   = length(p.flags.mg);
Kb  = length(p.flags.ngaus);

for k1=1:size(sopts,1)
    dat{k1}    = zeros(d(1:3),'uint8');
    if sopts(k1,3)
        Vt     = struct('fname',   spm_file(p.VF.fname,'prefix',['c', num2str(k1)]),...
                        'dim',     p.VF.dim,...
                        'dt',      [spm_type('uint8') spm_platform('bigend')],...
                        'pinfo',   [1/255 0 0]',...
                        'mat',     p.VF.mat,...
                        'n',       [1 1],...
                        'descrip', ['Tissue class ' num2str(k1)]);
        Vt     = spm_create_vol(Vt);
        VO(k1) = Vt;
    end
end
if opts.biascor
    VB = struct('fname',   spm_file(p.VF.fname,'prefix','m'),...
                'dim',     p.VF.dim(1:3),...
                'dt',      [spm_type('float32') spm_platform('bigend')],...
                'pinfo',   [1 0 0]',...
                'mat',     p.VF.mat,...
                'n',       [1 1],...
                'descrip', 'Bias Corrected');
    VB = spm_create_vol(VB);
end

lkp = []; for k=1:Kb, lkp = [lkp ones(1,p.flags.ngaus(k))*k]; end

spm_progress_bar('init',length(x3),['Working on ' spm_file(p.VF.fname,'basename')],'Planes completed');
M = p.VG(1).mat\p.flags.Affine*p.VF.mat;

for z=1:length(x3)

    % Bias corrected image
    f          = spm_sample_vol(p.VF,x1,x2,o*x3(z),0);
    cr         = exp(transf(bB1,bB2,bB3(z,:),bsol)).*f;
    if opts.biascor
        % Write a plane of bias corrected data
        VB = spm_write_plane(VB,cr,z);
    end

    if any(sopts(:))
        msk        = (f==0) | ~isfinite(f);
        [t1,t2,t3] = defs(T,z,B1,B2,B3,x1,x2,x3,M);
        q          = zeros([d(1:2) Kb]);
        bt         = zeros([d(1:2) Kb]);
        for k1=1:Kb
            bt(:,:,k1) = spm_sample_priors(b0{k1},t1,t2,t3,k1==Kb);
        end
        b = zeros([d(1:2) K]);
        for k=1:K
            b(:,:,k) = bt(:,:,lkp(k))*mg(k);
        end
        s = sum(b,3);
        for k=1:K
            p1            = exp((cr-mn(k)).^2/(-2*vr(k)))/sqrt(2*pi*vr(k)+eps);
            q(:,:,lkp(k)) = q(:,:,lkp(k)) + p1.*b(:,:,k)./s;
        end
        sq = sum(q,3)+eps;
        sw = warning('off','MATLAB:divideByZero');
        for k1=1:size(sopts,1)
            tmp            = q(:,:,k1);
            tmp(msk)       = 0;
            tmp            = tmp./sq;
            dat{k1}(:,:,z) = uint8(round(255 * tmp));
        end
        warning(sw);
    end
    spm_progress_bar('set',z);
end
spm_progress_bar('clear');

if opts.cleanup > 0
    [dat{1},dat{2},dat{3}] = clean_gwc(dat{1},dat{2},dat{3}, opts.cleanup);
end
if any(sopts(:,3))
    for z=1:length(x3)
        for k1=1:size(sopts,1)
            if sopts(k1,3)
                tmp = double(dat{k1}(:,:,z))/255;
                spm_write_plane(VO(k1),tmp,z);
            end
        end
    end
end

for k1=1:size(sopts,1)
    if any(sopts(k1,1:2))
        so      = struct('wrap',[0 0 0],...
                         'interp',1,...
                         'vox',[NaN NaN NaN],...
                         'bb',ones(2,3)*NaN,...
                         'preserve',0);
        ovx     = abs(det(p.VG(1).mat(1:3,1:3)))^(1/3);
        fwhm    = max(ovx./sqrt(sum(p.VF.mat(1:3,1:3).^2))-1,0.1);
        dat{k1} = decimate(dat{k1},fwhm);
        dim     = [size(dat{k1}) 1];
        VT      = struct('fname', spm_file(p.VF.fname,'prefix',['c', num2str(k1)]),...
                         'dim',   dim(1:3),...
                         'dt',    [spm_type('uint8') spm_platform('bigend')],...
                         'pinfo', [1/255 0]',...
                         'mat',   p.VF.mat,...
                         'dat',   dat{k1});
        if sopts(k1,2)
            spm_write_sn(VT,p,so);
        end
        so.preserve = 1;
        if sopts(k1,1)
           VN       = spm_write_sn(VT,p,so);
           VN.fname = spm_file(p.VF.fname,'prefix',['mwc', num2str(k1)]);
           spm_write_vol(VN,VN.dat);
        end
    end
end

%==========================================================================
% function [x1,y1,z1] = defs(sol,z,B1,B2,B3,x0,y0,z0,M)
%==========================================================================
function [x1,y1,z1] = defs(sol,z,B1,B2,B3,x0,y0,z0,M)
x1a = x0    + transf(B1,B2,B3(z,:),sol(:,:,:,1));
y1a = y0    + transf(B1,B2,B3(z,:),sol(:,:,:,2));
z1a = z0(z) + transf(B1,B2,B3(z,:),sol(:,:,:,3));
x1  = M(1,1)*x1a + M(1,2)*y1a + M(1,3)*z1a + M(1,4);
y1  = M(2,1)*x1a + M(2,2)*y1a + M(2,3)*z1a + M(2,4);
z1  = M(3,1)*x1a + M(3,2)*y1a + M(3,3)*z1a + M(3,4);

%==========================================================================
% function t = transf(B1,B2,B3,T)
%==========================================================================
function t = transf(B1,B2,B3,T)
if ~isempty(T)
    d2 = [size(T) 1];
    t1 = reshape(reshape(T, d2(1)*d2(2),d2(3))*B3', d2(1), d2(2));
    t  = B1*t1*B2';
else
    t  = zeros(size(B1,1),size(B2,1),size(B3,1));
end

%==========================================================================
% function dat = decimate(dat,fwhm)
%==========================================================================
function dat = decimate(dat,fwhm)
% Convolve the volume in memory (fwhm in voxels).
lim = ceil(2*fwhm);
x  = -lim(1):lim(1); x = spm_smoothkern(fwhm(1),x); x  = x/sum(x);
y  = -lim(2):lim(2); y = spm_smoothkern(fwhm(2),y); y  = y/sum(y);
z  = -lim(3):lim(3); z = spm_smoothkern(fwhm(3),z); z  = z/sum(z);
i  = (length(x) - 1)/2;
j  = (length(y) - 1)/2;
k  = (length(z) - 1)/2;
spm_conv_vol(dat,dat,x,y,z,-[i j k]);

%==========================================================================
% function [g,w,c] = clean_gwc(g,w,c,level)
%==========================================================================
function [g,w,c] = clean_gwc(g,w,c,level)
if nargin<4, level = 1; end

b    = w;
b(1) = w(1);

% Build a 3x3x3 seperable smoothing kernel
%--------------------------------------------------------------------------
kx=[0.75 1 0.75];
ky=[0.75 1 0.75];
kz=[0.75 1 0.75];
sm=sum(kron(kron(kz,ky),kx))^(1/3);
kx=kx/sm; ky=ky/sm; kz=kz/sm;

th1 = 0.15;
if level==2, th1 = 0.2; end
% Erosions and conditional dilations
%--------------------------------------------------------------------------
niter = 32;
spm_progress_bar('Init',niter,'Extracting Brain','Iterations completed');
for j=1:niter
    if j>2, th=th1; else th=0.6; end  % Dilate after two its of erosion
    for i=1:size(b,3)
        gp       = double(g(:,:,i));
        wp       = double(w(:,:,i));
        bp       = double(b(:,:,i))/255;
        bp       = (bp>th).*(wp+gp);
        b(:,:,i) = uint8(round(bp));
    end
    spm_conv_vol(b,b,kx,ky,kz,-[1 1 1]);
    spm_progress_bar('Set',j);
end
th = 0.05;
for i=1:size(b,3)
    gp       = double(g(:,:,i))/255;
    wp       = double(w(:,:,i))/255;
    cp       = double(c(:,:,i))/255;
    bp       = double(b(:,:,i))/255;
    bp       = ((bp>th).*(wp+gp))>th;
    g(:,:,i) = uint8(round(255*gp.*bp./(gp+wp+cp+eps)));
    w(:,:,i) = uint8(round(255*wp.*bp./(gp+wp+cp+eps)));
    c(:,:,i) = uint8(round(255*(cp.*bp./(gp+wp+cp+eps)+cp.*(1-bp))));
end
spm_progress_bar('Clear');


function [pulseCleanedTemplate, pulseTemplate] = tapas_physio_get_template_from_pulses(...
    c, cpulse, halfTemplateWidthInSamples, verbose, varargin)
% Computes mean pulse template given time stamp of detected pulses and raw
% time series; removes outlier pulses with correlation to initial guess of
% mean template
%
%   [pulseCleanedTemplate, pulseTemplate] = tapas_physio_get_template_from_pulses(...
%                c, cpulse2ndGuess, halfTemplateWidthInSamples, ...
%                doNormalizeTemplate, dt)
% IN
%   c                   cardiac time series (raw physiological recording)
%   cpulse              index vector (wrt c) of detected pulse events (1= event onset/max)
%   halfTemplateWidthInSamples
%                       half the width in samples of template to be
%                       generated, i.e. numel(pulseTemplate) = 2*this+1
%   verbose             verbose substructure of physio, holds all figure
%                       handles created and verbose.level to trigger visualization
%
%   optional as propertyName/Value pairs:
%
%   thresholdHighQualityCorrelation
%                           default: 0.95
%                           outliers pulses below that correlation will be
%                           removed for averaging when retrieving final template
%   minFractionIncludedPulses
%                           default: 0.1
%                           defines minimum fraction of total number of
%                           found pulses to be included in final template
%                           (after removing outliers). If there are not
%                           enough clean pulses, this value is enforced by
%                           lowering quality thresholds.
%   doNormalizeTemplate     default: true; if true, subtracts mean and
%                           scales max to 1 for each pulse, before
%                           averaging
%   dt                      default: 1; defines time vector only used for
%                           output plot
%
%
% OUT
%   pulseCleanedTemplate    pulseTemplate, mean after removing outliers for
%                           correlation quality
%   pulseTemplate           average of all detected pulse shapes
% EXAMPLE
%   tapas_physio_get_template_from_pulses
%
%   See also tapas_physio_get_cardiac_pulse_template tapas_physio_get_cardiac_pulses_auto_matched

% Author:   Lars Kasper
% Created:  2019-01-29
% Copyright (C) 2019 TNU, Institute for Biomedical Engineering,
%                    University of Zurich and ETH Zurich.
%
% This file is part of the TAPAS PhysIO Toolbox, which is released under
% the terms of the GNU General Public License (GPL), version 3. You can
% redistribute it and/or modify it under the terms of the GPL (either
% version 3 or, at your option, any later version). For further details,
% see the file COPYING or <http://www.gnu.org/licenses/>.

% z-transform to have all templates (for averaging) have
% same norm & be mean-corrected
defaults.doNormalizeTemplate = true;
defaults.minFractionIncludedPulses = 0.1;
defaults.thresholdHighQualityCorrelation = 0.95;
defaults.dt = 1; % for visualization only

args = tapas_physio_propval(varargin, defaults);
tapas_physio_strip_fields(args);

doDebug = verbose.level >= 3;

nSamplesTemplate = halfTemplateWidthInSamples * 2 + 1;
nPulses = numel(cpulse);
template = zeros(nPulses-3,nSamplesTemplate);

for n=2:nPulses-2
    startTemplate = cpulse(n)-halfTemplateWidthInSamples;
    endTemplate = cpulse(n)+halfTemplateWidthInSamples;

    template(n,:) = c(startTemplate:endTemplate);

    if doNormalizeTemplate
        template(n,:) = template(n,:) - mean(template(n,:),2);

        % std-normalized...
        %template(n,:) = template(n,:)./std(template(n,:),0,2);
        % max-norm:
        template(n,:) = template(n,:)./max(abs(template(n,:)));
    end

end

%delete first zero-elements of the template
template(1,:) = [];

% template as average of the found representative waves
pulseTemplate = mean(template);

if doDebug
    fh = verbose.fig_handles(end);
    figure(fh);
    subplot(3,1,3);
    tTemplate = dt*(0:2*halfTemplateWidthInSamples);
    plot(tTemplate, template');
    hold all;
    hp(1) = plot(tTemplate, pulseTemplate', '.--g', 'LineWidth', 3, 'Marker', ...
        'o');
    xlabel('t (seconds)');
    title('Templates of cycle time course and mean template');
end

%% Final template for peak search from best-matching templates
% delete the peaks deviating from the mean too
% much before building the final template
[~, pulseTemplate] = tapas_physio_corrcoef12(pulseTemplate, pulseTemplate);
isZtransformed = [0 1];

nTemplates = size(template,1);
similarityToTemplate = zeros(nTemplates,1);
for n=1:nTemplates
    similarityToTemplate(n) = tapas_physio_corrcoef12(template(n,:),pulseTemplate, ...
        isZtransformed);
end

% minimal number of high quality templates to be achieved, otherwise
% enforced
nMinHighQualityTemplates = ceil(minFractionIncludedPulses * nPulses);
indHighQualityTemplates = find(similarityToTemplate > ...
    thresholdHighQualityCorrelation);

% if threshold to restrictive, try with new one:
% best nMinHighQualityTemplates / nPulses of all found templates used for
% averaging
if numel(indHighQualityTemplates) < nMinHighQualityTemplates
    thresholdHighQualityCorrelation = tapas_physio_prctile(similarityToTemplate, ...
        1 - nMinHighQualityTemplates/nPulses);
    indHighQualityTemplates = find(similarityToTemplate > ...
        thresholdHighQualityCorrelation);
end
pulseCleanedTemplate = mean(template(indHighQualityTemplates, :));

if doDebug
    stringTitle = 'Preproc: Iterative Template Creation Single Cycle';
    hp(2) = plot(tTemplate, pulseCleanedTemplate, '.-g', 'LineWidth', 4, ...
        'Marker', 'x');
    legend(hp, 'mean of templates', 'mean of most similar, chosen templates');
    tapas_physio_suptitle(stringTitle);
end


function EEG = hlp_blockAverageConnectivity(EEG,numblocks)
    % INPUTS:
    %
    %   EEG         - EEG structure containing EEG.CAT.Conn
    %
    % Optional:
    %
    %   numblocks   - number of blocks to average over
    %
    % OUTPUTS:
    %
    %   EEG     - contained modifed Conn structure

    % average connectivity across trials or blocks
    % trials/blocks are assumed to be concatenated columnwise in last
    % dimension of EEG.CAT.Conn.<connmethod>
    % e.g. EEG.CAT.Conn.<connmethod> is assumed to be [nchs x nchs x nfreqs x numblocks*blocklength]
    % numblocks must exactly devide the number of time points in Conn matrices

    % References:
    %
    % [1] Mullen T (2010) The Source Information Flow Toolbox (SIFT):
    %     Theoretical Handbook and User Manual. Chapter 4
    %     Available at: http://www.sccn.ucsd.edu/wiki/Sift
    %
    % Author: Tim Mullen 2011, SCCN/INC, UCSD.
    % Email:  tim@sccn.ucsd.edu

    % This function is part of the Source Information Flow Toolbox (SIFT)
    %
    % This program 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.
    %
    % This program 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 this program; if not, write to the Free Software
    % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    connmethod = hlp_getConnMethodNames(EEG.CAT.Conn);

    if nargin < 2
        % default number of blocks is number of trials
        numblocks = size(EEG.CAT.srcdata,3);
    end

    [nchs nchs nfreq npoints] = size(EEG.CAT.Conn.(connmethod{1}));

    for m =1:length(connmethod)
        C = EEG.CAT.Conn.(connmethod{m});
        C = reshape(C,[nchs nchs nfreq npoints/numblocks numblocks]);
        EEG.CAT.Conn.(connmethod{m}) = mean(C,5);

    end

    EEG.CAT.Conn.erWinCenterTimes = EEG.CAT.Conn.erWinCenterTimes(1:npoints/numblocks);


function [g1, g2, g3] = sdlfmaXsdlfmKernGradientBlockILJ(lfmKern1, lfmKern2, ...
    t1, t2, i, j, generalConst, generalConstGrad, covGrad, g1Mean, ...
    g2Mean, gsp1Mean, gsp2Mean, typeMeanParam, typeMeanSwitching, ...
    typeKernParam1, typeKernParam2, typeKernSwitching1, typeKernSwitching2)

% SDLFMAXSDLFMKERNGRADIENTBLOCKILJ
% FORMAT
% DESC computes the gradients of the parameters for system 1 and system 2
% when i is lower than j. System 1 represents an acceleration while system
% 2 represents a position.
% ARG lfmKern1 : structure containing parameters for the system 1
% ARG lfmKern2 : structure containing parameters for the system 2
% ARG t1 : times at which the system 1 is evaluated
% ARG t2 : times at which the system 2 is evaluated
% ARG covGrad : partial derivatives of the objective function wrt portion
% of the corresponding kernel matrix
% ARG g1Mean : gradients of the parameter of the system 1 obtained from the
% part of the function that uses the funcitons accommpanying the initial
% conditions.
% ARG g2Mean : gradients of the parameter of the system 2 obtained from the
% part of the function that uses the funcitons accommpanying the initial
% conditions.
% ARG gsp1Mean : gradient of the switching point of the system 1 obtained
% from the part of the function that uses the funcitons accommpanying the
% initial conditions.
% ARG gsp2Mean : gradient of the switching point of the system 2 obtained
% from the part of the function that uses the funcitons accommpanying the
% initial conditions.
% ARG typeMeanParam : specify the mean functions used to compute this part
% of the kernel
% ARG typeMeanSwitching : specify the functions used to compute the
% gradients of the swicthing points in part thst uses mean functions
% ARG typeKernParam1 : specify the first kernel function used to compute
% this part of the kernel
% ARG typeKernParam2 : specify the second kernel function used to compute
% this part of the kernel
% ARG typeKernSwitching1 : specify the functions used to compute the
% gradients of the swicthing points in both sides of the kernel function 1
% ARG typeKernSwitching2 : specify the functions used to compute the
% gradients of the swicthing points in both sides of the kernel function 2
% RETURN g1 : gradients of parameters for the system 1
% RETURN g2 : gradients of parameters for the system 2
% RETURN g3 : gradients of switching points
%
% COPYRIGHT : Mauricio A. Alvarez, 2010.

% KERN

if nargin < 14
    typeMeanParam = 'sdlfm';
    typeMeanSwitching = 'sdlfmv';
    typeKernParam1 = 'lfmXlfm';
    typeKernParam2 = 'lfmvXlfm';
    typeKernSwitching1= {'lfmvXlfm', 'lfmvXlfm'};
    typeKernSwitching2 ={'lfmvXlfmv', 'lfmaXlfm'};
end

g3 = [];

fhandleMeanParam = str2func([typeMeanParam 'MeanCompute']);
fhandleMeanGradParam = str2func([typeMeanParam 'MeanGradient']);
fhandleMeanGradSwitching = str2func([typeMeanSwitching 'MeanCompute']);
fhandleKernPosPos = str2func([typeKernParam1 'KernCompute']);
fhandleKernGradPosPos = str2func([typeKernParam1 'KernGradient']);
fhandleKernGradSwitchingPosPos1 = str2func([typeKernSwitching1{1} 'KernCompute']);
fhandleKernGradSwitchingPosPos2 = str2func([typeKernSwitching1{2} 'KernCompute']);
fhandleKernVelPos = str2func([typeKernParam2 'KernCompute']);
fhandleKernGradVelPos = str2func([typeKernParam2 'KernGradient']);
fhandleKernGradSwitchingVelPos1 = str2func([typeKernSwitching2{1} 'KernCompute']);
fhandleKernGradSwitchingVelPos2 = str2func([typeKernSwitching2{2} 'KernCompute']);

c2 = fhandleMeanParam(lfmKern2(1), t2, 'Pos');
e2 = fhandleMeanParam(lfmKern2(1), t2, 'Vel');

if isempty(generalConst{i,j})
    coeffPosPos = c2;
    coeffPosVel = e2;
else
    coeffPosPos = generalConst{i,j}(1,1)*c2 + generalConst{i,j}(2,1)*e2;
    coeffPosVel = generalConst{i,j}(1,2)*c2 + generalConst{i,j}(2,2)*e2;
end
g1Kern = zeros(length(lfmKern1), 5);
g2Kern = zeros(length(lfmKern1), 5);
PosPos = zeros(length(t1),1);
PosVel = zeros(length(t1),1);
for k=1:length(lfmKern1)
    PosPos = PosPos + fhandleKernPosPos(lfmKern1(k), lfmKern2(k), t1,...
        lfmKern1(k).limit);
    [g1KLocal, g2KLocal] = fhandleKernGradPosPos(lfmKern1(k), lfmKern2(k), ...
        t1, lfmKern1(k).limit, covGrad, coeffPosPos.');
    g1Kern(k,:) = g1Kern(k, :) + g1KLocal;
    g2Kern(k,:) = g2Kern(k, :) + g2KLocal;
    PosVel = PosVel + fhandleKernVelPos(lfmKern1(k), lfmKern2(k), ...
        t1, lfmKern1(k).limit);
    [g1KLocal, g2KLocal] = fhandleKernGradVelPos(lfmKern1(k), lfmKern2(k), ...
        t1, lfmKern1(k).limit, covGrad, coeffPosVel.');
    g1Kern(k,:) = g1Kern(k, :) + g1KLocal;
    g2Kern(k,:) = g2Kern(k, :) + g2KLocal;
end
[gcAlpha, gcOmega] = fhandleMeanGradParam(lfmKern2(1), t2, 'Pos');
[geAlpha, geOmega] = fhandleMeanGradParam(lfmKern2(1), t2, 'Vel');
[gradAlpha, gradOmega] = getLocalGradAlphaOmega(lfmKern2);
g2Pos = fhandleMeanGradSwitching(lfmKern2(1), t2, 'Pos');
h2Vel = fhandleMeanGradSwitching(lfmKern2(1), t2, 'Vel');
gsp1Kern = zeros(1, length(lfmKern1));
gsp2Kern = zeros(1, length(lfmKern1));
% This means that are only two switching points involved, t1
% and t0 appear in k, like k_{ff}(t1-t0,t'-t0) and
% k_{mf}(t1-t0,t'-t0). The other points appear in c1(t - t1)
% and e1(t - t1)
for k=1:length(lfmKern1)
    temp = fhandleKernGradSwitchingPosPos1(lfmKern1(k), lfmKern2(k), t1, lfmKern1(k).limit);
    gsp1Kern(k) = gsp1Kern(k) - sum(sum((temp*coeffPosPos.').*covGrad));
    %temp = fhandleKernGradSwitchingPosPos2(lfmKern2(k), lfmKern1(k), lfmKern1(k).limit, t1)';
    temp = fhandleKernGradSwitchingPosPos2(lfmKern1(k), lfmKern2(k), t1, lfmKern1(k).limit);
    gsp1Kern(k) = gsp1Kern(k) - sum(sum((temp*coeffPosPos.').*covGrad));
    gsp2Kern(k) = gsp2Kern(k) + sum(sum((temp*coeffPosPos.').*covGrad));
    temp = fhandleKernGradSwitchingVelPos1(lfmKern1(k), lfmKern2(k), t1, lfmKern1(k).limit);
    gsp1Kern(k) = gsp1Kern(k) - sum(sum((temp*coeffPosVel.').*covGrad));
    temp = fhandleKernGradSwitchingVelPos2(lfmKern2(k), lfmKern1(k), lfmKern1(k).limit, t1).';
    gsp1Kern(k) = gsp1Kern(k) - sum(sum((temp*coeffPosVel.').*covGrad));
    gsp2Kern(k) = gsp2Kern(k) + sum(sum((temp*coeffPosVel.').*covGrad));
end
if isempty(generalConst{i,j})
    matGradAlpha = PosPos*gcAlpha.' + PosVel*geAlpha.';
    matGradOmega = PosPos*gcOmega.' + PosVel*geOmega.';
    gCoeff = gradAlpha*sum(sum(matGradAlpha.*covGrad)) + ...
        gradOmega*(sum(sum(matGradOmega.*covGrad)));
    matGradSp2 = PosPos*g2Pos.' + PosVel*h2Vel.';
    gsp2 = - sum(sum(matGradSp2.*covGrad));
    g3(i) = gsp1Mean + sum(gsp1Kern);                % switching points 1
    g3(j) = gsp2Mean + sum(gsp2Kern) + gsp2;         % switching points 2
else
    constGradAlpha = generalConstGrad{1}{i,j};
    constGradOmega = generalConstGrad{2}{i,j};
    constVal = generalConst{i,j};
    % Derivative wrt parameters
    matGradAlpha = PosPos*((constVal(1,1)*gcAlpha.' + constGradAlpha(1,1)*c2.') ...
        + constVal(2,1)*geAlpha.' + constGradAlpha(2,1)*e2.') ...
        + PosVel*((constVal(1,2)*gcAlpha.' + constGradAlpha(1,2)*c2.') ...
        + constVal(2,2)*geAlpha.' + constGradAlpha(2,2)*e2.');

    matGradOmega = PosPos*((constVal(1,1)*gcOmega.' + constGradOmega(1,1)*c2.') ...
        + constVal(2,1)*geOmega.' + constGradOmega(2,1)*e2.') ...
        + PosVel*((constVal(1,2)*gcOmega.' + constGradOmega(1,2)*c2.') ...
        + constVal(2,2)*geOmega.' + constGradOmega(2,2)*e2.');

    gCoeff = gradAlpha*sum(sum(matGradAlpha.*covGrad)) + ...
        gradOmega*(sum(sum(matGradOmega.*covGrad)));
    % Derivative wrt switching points
    % Firts, notice that gsp2Kern doesn't correspond to the switching point
    % of the interval j (or say 2). It's just the derivative of the inner
    % switching point that lead to the actual switching point for the
    % interval j. So we rename it first.
    gspInt = sum(gsp2Kern);
    % Compute the derivative of the swicthing point j, not appearing in the
    % constant
    matGradSp2 = PosPos*(constVal(1,1)*g2Pos.' + constVal(2,1)*h2Vel.') + ...
        PosVel*(constVal(1,2)*g2Pos.' + constVal(2,2)*h2Vel.');
    gsp2 = - sum(sum(matGradSp2.*covGrad));
    % Compute the derivatives for all the switching points apearing in the
    % constant
    constGradSPoint = generalConstGrad{3}{i,j};
    numberSP = size(constGradSPoint,2);
    gspInBetween = zeros(1, numberSP);
    for k=1:numberSP
        temp = PosPos*(constGradSPoint(1,k)*c2.' + constGradSPoint(3,k)*e2.') + ...
            PosVel*(constGradSPoint(2,k)*c2.' + constGradSPoint(4,k)*e2.');
        gspInBetween(k) = sum(sum(temp.*covGrad));
    end
    % Assign derivatives wrt all other switching points, with a correction
    % for the derivative of the innermost switching point in the constant
    gspInBetween(end) =  gspInBetween(end) + gspInt;
    g3(i) = gsp1Mean + sum(gsp1Kern);           % switching point 1
    g3(j) = gsp2Mean + gsp2 + gspInBetween(1);  % switching point 2
    g3(i+1:j-1) = fliplr(gspInBetween(2:end));
end
% Assign derivatives wrt first system
g1{1} = g1Mean + sum(g1Kern(:,1:3), 1);          % mass 1, spring 1, damper 1
g1{2} = g1Kern(:,4).';                            % inverse widths
g1{3} = g1Kern(:,5).';                            % sensitivities 1
% Assign derivatives wrt second system
g2{1} = g2Mean + sum(g2Kern(:,1:3), 1) + gCoeff; % mass 2, spring 2, damper 2
g2{2} = g2Kern(:,4).';                            % inverse widths
g2{3} = g2Kern(:,5).';                            % sensitivities 2


function v = cnn_vec(im, net)
% CNN_VEC computes a D-dimensional CNN vector for an image.
%
%   V = cnn_vec(IM, NET)
%
%   IM  : Input image, or input image path as a string
%   NET : CNN network to evaluate on image IM
%
%   V   : D-dimensional vector
%
% Authors: F. Radenovic, G. Tolias, O. Chum. 2017.

	minsize = 67;
	net.mode = 'test';
	descvarname = 'l2descriptor';

	use_gpu = strcmp(net.device, 'gpu');
	if use_gpu
		gpuarrayfun = @(x) gpuArray(x);
		gatherfun = @(x) gather(x);
	else
		gpuarrayfun = @(x) x; % do not convert to gpuArray
		gatherfun = @(x) x; % do not gather
	end

	if isstr(im)
		im = imread(im);
	end

	im = single(im) - mean(net.meta.normalization.averageImage(:));
	if size(im, 3) == 1
		im = repmat(im, [1 1 3]);
	end
	if min(size(im, 1), size(im, 2)) < minsize
		im = pad2minsize(im, minsize, 0);
	end

	net.eval({'input', gpuarrayfun(reshape(im, [size(im), 1]))});

	v = gatherfun(squeeze(net.getVar(descvarname).value));


%% Vectorization using Sparse Matrices
%
%% Vectorization

%% Sparse matrix

%% Example: assembling of discrete Laplacian operator

%% Example: node star

%% Example: eliminating hanging nodes


function [ save_totalNum,  visCells ] = deleteZeroPoints( weightFile, visFilesDir, compressResultsDir, saveReIndexFile, saveNewQFile )
%DELETEZEROPOINTS Summary of this function goes here
%   Detailed explanation goes here

    % get the union result
    disp('Prepare the next optimization');

    fileExt = '*.txt';
    compress_files = dir(fullfile(compressResultsDir,fileExt));
    all_ID = [];
    for i = 0:length(compress_files)-1

        fileCnt = num2str(i);
        fileName = [compressResultsDir, fileCnt, '.txt'];

        file_t = fopen(fileName);
        point_ID = fscanf(file_t, '%d');
        fclose(file_t);

        all_ID = union(all_ID, point_ID);

    end
    save_totalNum = length(all_ID);

    %%
    % get the one2one indexes relations and save
    % the map point index, in C++ from 0, in Matlab from 1
    % indexList id from ZERO
    indexList = [];
    indexList(:,1) = all_ID-1;
    for i= 1:length(all_ID)
        indexList(i,2) = i-1;  % map point re-index from zero
    end
    dlmwrite(saveReIndexFile, indexList, 'precision', '%d');

    % update the visMatrix and save

    fileExt = '*.txt';
    vis_files = dir(fullfile(visFilesDir,fileExt));
    for i=0:length(vis_files)-1
%         tic
%         disp(i);

        fileCnt = num2str(i);
        old_fileName = [visFilesDir, fileCnt, '.txt'];
        file_old = fopen(old_fileName);
        vis_point_ID_old = fscanf(file_old, '%d');

        % thought 3
        isInIndex = ismember(indexList(:,1), vis_point_ID_old);
        isSaved = find(isInIndex==1);
        newnew = indexList(:,2);
        vis_point_ID_new = newnew(isSaved);

        visCells{i+1} = vis_point_ID_new;

%         toc
    end

    % update the q-matrix-vector
    % weight is from ONE
    file_q = fopen(weightFile);
    weights = fscanf(file_q, '%d');
    new_weights = [];
    for i = 1:length(indexList)
        new_weights(i,:) = weights(indexList(i,1)+1);
    end
    dlmwrite(saveNewQFile, new_weights, 'precision', '%d');

    disp('Finished');

end

%         % visMatrix is from
%         vis_point_ID_new = [];
%         remain_cnt = 1;
        % thought 1
%         for j =1:length(vis_point_ID_old)
%             row_indexList = find(indexList(:,1) == (vis_point_ID_old(j)));
%             if size(row_indexList,1) == 1
%                 vis_point_ID_new(remain_cnt,:) = indexList(row_indexList,2);  % already from zero before this part
%                 remain_cnt = remain_cnt + 1;
%             else  % zero matrix
%             end
%         end
%         % thought 2
%         vis_point_ID_old_inter = intersect(vis_point_ID_old, indexList(:,1));
%         for j = 1:length(vis_point_ID_old_inter)
% %             rowLine = find(indexList(:,1) == vis_point_ID_old_inter(j));
%             vis_point_ID_old_inter(j,:) = indexList(find(indexList(:,1) == vis_point_ID_old_inter(j)), 2);
%         end
%


global planC
[SUVmax,SUVmean,BKG,BSL,Thresh,equiVol] = calcBSL(1,planC,1,1);
[SUVmax,SUVmean,BKG,BSL,Thresh,equiVol] = calcBSL(2,planC,1,1);
[SUVmax,SUVmean,BKG,BSL,Thresh,equiVol] = calcBSL(3,planC,1,1);


function evaluate_ref_models()
% Evaluate MatConvNet reference models to validate them

addpath(fullfile(fileparts(mfilename('fullpath')), '..','examples', 'imagenet')) ;

models = {...
  'resnet-50-dag', 2015, ...
  'resnet-101-dag', 2015, ...
  'resnet-152-dag', 2015, ...
  'matconvnet-alex', 2012, ...
  'matconvnet-vgg-s', 2013, ...
  'matconvnet-vgg-m', 2013, ...
  'matconvnet-vgg-f', 2013, ...
  'matconvnet-vgg-verydeep-16', 2014, ...
  'caffe-ref', 2012, ...
  'caffe-alex', 2012, ...
  'vgg-s', 2013, ...
  'vgg-m', 2013, ...
  'vgg-f', 2013, ...
  'vgg-m-128', 2013, ...
  'vgg-m-1024', 2013, ...
  'vgg-m-2048', 2013, ...
  'vgg-verydeep-19', 2014, ...
  'vgg-verydeep-16', 2014, ...
  'googlenet-dag', 2014} ;

for i = 1:2:numel(models)
  opts.dataDir = fullfile('data', 'imagenet12-s256') ;
  opts.expDir = fullfile('data','models-eval', models{i}) ;
  opts.imdbPath = fullfile(opts.expDir, 'imdb.mat');
  opts.modelPath = fullfile('data', 'models', ...
    sprintf('imagenet-%s.mat', models{i})) ;
  opts.lite = false ;
  opts.numFetchThreads = 12 ;
  opts.train.batchSize = 128 ;
  opts.train.numEpochs = 1 ;
  opts.train.gpus = [] ;
  opts.train.prefetch = true ;
  opts.train.expDir = opts.expDir ;

  resultPath = fullfile(opts.expDir, 'results.mat') ;
  if ~exist(resultPath)
    results = cnn_imagenet_evaluate(opts) ;
    save(fullfile(opts.expDir, 'results.mat'), 'results') ;
  end
end

fprintf('|%30s|%10s|%10s|%10s|%10s|\n', 'model', 'introduced', ...
        'top-1 err.', 'top-5 err.', 'images/s') ;
fprintf(strrep(sprintf('|%30s|%10s|%10s|%10s|%10s|\n', '', '', '', '', ''),' ','-')) ;

years = horzcat(models{2:2:end}) ;
[~,perm] = sort(years, 'descend') ;

for i = perm
  i = 2*(i - 1) + 1 ;
  opts.expDir = fullfile('data', 'models-eval', models{i}) ;
  resultPath = fullfile(opts.expDir, 'results.mat') ;
  load(resultPath, 'results') ;

  if isfield(results.val, 'error')
    top5 = results.val.error(2,end) ;
    top1 = results.val.error(1,end) ;
    speed = results.val.speed(end) ;
  else
    top5 = results.val.top5err(1,end) ;
    top1 = results.val.top1err(1,end) ;
    speed = results.val.num / results.val.time ;
  end

  fprintf('|%30s|%10d|%10s|%10s|%10s|\n', ...
    models{i}, ...
    models{i+1}, ...
    sprintf('%5.1f',top1*100), ...
    sprintf('%5.1f',top5*100), ...
    sprintf('%5.1f',speed)) ;
end

% (cd data/models ; md5sum *.mat | xargs  printf '| %-33s| %-40s|\n')