function bms = spm_cfg_bms_map
% Configuration file for BMS interface
%__________________________________________________________________________
% Copyright (C) 2008-2016 Wellcome Trust Centre for Neuroimaging

% Maria Joao Rosa
% $Id: spm_cfg_bms_map.m 6952 2016-11-25 16:03:13Z guillaume $

%--------------------------------------------------------------------------
% dir Directory
%--------------------------------------------------------------------------
dir         = cfg_files;
dir.tag     = 'dir';
dir.name    = 'Directory';
dir.help    = {['Select the directory where the files containing the '...
               'results from BMS (BMS.mat) will be written.']};
dir.filter  = 'dir';
dir.ufilter = '.*';
dir.num     = [1 1];

%--------------------------------------------------------------------------
% mod_map Log evidence maps
%--------------------------------------------------------------------------
mod_map         = cfg_files;
mod_map.tag     = 'mod_map';
mod_map.name    = 'Models';
mod_map.help    = {['Specify the log. evidence map for each model. '...
                    'Log-evidence maps should be specified '...
                    'in the same order for each subject and session.']};
mod_map.filter  = 'image';
mod_map.ufilter = '.*';
mod_map.num     = [1 Inf];

%--------------------------------------------------------------------------
% sess_map Sessions (Maps)
%--------------------------------------------------------------------------
sess_map      = cfg_branch;
sess_map.tag  = 'sess_map';
sess_map.name = 'Session';
sess_map.val  = {mod_map };

%--------------------------------------------------------------------------
% subj_dcm Subject (Maps)
%--------------------------------------------------------------------------
subj_map         = cfg_repeat;
subj_map.tag     = 'subj_map';
subj_map.name    = 'Subject';
subj_map.values  = {sess_map };

%--------------------------------------------------------------------------
% map Data
%--------------------------------------------------------------------------
map         = cfg_repeat;
map.tag     = 'map';
map.name    = 'Data';
map.help    = {['Select the log. evidence maps for each '...
               'model, session and subject.']}';
map.values  = {subj_map };
map.num     = [1 Inf];

%--------------------------------------------------------------------------
% mod_name Name
%--------------------------------------------------------------------------
mod_name         = cfg_entry;
mod_name.tag     = 'mod_name';
mod_name.name    = 'Name';
mod_name.help    = {'Specify name for each model (optional).'};
mod_name.strtype = 's';
mod_name.num     = [0 Inf];
mod_name.val     = {''};

%--------------------------------------------------------------------------
% name_mod Name models
%--------------------------------------------------------------------------
name_mod         = cfg_repeat;
name_mod.tag     = 'name_mod';
name_mod.name    = 'Name models';
name_mod.help    = {'Specify name for each model (optional).'}';
name_mod.values  = {mod_name };
name_mod.num     = [0 Inf];

%--------------------------------------------------------------------------
% method_maps Inference Method (maps)
%--------------------------------------------------------------------------
method_maps         = cfg_menu;
method_maps.tag     = 'method_maps';
method_maps.name    = 'Inference method';
method_maps.help    = {['Specify inference method: random effects '...
                   '(2nd-level, RFX) or fixed effects (1st-level, FFX) analysis. '...
                   'RFX uses a Variational Bayes approach.']};
method_maps.labels  = {
                  'Fixed effects (FFX)'
                  'Random effects (RFX)'
}';
method_maps.values  = {
                  'FFX'
                  'RFX'
}';

% %--------------------------------------------------------------------------
% % priors Priors
% %--------------------------------------------------------------------------
% priors         = cfg_menu;
% priors.tag     = 'priors';
% priors.name    = 'Priors';
% priors.help    = {['Specify priors for family-level inference (RFX only).
% '...
%                    'Options: ''Family'' sets alpha0=1 for each family '...
%                    'while ''Model'' sets alpha0=1 for each model (not '...
%                    'advised).']};
% priors.labels  = {
%                   'Model'
%                   'Family'
% }';
% priors.values  = {
%                   'M-unity'
%                   'F-unity'
% }';
% priors.val      = {'F-unity'};

%--------------------------------------------------------------------------
% out_file Output files
%--------------------------------------------------------------------------
out_file         = cfg_menu;
out_file.tag     = 'out_file';
out_file.name    = 'Output files (RFX)';
out_file.help    = {['Specify which output files to save (only valid for'...
                     'RFX analyses). ']...
                     ''...
                    ['Default option (and faster option): '...
                     'PPM = xppm.<ext> (Expected Posterior Probability Maps) '...
                     'for each model ie. posterior mean.']...
                     ''...
                    ['Second option: PPM + EPM = xppm.<ext> + '...
                     'epm.<ext> (Expected Posterior Probability '...
                     'Maps + Exceedance Probability Maps) for each model.']...
                     ''...
                    ['Third option: PPM + EPM + Alpha = xppm.<ext> + '...
                     'epm.<ext> + alpha.<ext> (PPM, EPM and Map of Dirichlet '...
                     'Parameters) for each model.']};
out_file.labels  = {
                   'PPM'
                   'PPM + EPM'
                   'PPM + EPM + Alpha'

}';
out_file.values  = {
                  0
                  1
                  2
}';
out_file.val     = {0};

%--------------------------------------------------------------------------
% mask Mask Image
%--------------------------------------------------------------------------
mask         = cfg_files;
mask.tag     = 'mask';
mask.name    = 'Mask Image';
mask.help    = {['Specify an image for explicitly masking the analysis. '...
                '(optional). '...
                'A sensible option here is to use a segmention of '...
                'structural images to specify a within-brain mask. '...
                'If you select that image as an explicit mask then only '...
                'those voxels in the brain will be analysed. This both '...
                'speeds the inference process and restricts BMS to '...
                'within-brain voxels. Alternatively, if such structural '...
                'images are unavailble or no masking is required, then '...
                'leave this field empty.']};
mask.filter  = 'image';
mask.ufilter = '.*';
mask.val     = {{''}};
mask.num     = [0 1];

%--------------------------------------------------------------------------
% nsamp Number of samples
%--------------------------------------------------------------------------
nsamp         = cfg_entry;
nsamp.tag     = 'nsamp';
nsamp.name    = 'Number of samples';
nsamp.help    = {['Number of samples used to compute exceedance '...
                  'probabilities (default: 1e6). '...
                  'To make computations faster reduce the number of '...
                  'samples when number of models is bigger than 3.']};
nsamp.strtype = 's';
nsamp.num     = [1 Inf];
nsamp.val     = {'1e6'};

%--------------------------------------------------------------------------
% file BMS.mat
%--------------------------------------------------------------------------
file         = cfg_files;
file.tag     = 'file';
file.name    = 'BMS.mat';
file.help    = {['Specify the BMS (.mat) file obtained from previous BMS '...
               'analysis (optional). Leave field empty to work on '...
               'serial mode.']};
file.filter  = 'mat';
file.ufilter = '.*';
file.val     = {{''}};
file.num     = [0 1];

%--------------------------------------------------------------------------
% img Map to display
%--------------------------------------------------------------------------
img         = cfg_files;
img.tag     = 'img';
img.name    = 'Map to display';
img.help    = {['Specify map obtained from BMS Maps '...
               '(optional). Leave field empty to work on serial mode.']};
img.filter  = 'image';
img.ufilter = '.*';
img.val     = {{''}};
img.num     = [0 1];

%--------------------------------------------------------------------------
% thres Probability Threshold
%--------------------------------------------------------------------------
thres         = cfg_entry;
thres.tag     = 'thres';
thres.name    = 'Probability threshold';
thres.help    = {['Specify the probability threshold to apply to the '...
                 'image (optional). Leave field empty to work on '...
                 'serial mode.']};
thres.strtype = 'r';
thres.num     = [0 Inf];
thres.val     = {[]};

%--------------------------------------------------------------------------
% k Extent threshold
%--------------------------------------------------------------------------
k         = cfg_entry;
k.tag     = 'k';
k.name    = 'Extent threshold';
k.help    = {['Specify extent threshold (minimum number of voxels '...
                 'per cluster).']};
k.strtype = 'w';
k.num     = [0 Inf];
k.val     = {[]};

%--------------------------------------------------------------------------
% scale Map Scale
%--------------------------------------------------------------------------
scale         = cfg_menu;
scale.tag     = 'scale';
scale.name    = 'Map scale';
scale.help    = {['Specify scale to display maps (optional). Default: '...
                 'empty field to work on serial mode. Other options: '...
                 '''None'' will display image with original scale and '...
                 '''Log-odds'' will display image in a log-odds '...
                 ' scale (in this case image should be a '...
                 'probability map).']};
scale.labels  = {
                  'Empty'
                  'None'
                  'Log-odds'
}';
scale.values  = {
                  []
                  0
                  1
}';
scale.val     = {[]};

%--------------------------------------------------------------------------
% bms_map_inf BMS: Maps (Inference), output is BMS map
%--------------------------------------------------------------------------
bms_map_inf      = cfg_exbranch;
bms_map_inf.tag  = 'inference';
bms_map_inf.name = 'BMS: Maps (Inference)';
bms_map_inf.val  = {dir map name_mod method_maps out_file mask nsamp };
bms_map_inf.help = {'Bayesian Model Selection for Log-Evidence Maps.'...
    ''...
    ['Input: log-evidence maps for each model, session and '...
    'subject. Note that there must be identical numbers of models for '...
    'all sessions, and identical numbers of sessions for all '...
    'subjects.']...
    ''...
    ['Output: For the fixed effects analysis, posterior probability maps '...
    'are created for each model. '...
    'For the random effects analysis, expected posterior probability '...
    'and exceedance probability (i.e. the probability that this model '...
    'is more likely than any other model) maps are created for each '...
    'model. If there are multiple sessions per subject, the random '...
    'effects analysis operates on the subject-specific sums of log '...
    'evidences across sessions. In addition, a BMS.mat file will be save '...
    'in the specified directory for both methods']};
bms_map_inf.prog = @spm_run_bms_map;
bms_map_inf.vout = @vout;

%--------------------------------------------------------------------------
% bms_map_vis BMS: Maps (Results), visualisation of BMS Maps results
%--------------------------------------------------------------------------
bms_map_vis      = cfg_exbranch;
bms_map_vis.tag  = 'results';
bms_map_vis.name = 'BMS: Maps (Results)';
bms_map_vis.val  = {file img thres k scale};
bms_map_vis.help = {['Bayesian Model Selection Maps (Results).'...
                    'Show results from BMS Maps (Inference).']};
bms_map_vis.prog = @spm_run_bms_vis;

%--------------------------------------------------------------------------
% bms Bayesian Model Selection
%--------------------------------------------------------------------------
bms         = cfg_choice;
bms.tag     = 'bms_map';
bms.name    = 'Bayesian Model Selection';
bms.help    = {['Bayesian Model Selection for group studies (fixed '...
               'effects and random effects analysis).']};
bms.values  = { bms_map_inf bms_map_vis };

%==========================================================================
function dep = vout(varargin)
% Output file names will be saved in a struct with field .files
dep(1)            = cfg_dep;
dep(1).sname      = 'BMS.mat File';
dep(1).src_output = substruct('.','files');
dep(1).tgt_spec   = cfg_findspec({{'filter','mat','strtype','e'}});


function [ALLEEG cfg] = pop_est_fitMVAR(ALLEEG,typeproc,varargin)
%
% Preprocess EEG dataset(s) for connectivity analysis. See [1] for
% mathematical details on preprocessing steps.
%
%
% Input:
%
%   ALLEEG:         Array of EEGLAB datasets to preprocess.
%   typeproc:       Reserved for future use. Use 0
%
% Optional:
%
%   <'Name',value> pairs as defined in pre_prepData()
%
% Output:
%
%   ALLEEG:         Prepocessed EEG structure(s)
%   cfg:            Argument specification structure.
%
%
% See Also: pre_prepData()
%
% References:
%
% [1] Mullen T (2010) The Source Information Flow Toolbox (SIFT):
%   Theoretical Handbook and User Manual. Section 6.5.1
%   Available at: http://www.sccn.ucsd.edu/wiki/Sift
%
% Author: Tim Mullen 2009, 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

if nargin<2
    typeproc = 0;
end

fcnName     = strrep(mfilename,'pop_','');
fcnHandle   = str2func(fcnName);

% check the dataset
res = hlp_checkeegset(ALLEEG,{'cat'});
if ~isempty(res)
    error(['SIFT:' fcnName],res{1});
end

if isfield(ALLEEG(1).CAT.configs,fcnName)
    % get default configuration (from prior use) and merge with varargin
    varargin = [hlp_struct2varargin(ALLEEG(1).CAT.configs.(fcnName)) varargin];
end

if strcmpi(typeproc,'nogui')
    % get the config from function
    cfg = arg_tovals(arg_report('rich',fcnHandle,[{'EEG',ALLEEG(1)},varargin]),false);
else
    % render the GUI
    [PGh figh] = feval(['gui_' fcnName],ALLEEG(1),varargin{:});

    if isempty(PGh)
        % user chose to cancel
        cfg = [];
        return;
    end

    % get the specification of the PropertyGrid
    ps = PGh.GetPropertySpecification;
    cfg = arg_tovals(ps,false);
end

drawnow;

if strcmpi(typeproc,'cfg_only')
    return;
end

% initialize progress bar
if cfg.verb==2 && length(ALLEEG)>1
    waitbarTitle = 'Fitting VAR Models';

    multiWaitbar(waitbarTitle,'Reset');
    multiWaitbar(waitbarTitle,'ResetCancel',true);
    multiWaitbar(waitbarTitle,...
                 'Color', [0.8 0.0 0.1],  ...
                 'CanCancel','on',        ...
                 'CancelFcn',@(a,b)disp('[Cancel requested. Please wait...]'));
end

% execute the low-level function
for cnd=1:length(ALLEEG)
    [ALLEEG(cnd).CAT.MODEL] = feval(fcnHandle,'EEG',ALLEEG(cnd),cfg);

    if ~isempty(cfg)
        % store the configuration structure
        ALLEEG(cnd).CAT.configs.(fcnName) = cfg;
    end

    if cfg.verb==2 && length(ALLEEG)>1
        % update waitbar
        drawnow;
        cancel = multiWaitbar(waitbarTitle,cnd/length(ALLEEG));
        if cancel && hlp_confirmWaitbarCancel(waitbarTitle)
            break;
        end
    end

end

% cleanup progress bar
if cfg.verb==2 && length(ALLEEG)>1
    multiWaitbar(waitbarTitle,'Close');
end


function rez = runTemplates(rez)

% this function will run Kilosort2 initializing at some previously found
% templates. These must be specified in rez.W, rez.U and rez.mu. The batch
% number at which the new template run is started is by default 1 (modify it by changing rez.istart).

% If you don't mind changes in template throughout the recording, but want
% to use the results from a previous session after splitting and merging, just pass
% the rez output from this previous session.

% Keep in mind that these templates will nonetheless
% change substantially as they track neurons throughout the new recording.
% As such, it is best to use the templates obtained at the very end of the
% previous recording, which are found in rez.WA(:,:,:,end),
% rez.UA(:,:,:,end), rez.muA(:,end). Keep in mind that any merging and
% splitting steps are done after running the templates, and would result in
% difference between sessions if done separately on each session.

% update: these recommendations no longer apply for the datashift version!

if sum(isfield(rez, {'istart'}))<1
    warning('if using pre-loaded templates, please specify istart, defaulting to 1');
    rez.istart = 1;
end

if sum(isfield(rez, {'W', 'U', 'mu'}))<3
    error('missing at least one field: W, U, mu');
end

Nbatches = rez.ops.Nbatch;

iorder = 1:Nbatches;

[rez, st3, fW,fWpc] = trackAndSort(rez, iorder);

% sort all spikes by batch -- to keep similar batches together,
% which avoids false splits in splitAllClusters. Break ties
% [~, isort] = sortrows(st3,[5,1,2,3,4]);
% st3 = st3(isort, :);
% fW = fW(:, isort);
% fWpc = fWpc(:, :, isort);

% just display the total number of spikes
fprintf( 'Number of spikes before applying cutoff: %d\n', size(st3,1));

rez.st3 = st3;
rez.st2 = st3; % keep also an st2 copy, because st3 will be over-written by one of the post-processing steps

% the template features are stored in cProj, like in Kilosort1
rez.cProj    = fW';

%  permute the PC projections in the right order
rez.cProjPC     = permute(fWpc, [3 2 1]); %zeros(size(st3,1), 3, nNeighPC, 'single');
% iNeighPC keeps the indices of the channels corresponding to the PC features


% --------------------------------------------------------------------------- %
% MarrRevisited - Surface Normal Estimation
% Copyright (c) 2016 Adobe Systems Incorporated and Carnegie Mellon University.
% All rights reserved.[see LICENSE for details]
% -------------------------------------------------------------------------- %

% Written by Aayush Bansal. Please contact ab.nsit@gmail.com
% demo code to use the surface normal mode --
clc; clear all;

%
conv_cache = ['./cachedir/demo_results/'];
if(~isdir(conv_cache))
        mkdir(conv_cache);
end

% initialize caffe
NET_FILE_PATH = ['./cachedir/surface_normal_models/'];
net_file     = [NET_FILE_PATH, 'best_model.caffemodel'];
DEPLOY_FILE_PATH = ['./net/conv/'];
deploy_file  = [DEPLOY_FILE_PATH, 'deploy.prototxt'];

% set the gpu --
% if not using GPU, set it to CPU mode.
gpu_id = 0;
caffe.reset_all;
caffe.set_device(gpu_id);
caffe.set_mode_gpu;
net = caffe.Net(deploy_file, net_file, 'test');

cnn_input_size = 224;
crop_height = 224; crop_width = 224;
image_mean = cat(3,  103.9390*ones(cnn_input_size),...
		     116.7700*ones(cnn_input_size),...
		     123.6800*ones(cnn_input_size));

% read the image set for NYU
img_data = {'demo/img_000001.jpg', 'demo/img_000002.jpg'};

% for each image in the img_set
for i = 1:length(img_data)

	display(['Image : ', img_data{i}]);
	ith_Img = im2uint8(imread(img_data{i}));

	%
        save_file_name = [conv_cache, strrep(img_data{i}, '.jpg', '')];
        if(exist([save_file_name, '.mat'], 'file'))
                continue;
        end

        j_ims = single(ith_Img(:,:,[3 2 1]));
        j_tmp = imresize(j_ims, [cnn_input_size, cnn_input_size], ...
                           'bilinear', 'antialiasing', false);
        j_tmp = j_tmp - image_mean;
        ims(:,:,:,1) = permute(j_tmp, [2 1 3]);

        snd(:,:,:,1) = (1/sqrt(3))*ones(cnn_input_size+200, cnn_input_size+200,3);
        depd(:,:,:,1) = zeros(cnn_input_size+200, cnn_input_size+200);

        %
        net.blobs('data0').reshape([crop_height+200, crop_width+200, 3, 1]);
        net.blobs('data2').reshape([crop_height+200, crop_width+200, 1, 1]);
        net.blobs('data1').reshape([crop_height+200, crop_width+200, 3, 1]);

        input_data = zeros(crop_height+200,crop_width+200,3,1);
        input_data(101:crop_width+100, 101:crop_width+100, :, 1) = ims;
        depd(101:crop_width+100, 101:crop_width+100, :, 1) = 1;
        net.blobs('data0').set_data(input_data);
        net.blobs('data2').set_data(depd);
        net.blobs('data1').set_data(snd);

        net.forward_prefilled();
        out = net.blobs('fc8_hcol').get_data();

        %%
        f2 = out';
        f2 = reshape(f2, [224, 224,3]);
        f2 = permute(f2, [2,1,3]);

        % normalize
        nx = f2(:,:,1); ny = f2(:,:,2); nz = f2(:,:,3);
        N = (nx.^2 + ny.^2 + nz.^2).^0.5 + eps;
        nx = nx./N; ny = ny./N; nz = nz./N;

        predns = cat(3, nx, ny, nz);
        predns = imresize(predns,...
                 [size(ith_Img,1), size(ith_Img,2)]);
        pred_N = (predns(:,:,1).^2 + predns(:,:,2).^2 +...
                                 predns(:,:,3).^2).^0.5 + eps;
        predns(:,:,1) = predns(:,:,1)./pred_N;
        predns(:,:,2) = predns(:,:,2)./pred_N;
        predns(:,:,3) = predns(:,:,3)./pred_N;

        predns_vis = uint8(255*(max(min(predns,1),-1)+1)/2);

        % dump the nx/ny/nz
        predns = single(predns);
        imwrite(predns_vis, [save_file_name, '.png']);
        save([save_file_name, '.mat'], 'predns')

end

% reset caffe
caffe.reset_all;


function kern = pathKernExpandParam(kern, params)

% PATHKERNEXPANDPARAM Create kernel structure from PATH kernel's parameters.
% FORMAT
% DESC returns a path kernel structure filled with the
% parameters in the given vector. This is used as a helper function to
% enable parameters to be optimised in, for example, the NETLAB
% optimisation functions.
% ARG kern : the kernel structure in which the parameters are to be
% placed.
% ARG param : vector of parameters which are to be placed in the
% kernel structure.
% RETURN kern : kernel structure with the given parameters in the
% relevant locations.
%
% SEEALSO : pathKernParamInit, pathKernExtractParam, kernExpandParam
%
% COPYRIGHT : Andrea Baisero, Carl Henrik Ek, 2013

% SHEFFIELDML

kern.cd=(params(1))^2;
kern.chv=params(2);
kern.gkern=kernExpandParam(kern.gkern,params(3:end));

kern = pathKernUpdateWMat(kern,[],true);


function output = BalancePrep(meta_meta)
% Balances the reactions, used in `ReactionChecks`
%
% USAGE:
%
%    output = BalancePrep(meta_meta)
%
% INPUT:
%    meta_meta:    matrix from `ReconstructionTool`
%
% OUTPUT:
%    output:   `leftside`, `rightside`, `charge_l` and `charge_r` in `varargout`
%
% .. Author: - Stefan G. Thorleifsson 2010
%
% .. rBioNet is published under GNU GENERAL PUBLIC LICENSE 3.0+
% .. Thorleifsson, S. G., Thiele, I., rBioNet: A COBRA toolbox extension for
% .. reconstructing high-quality biochemical networks, Bioinformatics, Accepted.
% .. rbionet@systemsbiology.is

output = [];
if isempty(meta_meta)
    return
end

S = size(meta_meta);

for i = 1:S(1);
    if ismember('',meta_meta(i,6))
        msgbox(['Reaction cannot be created with metabolites that are'...
            'missing the charged formula. ' meta_meta(i,1)  ],...
            'Missing charge formula','warn');
        return
    end
end
%---------- Creating formula ---------------- begin

%initialize variables
leftside = []; rightside = [];
charge_left = []; charge_right = [];

for i = 1:S(1)

    %creating metabolite [compartment] ready
    comp_str = meta_meta{i,4};
    comp_cnt = regexpi(comp_str,'\(');
    comp = comp_str(comp_cnt+1);

    if meta_meta{i,3} == 1 % No numbers
        newmetab = [meta_meta{i,1} '[' comp ']'];
    else
        newmetab = [num2str(meta_meta{i,3}) ' ' meta_meta{i,1} '[' comp ']'];
    end

    % Dividing left from right.
    if strmatch(meta_meta(i,5),'Substrate','exact')
        charge_left = [charge_left str2double(meta_meta{i,7})*meta_meta{i,3}]; %adding up the charge

        if isempty(leftside)
            leftside = newmetab;
        else
            leftside = [leftside ' + ' newmetab];
        end
    elseif strmatch(meta_meta(i,5),'Product','exact')
        charge_right = [charge_right str2double(meta_meta{i,7})*meta_meta{i,3}];%adding up the charge
        if isempty(rightside)
            rightside = newmetab;
        else
            rightside = [rightside ' + ' newmetab];
        end
    else
        msgbox('Something is wrong with Substrate and Product.',...
            'Reaction balance.','error');
        return
    end
end

charge_l = sum(charge_left);
charge_r = sum(charge_right);

output = {leftside,rightside,charge_l,charge_r};


function [gp, varargout] = gp_optim(gp, x, y, varargin)
%GP_OPTIM  Optimize paramaters of a Gaussian process
%
%  Description
%    GP = GP_OPTIM(GP, X, Y, OPTIONS) optimises the parameters of a
%    GP structure given matrix X of training inputs and vector
%    Y of training targets.
%
%    [GP, OUTPUT1, OUTPUT2, ...] = GP_OPTIM(GP, X, Y, OPTIONS)
%    optionally returns outputs of the optimization function.
%
%    OPTIONS is optional parameter-value pair
%      z      - optional observed quantity in triplet (x_i,y_i,z_i)
%               Some likelihoods may use this. For example, in case of
%               Poisson likelihood we have z_i=E_i, that is, expected
%               value for ith case.
%      optimf - function handle for an optimization function, which is
%               assumed to have similar input and output arguments
%               as usual fmin*-functions. Default is @fminscg.
%      opt    - options structure for the minimization function.
%               Use optimset to set these options. By default options
%               'GradObj' is 'on', 'LargeScale' is 'off'.
%      loss   - 'e' to minimize the marginal posterior energy (default) or
%               'loo' to minimize the negative leave-one-out lpd
%               'kfcv' to minimize the negative k-fold-cv lpd
%               'waic' to minimize the WAIC loss
%               only 'e' and 'loo' with Gaussian likelihood have gradients
%      k      - number of folds in kfcv
%
%  See also
%    GP_SET, GP_E, GP_G, GP_EG, FMINSCG, FMINLBFGS, OPTIMSET, DEMO_REGRESSION*
%
% Copyright (c) 2010-2012 Aki Vehtari

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

ip=inputParser;
ip.FunctionName = 'GP_OPTIM';
ip.addRequired('gp',@(x) isstruct(x) || isempty(x));
ip.addRequired('x', @(x) ~isempty(x) && isreal(x) && all(isfinite(x(:))))
ip.addRequired('y', @(x) ~isempty(x) && isreal(x) && all(isfinite(x(:))))
ip.addParamValue('z', [], @(x) isreal(x) && all(isfinite(x(:))))
ip.addParamValue('optimf', @fminscg, @(x) isa(x,'function_handle'))
ip.addParamValue('opt', [], @isstruct)
ip.addParamValue('loss', 'e', @(x) ismember(lower(x),{'e', 'loo', 'kfcv', 'waic' 'waic' 'waicv' 'waicg'}))
ip.addParamValue('k', 10, @(x) isreal(x) && isscalar(x) && isfinite(x) && x>0)
ip.parse(gp, x, y, varargin{:});
if isempty(gp)
  gp=gp_set();
end
if isempty(gp_pak(gp))
  % nothing to optimize
  return
end
z=ip.Results.z;
optimf=ip.Results.optimf;
opt=ip.Results.opt;
loss=ip.Results.loss;
k=ip.Results.k;

switch lower(loss)
  case 'e'
    fh_eg=@(ww) gp_eg(ww, gp, x, y, 'z', z);
    optdefault=struct('GradObj','on','LargeScale','off');
  case 'loo'
    fh_eg=@(ww) gp_looeg(ww, gp, x, y, 'z', z);
    if isfield(gp.lik.fh,'trcov') || isequal(gp.latent_method, 'EP')
      optdefault=struct('GradObj','on','LargeScale','off');
    else
      % Laplace-LOO does not have yet gradients
      optdefault=struct('Algorithm','interior-point');
      if ismember('optimf',ip.UsingDefaults)
        optimf=@fmincon;
      end
    end
  case 'kfcv'
    % kfcv does not have yet gradients
    fh_eg=@(ww) gp_kfcve(ww, gp, x, y, 'z', z, 'k', k);
    optdefault=struct('Algorithm','interior-point');
    if ismember('optimf',ip.UsingDefaults)
      optimf=@fmincon;
    end
  case {'waic' 'waicv'}
    % waic does not have yet gradients
    fh_eg=@(ww) -gp_waic(gp_unpak(gp,ww), x, y, 'z', z);
    optdefault=struct('Algorithm','interior-point');
    if ismember('optimf',ip.UsingDefaults)
      optimf=@fmincon;
    end
  case 'waicg'
    % waic does not have yet gradients
    fh_eg=@(ww) -gp_waic(gp_unpak(gp,ww), x, y, 'z', z, 'method', 'G');
    optdefault=struct('Algorithm','interior-point');
    if ismember('optimf',ip.UsingDefaults)
      optimf=@fmincon;
    end
end
opt=setOpt(optdefault,opt);
w=gp_pak(gp);
if isequal(lower(loss),'e') || (isequal(lower(loss),'loo')) && (isfield(gp.lik.fh,'trcov') || isequal(gp.latent_method, 'EP'))
  switch nargout
    case 6
      [w,fval,exitflag,output,grad,hessian] = optimf(fh_eg, w, opt);
      varargout={fval,exitflag,output,grad,hessian};
    case 5
      [w,fval,exitflag,output,grad] = optimf(fh_eg, w, opt);
      varargout={fval,exitflag,output,grad};
    case 4
      [w,fval,exitflag,output] = optimf(fh_eg, w, opt);
      varargout={fval,exitflag,output};
    case 3
      [w,fval,exitflag] = optimf(fh_eg, w, opt);
      varargout={fval,exitflag};
    case 2
      [w,fval] = optimf(fh_eg, w, opt);
      varargout={fval};
    case 1
      w = optimf(fh_eg, w, opt);
      varargout={};
  end
else
  lb=repmat(-8,size(w));
  ub=repmat(10,size(w));
  switch nargout
    case 6
      [w,fval,exitflag,output,grad,hessian] = optimf(fh_eg, w, [], [], [], [], lb, ub, [], opt);
      varargout={fval,exitflag,output,grad,hessian};
    case 5
      [w,fval,exitflag,output,grad] = optimf(fh_eg, w, [], [], [], [], lb, ub, [], opt);
      varargout={fval,exitflag,output,grad};
    case 4
      [w,fval,exitflag,output] = optimf(fh_eg, w, [], [], [], [], lb, ub, [], opt);
      varargout={fval,exitflag,output};
    case 3
      [w,fval,exitflag] = optimf(fh_eg, w, [], [], [], [], lb, ub, [], opt);
      varargout={fval,exitflag};
    case 2
      [w,fval] = optimf(fh_eg, w, [], [], [], [], lb, ub, [], opt);
      varargout={fval};
    case 1
      w = optimf(fh_eg, w, [], [], [], [], lb, ub, [], opt);
      varargout={};
  end
end
gp=gp_unpak(gp,w);
end

function opt=setOpt(optdefault, opt)
  % Set default options
  opttmp=optimset(optdefault,opt);

  % Set some additional options for @fminscg
  if isfield(opt,'lambda')
    opttmp.lambda=opt.lambda;
  end
  if isfield(opt,'lambdalim')
    opttmp.lambdalim=opt.lambdalim;
  end
  opt=opttmp;
end


%%% Note: run the 'DataGen/A_data_generation.m' to generate
%%% training data first.
clear;
rng('default')
addpath(genpath('./.'));
addpath(genpath('../.'));
addpath(genpath('../DataGen'));
addpath('matconvnet');
vl_setupnn;

%%%-------------------------------------------------------------------------
%%% Data generation
%%%-------------------------------------------------------------------------
A_data_generation;

%%%-------------------------------------------------------------------------
%%% Configuration
%%%-------------------------------------------------------------------------

opts.gpus             = [1 2]; %%% this code can only support multi-GPU!

opts.numSubBatches    = 1;
opts.bnormLearningRate= 0;

%%% solver
opts.solver           = 'Adam';
opts.numberImdb       = 1;

opts.derOutputs       = {'objective', 1} ;

ext               =  {'*.jpg','*.png','*.bmp'};

opts.gradientClipping = false; %%% set 'true' to prevent exploding gradients in the beginning.
opts.backPropDepth    = Inf;
%%%-------------------------------------------------------------------------
%%%   Initialize model and load data
%%%----------------------------------------------------

%%%  load data

global CurTask;
CurTask = 'Denoising'; %% 'Deblocking' and 'SISR'

opts.imdbDir          = '../DataGen/DN_PATCH192';
filepaths           =  [];
for i = 1 : length(ext)
    filepaths = [filepaths; dir(fullfile(opts.imdbDir, ext{i}))];
end
imdb.imdbPath = opts.imdbDir;
imdb.filepaths = filepaths;
imdb.images.set = ones(numel(filepaths),1);
fprintf('-----------------------------------------------------------\n');
fprintf('--------------------Training Number %d---------------------\n', numel(filepaths));
fprintf('-----------------------------------------------------------\n');
image = imread(fullfile(opts.imdbDir, filepaths(1).name));
imdb.patch_size = size(image, 1);

opts.learningRate     = [logspace(-3, -3, 15) logspace(-3.8, -4, 20) logspace(-4.5, -5, 10)];

%% for denosining, set simga to [15, 25, 50]; for SISR, set simga to [2, 3, 4], and for deblocking, set sigma to [10, 20, 30, 40]
opts.sigma            = 50;

opts.modelName        = ['MWCNN_GDSigma' num2str(opts.sigma)]; %%% model name
imdb.modelName        = opts.modelName;

opts.expDir      = fullfile('data', opts.modelName);
opts.batchSize        = 32*numel(opts.gpus);
net = net_wavelet_haart_24;

[~, ~] = cnn_train(net, imdb, ...
    'expDir', opts.expDir, ...
    'learningRate',opts.learningRate, ...
    'derOutputs',opts.derOutputs, ...
    'bnormLearningRate',opts.bnormLearningRate, ...
    'numSubBatches',opts.numSubBatches, ...
    'numberImdb',opts.numberImdb, ...
    'backPropDepth',opts.backPropDepth, ...
    'batchSize', opts.batchSize, ...
    'modelname', opts.modelName, ...
    'sigma', opts.sigma, ...
    'gpus',opts.gpus) ;


function [modelMin, modelPruned, Ex_Rxns] = generateCompactExchModel(model,minGrowth,biomassRxn,prune,fastFVA)
% This function identifies a subnetwork with the least number of possible exchange
% reactions given the model and the applied constraints. It returns the resulting pruned model.
%
% USAGE:
%
%    [modelMin, modelPruned, Ex_Rxns] = generateCompactExchModel(model, minGrowth, biomassRxn, prune, fastFVA)
%
% INPUTS:
%    model:         model structure
%    minGrowth:     minimal Growth rate to be set on biomass reaction
%    biomassRxn:    biomass reaction name (default: 'biomass_reaction2')
%    prune:         optional: to prune the model based on exchange reactions
%                   (default: 1)
%    fastFVA:       optional: to use fastFVA instead of fluxvariability for
%                   computing FVA results (default: 0)
%    medium:        (default: {})
%
% OUTPUTS:
%    modelUpdated:  same as input model but constraints on blocked reactions
%                   are set to be 0
%    modelPruned:   pruned model, where all blocked reactions are removed
%                   (attention this seems to cause issues with GPRs)
%    Ex_Rxns:       List of exchange reactions in pruned model
%
% .. Author: - Ines Thiele, 02/2014

medium={};

if ~exist('biomassRxn','var')
    biomassRxn = 'biomass_reaction2';
end
if ~exist('prune','var')
    prune = 1;
end
if ~exist('fastFVA','var')
    fastFVA = 0;
end

% find exchange reactions
cnt=1;
for t=1:length(model.rxns)
    if  strfind(model.rxns{t}, 'EX_')
        Ex_Rxns1All(cnt,1) =model.rxns(t); %make exchange reaction list
        cnt=cnt+1;
    elseif  strfind(model.rxns{t}, 'Ex_')
        Ex_Rxns1All(cnt,1) =model.rxns(t); %make exchange reaction list
        cnt=cnt+1;
    end
end
% exclude all exchanges that have been set
Ex_Rxns2Min = Ex_Rxns1All;

model.lb(find(ismember(model.rxns,biomassRxn)))=minGrowth;% based on slowlest cell line in data

% exclude ions
Ex_Rxns2Min(ismember(Ex_Rxns2Min,medium))=[];

% identify iteratively the minimal exchange reaction network
OptExchRxns = Ex_Rxns2Min;
LO = length(OptExchRxns);
OptExchRxnsLast = OptExchRxns;
modelMin = model;
first = 1;
while LO>0
    if length(OptExchRxns)>0
        [modelMin,AddedExchange] = findMinCardModel(modelMin,OptExchRxns);
        if first == 0
            [OptExchRxns] = findOptExchRxns(modelMin,OptExchRxns);
        elseif first == 1
           [OptExchRxns] = findOptExchRxns(modelMin,AddedExchange);
            first =1;
        end
        LO = length(OptExchRxnsLast) - length(OptExchRxns)
        OptExchRxnsLast = OptExchRxns;
    else
        LO = 0;
    end
end

if prune == 1
    % prune the model. modelMin has same dimension but all blockedRxns
    % have bounds set to 0
    [modelMin,modelPruned, Ex_Rxns] = pruneModel(modelMin,minGrowth,biomassRxn);
else
    modelPruned = struct();
    Ex_Rxns = '';
end


function eev(obj, eventnum)
    % CATALOG.EEV - Browse an Catalog object one event at a time.
    %  catalogObject.EEV() Browse through an Catalog object one event
    %  at a time in a similar way to the Seisan program 'eev'.

    if ~exist('eventnum','var')
        eventnum = 1;
    end

    while 1,

        % don't beyond start or end of this catalogObject object
        if eventnum<1
            eventnum=1;
        end
        if eventnum>numel(obj.otime)
            eventnum=numel(obj.otime);
        end
        % display line for this event
        dstr=datestr(obj.otime(eventnum),31);
        subclass=obj.etype{eventnum};
        mag=obj.mag(eventnum);
        outstr=sprintf('%s %7.2f %7.2f %7.2 %5.1f %s %s',dstr, obj.lon(eventnum), obj.lat(eventnum), obj.depth(eventnum), mag, obj.magtype{eventnum}, subclass);
        choice=input([outstr,':  ?'],'s');

        % process choice
        if isempty(choice)
            eventnum=eventnum+1; % ENTER goes to next event

        elseif (choice(1)=='c') % CLASSIFY
            classify_event(datenum);
% ^^ does this line need obj.otime?

        elseif (choice(1)=='f') % FORWARD N EVENTS
            num=1;
            if length(choice)>1
                num=str2num(choice(2:end));
            end
            eventnum=eventnum+num;

        elseif (choice(1)=='b') % BACKWARD N EVENTS
            num=1;
            if length(choice)>1
                num=str2num(choice(2:end));
            end
            eventnum=eventnum-num;

        elseif (choice(1)=='t') % JUMP TO TIME
            month=1;dd=1;hr=0;
            if length(choice)>4
                year=str2num(choice(2:5));
            end
            if length(choice)>6
                month=str2num(choice(6:7));
            end
            if length(choice)>8
                dd=str2num(choice(8:9));
            end
            if length(choice)>10
                hr=str2num(choice(10:11));
            end
            jumptime=datenum(year,month,dd,hr,0,0);
            eventnum = min(find(obj.otime >= jumptime));

        elseif (choice(1)=='s') % SUMMARISE - SHOW S FILE or similar data
            fprintf('\nTime:\t\t%s\n',dstr);
            fprintf('Longitude:\t%7.2f degrees\n',obj.lon(eventnum));
            fprintf('Latitude:\t%7.2f degrees\n',obj.lat(eventnum));
            fprintf('Depth:\t\t%7.2f km\n',obj.depth(eventnum));
            fprintf('Magnitude:\t%7.2f\n',obj.mag(eventnum));
            fprintf('Magnitude Type:\t%s\n',obj.magtype{eventnum});
            fprintf('Event Type:\t%s\n',obj.etype{eventnum});
            fprintf('\n');

        elseif (choice(1)=='x') % CLOSE ALL
            close all;

        elseif (choice=='q') % QUIT
            break;

        elseif (choice(1)=='h') % HELP
            disp(' ');
            disp('Options:');
            disp('________');
            disp(' ');
            disp('b[num]            - go backward 1 event (or N events)');
            disp('c                 - classify');
            %disp('e                 - edit/generate S-file');
            disp('f[num]            - go forward 1 event (or N events)');
            disp('h                 - this help');
            %disp('p                 - plot');
            disp('s                 - summarise');
            disp('tYYYY[MM[DD[HH]]] - jump to date/hour specified');
            disp('x                 - close all figure windows');
            disp('q                 - quit');
            disp(' ');
        end
    end
end


function [A_lh, A_rh]=cortical_label_adf(subject, p_val)
% Computes the area of the different cortical labels
% and compare them to the normal range
% Uses p_value to detect the abnormal areas
% Uses the lh/rh.parc.txt files
%

%
% cortical_labeling_afd_txt.m
%
% Original Author: Laurence Wastiaux
% CVS Revision Info:
%    $Author: nicks $
%    $Date: 2011/03/02 00:04:12 $
%    $Revision: 1.3 $
%
% Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH"
%
% Terms and conditions for use, reproduction, distribution and contribution
% are found in the 'FreeSurfer Software License Agreement' contained
% in the file 'LICENSE' found in the FreeSurfer distribution, and here:
%
% https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferSoftwareLicense
%
% Reporting: freesurfer@nmr.mgh.harvard.edu
%

if (nargin<2 | nargin>2)
    msg=sprintf('USAGE: [L, R]=cortical_label_adf(subject, p_val)');
    disp(msg)
end

A_lh=zeros(1,84);
A_rh=zeros(1,84);
namerh=[];
namelh=[];

labmapfile=('/space/lyon/1/fsdev/freesurfer_dev/Simple_surface_labels2002.txt');
[label name val1 val2 val3 val4]=textread(labmapfile,'%d %s %d %d %d %d',85);

%% a- Check if the left and right stats files exist %%
LabelDir=strcat(subject, '/label');
dlabel=dir(LabelDir);
if(length(dlabel)<=2)
    mess=sprintf('Directory %s is empty', LabelDir);
    error(mess)
end
if(length(dlabel)>2)
    if ((exist(strcat(LabelDir, '/rh.parc.txt'))==0) | (exist(strcat(LabelDir, '/lh.parc.txt'))==0))
        mess=sprintf('Cannot find the stats files for subject %s', subject);
        error(mess)
    end
end

%% b- Read areas for each label & for both hemispheres using the lh/rh.parc.txt files %%
sn=strread(subject, '%s', 'delimiter', '/');
subject_name=char(sn(length(sn)));
rh_LabelFile=strcat(subject, '/label/rh.parc.txt');
lh_LabelFile=strcat(subject, '/label/lh.parc.txt');

lh_fid=fopen(lh_LabelFile);
rh_fid=fopen(rh_LabelFile);
if(lh_fid == -1)
    msg=sprintf('Cannot open file %s', lh_LabelFile);
    error(msg)
elseif(rh_fid ==-1)
    msg=sprintf('Cannot open file %s', rh_LabelFile);
    error(msg)
else
    while(feof(lh_fid)==0)
        s=fgetl(lh_fid);
        if(strfind(s,'structure name')>1)
            s=fgetl(lh_fid);
            lhpt=ftell(lh_fid);
            break;
        end
    end
    fseek(lh_fid, lhpt,'bof');
    while(feof(lh_fid)==0)
        s=fgetl(lh_fid);
        a=strread(s,'%d',2);  %area
        aa=strread(s,'%s',11); %name
        llab=0;
        for test=1:length(name)
            if(strfind(char(name(test)),char(aa(11)))>=1)
                llab=label(test);
                break;
            end
        end
        if(llab==0)
            disp(sprintf('impossible to find the label'));
        elseif(A_lh(llab)~=0)
            disp(sprintf('already attributed'));
        else
            A_lh(llab)=a(2);
        end
    end
    while(feof(rh_fid)==0)
        s=fgetl(rh_fid);
        if(strfind(s,'structure name')>1)
            s=fgetl(rh_fid);
            rhpt=ftell(rh_fid);
            break;
        end
    end
    fseek(rh_fid, rhpt,'bof');
    while(feof(rh_fid)==0)
        s=fgetl(rh_fid);
        a=strread(s,'%d',2);
        aa=strread(s,'%s',11);
        llab=0;
        for test=1:length(name)
            if(strfind(char(name(test)),char(aa(11)))>=1)
                llab=label(test);
                break;
            end
        end
        if(llab==0)
            disp(sprintf('impossible to find the label'));
        elseif(A_rh(llab)~=0)
            disp(sprintf('already attributed'));
        else
            A_rh(llab)=a(2);
        end
    end
end
nl=length(name)-1;
if(length(A_lh)< nl)
    for lleft=(length(A_lh)+1):nl
        A_lh(lleft)=0;
    end
end
if(length(A_rh)< nl)
    for lleft=(length(A_rh)+1):nl
        A_rh(lleft)=0;
    end
end
if (sum(A_lh)==0 | sum(A_rh)==0)
    msg=sprintf('Total area is null');
    error(msg)
else
    total_lharea=sum(A_lh);
    total_rharea=sum(A_rh);
end
for i=1:nl
    A_lh(i)= 100 * A_lh(i) / total_lharea;
    A_rh(i)= 100 * A_rh(i) / total_rharea;
end
% Compute p_values %

count=0;
for k =1:length(A_lh)
    %disp(k)

    [Rpval_inf,Rpval_sup, Lpval_inf, Lpval_sup]=compute_pval(k,A_rh(k),A_lh(k));
    if ((Lpval_inf<p_val | Lpval_sup <p_val) & (A_lh(k)~=0))
        fprintf('%s, left hemisphere: percent area of %s (%d) = %g (pval_inf=%g, pval_sup=%g)\n' ,subject_name, char(name(k+1)), k , A_lh(k),Lpval_inf, Lpval_sup);
        count=1;
    end
    if ((Rpval_inf<p_val | Rpval_sup <p_val)& (A_rh(k)~=0))
        fprintf('%s, right hemisphere: percent area of %s (%d) = %g (pval_inf=%g, pval_sup=%g)\n' ,subject_name, char(name(k+1)),k, A_rh(k),Rpval_inf,Rpval_sup);
        count=1;
    end

end
if(count==0)
    fprintf('%s: subject is normal\n', subject_name);
end

% subfunction compute_pval() %
function [pinf_rh, psup_rh, pinf_lh, psup_lh]=compute_pval(llabel,R,L)
%load('/space/okapi/3/data/laurence/ADF/cortical_labeling/PercentArea_labels.mat'); % loads D_lh and D_rh
% load('/space/okapi/3/data/laurence/ADF/cortical_labeling/PercentArea_labels_parctxt.mat');
% D_lh=D2_lh;
% D_rh=D2_rh;
%rh_stat_file='/space/okapi/3/data/laurence/ADF/cortical_labeling/rh.CorticalLabelingPercentArea_txt.adf';
%lh_stat_file='/space/okapi/3/data/laurence/ADF/cortical_labeling/lh.CorticalLabelingPercentArea_txt.adf';
%%% Get the table's directory %%%
if(getenv('FREESURFER_HOME'))
    fsh=getenv('FREESURFER_HOME');
    fsafdDir=strcat(fsh, '/fsafd');
else
    error(sprintf('Impossible to find FREESURFER_HOME\n'));
end
rh_stat_file=strcat(fsafdDir, '/rh.CorticalLabelingPercentArea_txt.adf');
lh_stat_file=strcat(fsafdDir, '/lh.CorticalLabelingPercentArea_txt.adf');
fidrh=fopen(rh_stat_file);
fidlh=fopen(lh_stat_file);
if(fidrh==-1 | fidlh==-1)
    mess=sprintf('Could not find %s or %s', rh_stat_file, lh_stat_file);
    error(mess)
end
while(strfind(fgetl(fidrh), '#'))
    pos=ftell(fidrh);
end
fseek(fidrh, pos, 'bof');
D_rhtmp=fscanf(fidrh, '%g');
nrowr=length(D_rhtmp)/84;
D_rh=(reshape(D_rhtmp, [84, nrowr]))';
while(strfind(fgetl(fidlh), '#'))
    pos=ftell(fidlh);
end
fseek(fidlh, pos, 'bof');
D_lhtmp=fscanf(fidlh, '%g');
nrow=length(D_lhtmp)/84;
D_lh=(reshape(D_lhtmp, [84,nrow]))';
%distribution%
pas=0.01;
x=0:pas:18;
[h1] = hist(D_lh(:,llabel),x);
[h2] = hist(D_rh(:,llabel),x);
%[h1] = hist(D2_lh(:,llabel),x);
%[h2] = hist(D2_rh(:,llabel),x);
p1 = h1/sum(h1);
p2 = h2/sum(h2);
d1inf=find(x<=L);
d2inf=find(x<=R);
d1sup=find(x>L);
d2sup=find(x>R);
x1inf=x(d1inf);
x1sup=x(d1sup);
x2inf=x(d2inf);
x2sup=x(d2sup);
p1inf=p1(1:length(x1inf));
p2inf=p2(1:length(x2inf));
p1sup=p1(length(x)-length(x1sup)+1:end);
p2sup=p2(length(x)-length(x2sup)+1:end);
if( L>=0 & length(x1inf)>1 & length(x1sup)>1)
    pinf_lh=trapz(x1inf,p1inf)/pas;
    psup_lh=trapz(x1sup,p1sup)/pas;
else   % No subdivisions of the last intervals
    pinf_lh=0;
    psup_lh=0;
end
if(R>=0 & length(x2inf)>1 & length(x2sup)>1)
    pinf_rh=trapz(x2inf,p2inf)/pas;
    psup_rh=trapz(x2sup,p2sup)/pas;
else
    pinf_rh=0;
    psup_rh=0;
end


%CAMSHIFT  Finds an object center, size, and orientation
%
%     box = cv.CamShift(probImage, window)
%     [box,window] = cv.CamShift(probImage, window)
%     [...] = cv.CamShift(..., 'OptionName', optionValue, ...)
%
% ## Input
% * __probImage__ Back projection of the object histogram. See
%   cv.calcBackProject for details.
% * __window__ Initial search window `[x,y,w,h]`.
%
% ## Output
% * __box__ Output rectangle with rotation. A scalar structure of the form:
%   `struct('center',[x,y], 'size',[w,h], 'angle',a)`
% * __window__ Converged CAMSHIFT window `[x,y,w,h]`
%
% ## Options
% * __Criteria__ Stop criteria for the underlying cv.meanShift. Accepts a
%   struct with 'type', 'maxCount', and 'epsilon' fields. Default
%   `struct('type','Count+EPS', 'maxCount',100, 'epsilon',1.0)`
%
% The function implements the CAMSHIFT object tracking algorithm
% [Bradski98]. First, it finds an object center using cv.meanShift and then
% adjusts the window size and finds the optimal rotation. The function
% returns the rotated rectangle structure that includes the object
% position, size, and orientation. The next position of the search window
% can be obtained with cv.RotatedRect.boundingRect.
%
% ## References
% [Bradski98]:
% > Gary R Bradski. Computer vision face tracking for use in a perceptual
% > user interface. 1998.
%
% See also: cv.meanShift, cv.calcBackProject, vision.HistogramBasedTracker
%


function dt6_new = dtiResliceTensorSn3d(dt6, sn3dParams, nonLinearFlag, mmPerVoxOut, xformToTensor, rotTensorMethod)
% dt6_new = dtiResliceTensor(dt6, sn3dParams, [nonLinearFlag], [mmPerVoxOut], [xformToTensor], [rotTensorMethod])
%
% Applies spm-style sn3d parameters to a tensor volume in dt6 format.
% These sn3d parameters include a linear (affine) component and a non-linear component.
%
% INPUT:
%   dt6                 XxYxZx6 tensor array. If last dimension is 1 then data is
%                       treated as scalar volume.
%   sn3dParams          The sn3d parameter structure from SPM.
%   nonLinearFlag       If 1 (default), non-linear component is included.
%                       If 0, then non-linear component is not included.
%   mmPerVoxOut         mm per voxel in resliced array.
%   xformToTensor       Linear xform required with raw data. Not required if
%                       data is in Analyze format (set to identity).
%   rotTensorMethod     Method of tensor rotation. Ignored if data is scalar.
%                           'SPM' (using spm_matrix.m) - default
%                           'FS' (finite strain)
%                           'PPD' (preservation fo principal direction)
%                           '' (no rotation)
%
% OUTPUT:
%   dt6_new             XxYxZx6 tensor array, or XxYxZ if data is scalar.
%
% REQUIRES:
% spm99 or spm2 in the path.
%
% HISTORY:
% 2004.09.13 ASH & RFD Wrote it.
% 2005.01.12 RFD: Cleaning code, adding support for SPM2 spatial norm
% params, and adding code to do a proper tensor correction with nonlinear
% deformations.
%
% Example:
% sn3dParams = load('dti_analyses/may021126_B0_sn3d.mat');
% xformToB0 = computeCannonicalXformFromIfile('dti/B0.001');
% xformToTensor = inv(xformToB0);
% [eigVec,eigVal,mm] = dtiLoadTensor('/snarp/u1/dti/adultData/may021126/dti/Vectors.float');
% dt6 = dtiRebuildTensor(eigVec, eigVal);
% dt6_new = dtiResliceTensorSn3d(dt6, sn3dParams, mmPerVoxOut, xformToTensor);
% [newVec, newVal] = dtiSplitTensor(dt6_new);
% fa = dtiComputeFA(newVal);
% figure; imagesc(fa(:,:,23)); axis equal; colormap gray; axis xy;

if (size(dt6,4)~=6 & size(dt6,4)~=1),
    error('Wrong input format')
end
if(~exist('nonLinearFlag') | isempty(nonLinearFlag))
    nonLinearFlag = 1;
end
if(~exist('mmPerVoxOut') | isempty(mmPerVoxOut))
    mmPerVoxOut = [2 2 2];
end
if(~exist('xformToTensor') | isempty(xformToTensor))
    xformToTensor = eye(4);
end
if(~exist('rotTensorMethod') | isempty(rotTensorMethod))
    rotTensorMethod = 'SPM';
end

% Create a bounding box for the resliced data.
% The following is the spm default bounding box. Note that the box is
% defined in Talairach space (units = mm).
bb = [-78 -112 -50;
       78  76   85];

x = (bb(1,1):mmPerVoxOut(1):bb(2,1));
y = (bb(1,2):mmPerVoxOut(2):bb(2,2));
z = (bb(1,3):mmPerVoxOut(3):bb(2,3));

if(isfield(sn3dParams, 'Dims'))
    mm = sn3dParams.Dims(6,:)';
else
    % support spm2 style sn params
    mm = diag(sn3dParams.VF.mat(1:3,1:3));
end

[X,Y,Z] = meshgrid(x, y, z);
clear x y z;

talCoords = [X(:) Y(:) Z(:)];
newSize = size(X);
clear X Y Z;

imgCoords = mrAnatGetImageCoordsFromSn(sn3dParams, talCoords, nonLinearFlag);
if(isfield(sn3dParams,'VF'))
    [trans,rot,mm,skew] = affineDecompose(sn3dParams.VF.mat);
    imgCoords = mrAnatXformCoords(inv(sn3dParams.VF.mat)*xformToTensor, imgCoords')';
else
    mm = sn3dParams.Dims(6,:)';
    imgCoords = imgCoords./repmat(mm,1,size(imgCoords,2));
    imgOrigin = sn3dParams.Dims(5,:)'/2;
    imgCoords = imgCoords+repmat(imgOrigin,1,size(imgCoords,2));
    % We now have image coords for the space defined by the bounding box (in
    % Talairach space). These image coords are in the space of the original
    % image that was used to compute the sn3d params. But that may not be the
    % same space as the tensor image.
    imgCoords = mrAnatXformCoords(xformToTensor, imgCoords);
    imgCoords(1,:) = imgCoords(1,:).*mm(1);
    imgCoords(2,:) = imgCoords(2,:).*mm(2);
    imgCoords(3,:) = imgCoords(3,:).*mm(3);
end

fprintf('Interpolate coordinate grid...\n')
if (size(dt6,4)==6),
    % convert from matlab 1-indexing to C 0-indexing
	imgCoords = imgCoords - 1;

	% *** HACK so that matlab can find the shared library
	old = pwd;
	cd(fileparts(which('dtiTensorInterp_Pajevic')));
	dt6_new = dtiTensorInterp_Pajevic(dt6, [imgCoords(2,:);imgCoords(1,:);imgCoords(3,:)]', mm, 1, mm./2);
	cd(old);
    dt6_new = reshape(dt6_new, [newSize, 6]);
else
    dt6_new = myCinterp3(dt6, [size(dt6,1) size(dt6,2)], size(dt6,3), imgCoords', 0.0);
    dt6_new = reshape(dt6_new, [newSize, 1]);
end
dt6_new = real(dt6_new);

% ROTATE THE TENSORS
fprintf('Rotate tensors...\n')
xformTalToImg = sn3dParams.MF * sn3dParams.Affine * inv(sn3dParams.MG);
xformImgToTal = inv(xformTalToImg);

% Apply just the rigid rotation component of the xform to the tensors
if (size(dt6,4)==6),
    switch rotTensorMethod,
    case 'SPM',
        % spm_matrix method
		p = spm_imatrix(xformImgToTal);
		p([1:3,10:12]) = 0; p(7:9) = 1;
		rot = spm_matrix(p); rot = rot(1:3,1:3);
     	dt6_new = dtiXformTensors(dt6_new, rot);
    case 'FS',
        % Finite strain method
    	rigidXform = dtiFiniteStrainDecompose(xformImgToTal);
     	dt6_new = dtiXformTensors(dt6_new, rigidXform);
    case 'PPD',
        % Preservation of principal direction method
        dt6_new = dtiXformTensorsPPD(dt6_new, xformImgToTal);
    end
end
% Apply cannonical transform
% xformToTensor is same as inv(xformToTensor)
dt6_new = dtiXformTensors(dt6_new, xformToTensor);

return;


function MeshMat = in_tess_simnibs(MeshFile, FileFormat)
% IN_TESS_SIMNIBS: Reads a 3D mesh from a gmsh4 file generated with SimNIBS

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Takfarinas Medani, Francois Tadel, 2022-2023

% Read mesh
m = mesh_load_gmsh4(MeshFile);

% Get file name
[fPath, fBase, fExt] = bst_fileparts(MeshFile);

% Convert to bst format
MeshMat = db_template('femmat');
MeshMat.Comment  = fBase;
MeshMat.Vertices = m.nodes(:,1:3);
MeshMat.Elements = double(m.tetrahedra(:,1:4));
MeshMat.Tissue   = double(m.tetrahedron_regions);

% Swap tetrahedrons orientation
MeshMat.Elements = MeshMat.Elements(:, [2 1 3 4]);

switch (FileFormat)
    case 'SIMNIBS3'
        % Replace the eyes with scalp (not used for now)
        % MeshMat.Tissue(MeshMat.Tissue==6) = 5;

        % Default tissue labels
        switch length(unique(MeshMat.Tissue))
            case 3
                MeshMat.TissueLabels = {'brain', 'skull', 'scalp'};
            case 4
                MeshMat.TissueLabels = {'brain', 'csf', 'skull', 'scalp'};
            case 5
                MeshMat.TissueLabels = {'white', 'gray', 'csf', 'skull', 'scalp'};
            otherwise
                uniqueLabels = unique(MeshMat.Tissue);
                for i = 1:length(uniqueLabels)
                     MeshMat.TissueLabels{i} = num2str(uniqueLabels(i));
                end
        end

    case 'SIMNIBS4'
        % Relabel the electrodes and gel
        MeshMat.Tissue(MeshMat.Tissue==100) = 11;
        MeshMat.Tissue(MeshMat.Tissue==500) = 12;
        % Default tissue labels (from file: final_tissues_LUT.txt)
        MeshMat.TissueLabels = {'white', 'gray', 'csf', 'skull', 'scalp', 'eyes', 'compact', 'spongy', 'blood', 'muscle', 'electrode', 'gel'};
end


function runTrackerDets(isSeqDisplay, gtPath, datasetPath, detPath, resPath, seqPath, trackerName)

createPath(resPath); % create the saving path of the tracking results
seqList = load(seqPath); % find the sequence list

% evaluate each sequence
for idSeq = 1:length(seqList)
    if(mod(idSeq,10)==0)
        disp(['tracking the sequence ' num2str(idSeq) '/' num2str(length(seqList)) '...']);
    end
    % load detections and sequence
    seqID = seqList(idSeq);
    seqName = sprintf('%05d',seqID);
    sequence.dataset = dir(fullfile(datasetPath, [seqName '/*.jpg']));
    sequence.seqPath = fullfile(datasetPath, seqName);
    sequence.seqName = seqName;
    img = imread(fullfile(datasetPath, seqName, sequence.dataset(1).name));
    [sequence.imgHeight, sequence.imgWidth, ~] = size(img);
    % nms processing
    detections = [];
    for i = 1:length(sequence.dataset)
        det = load(fullfile(detPath, sprintf('img%03d%03d_loc.txt',seqID,i)));
        if(size(det,2) ~= 3)
            det = det';
        end
        if(~isempty(det))
            idx = det(:,3) > 0;
            det = det(idx,:);
        end
        numdet = size(det,1);
        if(numdet>0)
            curdet = [repmat([i, -1], [numdet, 1]), det(:,1)-10, det(:,2)-10, repmat([20, 20], [numdet, 1]), det(:,3), repmat([-1, -1, -1], [numdet, 1])];
            detections = cat(1, detections, curdet);
        end
    end
    % show the tracking results
    dlmwrite(fullfile(resPath, [seqName '_det.txt']), detections);

end


function [V,compareFluxes] = exoMetLOOCV(model,measuredFluxes,param)
% model: COBRA model
%
% measuredFluxes:   table with the fluxes obtained from exometabolomics experiments with the following variables
%           * .rxns:    k x 1 cell array of reaction identifiers
%           * .mean:    k x 1 double of measured mean flux
%           * .SD:      k x 1 double standard deviation of the measured flux
%           * .labels:  k x 1 cell array of labels to display on y axis
%           * .Properties.Description: string describing the data, used in plot legend
%
%  param.alpha:              alpha in (alpha/2)(v-h)'*H*(v-h), default = 10000;
%  param.metabolomicWeights: String indicating the type of weights to be applied to penalise the difference
%                            between of predicted and experimentally measured fluxes by, where
%                            'SD'   weights = 1/(1+exoMet.SD^2)
%                            'mean' weights = 1/(1+exoMet.mean^2)
%                            'RSD'  weights = 1/((exoMet.SD./exoMet.mean)^2)
%  param.relaxBounds: True to relax bounds on reaction whose fluxes are to be fitted to exometabolomic data
%
%
% OUTPUTS:
%  V:     table with the fluxes predicted by leave one out cross validation
%           * .rxns:    n x 1 cell array of reaction identifiers, one for each in input model
%           * .v:       n x 1 double of predicted mean flux
%           * .lb:      n x 1 double lower bound on reaction flux
%           * .ub:      n x 1 double upper bound on reaction flux
%
% LIBkey:
%
% EXAMPLE:
%
% NOTE:
%
% Author(s):
if ~exist('param','var')
    param = struct;
end
if ~isfield(param,'alpha')
    param.alpha=10000;
end
if ~isfield(param,'relaxBounds')
    param.relaxBounds=1;
end
if ~isfield(param,'metabolomicWeights')
    param.metabolomicWeights = 'mean';
end
if ~isfield(param,'relaxBounds')
    param.relaxBounds=1;
end
if ~isfield(param,'approach')
    param.approach='QEFBA';
end

[~,nRxns] = size(model.S);

if param.relaxBounds
    bool=ismember(model.rxns,measuredFluxes.rxns);
    model.lb(bool) = model.lb_preconstrainRxns(bool);
    model.ub(bool) = model.ub_preconstrainRxns(bool);
end

modelOrig = model;

if 1
    [measuredFluxes,LIBkey,LOCAkey] = mapAontoB(measuredFluxes.rxns,model.rxns,measuredFluxes);

    %preallocate and add data from measurments
    V = zeros(nRxns,nnz(LIBkey)+4);
    varNames = cell(nnz(LIBkey)+4,1);
    V(:,1) = measuredFluxes.mean;
    varNames{1} = 'mean';
    V(:,2) = measuredFluxes.SD;
    varNames{2} = 'SD';

    %reduce to the measured fluxes part of the model
    measuredFluxes = measuredFluxes(LIBkey,:);
else
    nMeasuredRxns = size(measuredFluxes,1);

    %preallocate and add data from measurments
    V = zeros(nRxns,nMeasuredRxns+4);
    varNames = cell(nMeasuredRxns+4,1);
    [V(:,1),LIBkey] = mapAontoB(measuredFluxes.rxns,model.rxns,measuredFluxes.mean);
    varNames{1} = 'mean';
    V(:,2) = mapAontoB(measuredFluxes.rxns,model.rxns,measuredFluxes.SD);
    varNames{2} = 'SD';
end

nMeasuredRxns = size(measuredFluxes,1);
bool = true(nMeasuredRxns,1);

%loop through the measured fluxes, leaving one of them out each time
for i=1:nMeasuredRxns
    bool(i)=0;
    switch param.approach
        case 'QEFBA'
            if i==1
                %compare without leaving any measured flux out
                model = addExoMetToEFBA(modelOrig,measuredFluxes,param);
                efbaParam.method = 'fluxes';
                efbaParam.printLevel = 0;
                model.osenseStr = 'min';
                model.cf = 0;
                model.cr = 0;
                model.g = 2;
                model.u0 = 0;
                model.f = 1;
                [QEFBAsolution, ~] = entropicFluxBalanceAnalysis(model,efbaParam);
                V(:,3) = QEFBAsolution.v;
                varNames{3}='QEFBA';
            end

            model = changeRxnBounds(modelOrig, measuredFluxes.rxns(~bool), min(modelOrig.lb), 'l');
            model = changeRxnBounds(model, measuredFluxes.rxns(~bool), max(modelOrig.ub), 'u');
            model = addExoMetToEFBA(model,measuredFluxes(bool,:),param);
            efbaParam.method = 'fluxes';
            efbaParam.printLevel = 0;
            model.osenseStr = 'min';
            model.cf = 0;
            model.cr = 0;
            model.g = 2;
            model.u0 = 0;
            model.f = 1;
            [solution, modelOut] = entropicFluxBalanceAnalysis(model,efbaParam);
            V(:,i+4) = solution.v;
            varNames{i+4}=measuredFluxes.rxns{~bool};

            %generate a flux vector amalgamated from all of the leave one out predictions
            boolRxn = ismember(model.rxns,measuredFluxes.rxns(~bool));
            V(boolRxn,4) = solution.v(boolRxn);
            if i==1
                varNames{4}='LOOCV';
            end
    end
    bool(i)=1;
end

V = array2table(V,'VariableNames',varNames);
V = addvars(V,model.rxns,modelOrig.lb,modelOrig.ub,'NewVariableNames',{'rxns','lb','ub'},'Before','mean');
% V = V(LIBkey,:);

compareFluxes = mapAontoB('rxns','rxns',V,measuredFluxes);


function [success,msg,...
  arenatype,arenacenterx,arenacentery,...
  arenaradius,arenawidth,arenaheight,...
  pxpermm] = ...
  ReadArenaParameters_Ctrax(varargin)

success = false;
msg = ''; %#ok<NASGU>

[inmoviefile,...
  arenatype,arenacenterx,arenacentery,...
  arenaradius,arenawidth,arenaheight,...
  pxpermm,intrxfile,annfile,inperframedir] = myparse(varargin,...
  'inmoviefile','',...
  'arenatype','None','arenacenterx',0,'arenacentery',0,...
  'arenaradius',123,'arenawidth',123,'arenaheight',123,...
  'pxpermm',1,'intrxfile','','annfile','','inperframedir','');

% try to read from the trx file first
if isempty(intrxfile),
  msg = 'Input trxfile not yet set';
  return;
end

try
  [trx,~,success1] = load_tracks(intrxfile,inmoviefile,...
    'dosave',false,'annname',annfile,'verbose',false);
  if ~success1,
    msg = sprintf('Could not load tracks from trxfile %s',intrxfile);
    return;
  end
catch ME,
  msg = sprintf('Could not load from trxfile %s: %s',intrxfile,getReport(ME));
  return;
end

readarenafrom = '';
readpxpermmfrom = '';
readoff = false;
if isfield(trx,'pxpermm'),
  newpxpermm = nanmean([trx.pxpermm]);
  if ~isnan(newpxpermm) && newpxpermm > 0,
    pxpermm = newpxpermm;
    readpxpermmfrom = 'intrxfile';
  end
  if all(isfield(trx,{'x','x_mm','y','y_mm'})),
    offx = nanmean(([trx.x] - [trx.x_mm])*pxpermm);
    offy = nanmean(([trx.y] - [trx.y_mm])*pxpermm);
    readoff = true;
  end
end

if isfield(trx,'arena'),

  % in px
  if all(isfield(trx(1).arena,{'x','y','r'})),
    arenacenterx = trx(1).arena.x;
    arenacentery = trx(1).arena.y;
    arenaradius = trx(1).arena.r;
    arenatype = 'Circle';
    readarenafrom = 'intrxfile';
  elseif ~isempty(readpxpermmfrom) && readoff && ...
      all(isfield(trx(1).arena,{'arena_radius_mm','arena_center_mm_x','arena_center_mm_y'})),
    arenacenterx = trx(1).arena_center_mm_x * pxpermm + offx;
    arenacentery = trx(1).arena_center_mm_y * pxpermm + offy;
    arenaradius = trx(1).arena_radius_mm * pxpermm;
    readarenafrom = 'intrxfile';
  elseif all(isfield(arena,{'tl_px','tr_px','bl_px','br_px'})),
    tl_px = trx(1).arena.tl;
    tr_px = trx(1).arena.tr;
    bl_px = trx(1).arena.bl;
    br_px = trx(1).arena.br;
    arenawidth = mean([abs(tr_px(1)-tl_px(1)),abs(br_px(1)-bl_px(1))]);
    arenaheight = mean([abs(tr_px(2)-br_px(2)),abs(tl_px(2)-bl_px(2))]);
    arenacenterx = mean([tl_px(1),tr_px(1),bl_px(1),br_px(1)]);
    arenacentery = mean([tl_px(2),tr_px(2),bl_px(2),br_px(2)]);
    arenatype = 'Rectangle';
    readarenafrom = 'intrxfile';
  elseif ~isempty(readpxpermmfrom) && readoff && all(isfield(arena,{'tl','tr','bl','br'})),
    tl_px = trx(1).arena.tl(:)'*pxpermm + [offx,offy];
    tr_px = trx(1).arena.tr(:)'*pxpermm + [offx,offy];
    bl_px = trx(1).arena.bl(:)'*pxpermm + [offx,offy];
    br_px = trx(1).arena.br(:)'*pxpermm + [offx,offy];
    arenawidth = mean([abs(tr_px(1)-tl_px(1)),abs(br_px(1)-bl_px(1))]);
    arenaheight = mean([abs(tr_px(2)-br_px(2)),abs(tl_px(2)-bl_px(2))]);
    arenacenterx = mean([tl_px(1),tr_px(1),bl_px(1),br_px(1)]);
    arenacentery = mean([tl_px(2),tr_px(2),bl_px(2),br_px(2)]);
    arenatype = 'Rectangle';
    readarenafrom = 'intrxfile';
  end

end

if isempty(readarenafrom) && ~isempty(annfile),
  % try to read from annfile
  [newarenacenterx,newarenacentery,newarenaradius,dosetcirculararena] = ...
    read_ann('arena_center_x','arena_center_y','arena_radius','do_set_circular_arena');
  if dosetcirculararena && newarenaradius > 0 && ~any(isnan([newarenaradius,newarenacenterx,newarenacentery])),
    arenacenterx = newarenacenterx;
    arenacentery = newarenacentery;
    arenaradius = newarenaradius;
    arenatype = 'Circle';
    readarenafrom = 'annfile';
  end
end

success = ~isempty(readarenafrom);
if ~isempty(readarenafrom);
  msg = sprintf('Read arena from %s, ',readarenafrom);
else
  msg = sprintf('Did not read arena, ');
end
if ~isempty(readpxpermmfrom);
  msg = [msg, sprintf('read pxpermm from %s.',readpxpermmfrom)];
else
  msg = [msg, sprintf('Did not read pxpermm.')];
end


%kkrect2pol 'Convert (real, imaginary) to (r, theta) Coordinates'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros krect2pol.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'Input data object'
% OutputFile: o 'Output', required: 'Resulting output data object'
%
% Example: o = kkrect2pol(i, {'i','';'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% krect2pol - Convert (real, imaginary) to (r, theta) Coordinates
%
%  DESCRIPTION
% The "Rect. to Polar" operator converts data from the rectangular to the
% polar coordinate system for each complex data point in the input data
% object, \fBInput".  The conversion from rectangular to polar will result
% in angles measured in radians.  The data type of
% the output data object, \fBOutput", will be the same as the data type
% of \fBInput".
%
% Executing "Rect. to Polar" runs the program \fIkcmplx\fP
% with the -r2p flag.
%
%  "Map Data" 5
% .cI $DATAMANIP/repos/shared/man/sections/map_1input
%
%  "Validity Mask" 5
% .cI $DATAMANIP/repos/shared/man/sections/mask_1input
%
%  "Location and Time Data" 5
% .cI $DATAMANIP/repos/shared/man/sections/loc_and_time_1input
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
% DATAMANIP::kcmplx, DATAMANIP::kpol2rect
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kkrect2pol(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kkrect2pol(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'o', '__output'};
maxval={0,0};
minval={0,0};
istoggle=[0,0];
was_set=istoggle * 0;
paramtype={'InputFile','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'kcmplx"  -r2p'],Inputs,narglist);


function [f,the_regimes,endog,data,tex]=load_filters(m)

n=numel(m);

if n>1

    f=cell(size(m));
    the_regimes=f;
    endog=f;
    data=f;
    tex=f;

    for ii=1:n

        [f{ii},the_regimes{ii},endog{ii},data{ii},tex{ii}]=load_filters(m(ii));

    end

    return

end

if isa(m,'abstvar')

    [~,~,~,f]=filter(m);

    the_regimes=generic.describe_regimes(m.markov_chain_info);

    data=m.estim_.data;

    endog=m.endogenous;

    tex=[];

else

    f=filter(m);

    the_regimes=generic.describe_regimes(m.markov_chains);

    endog=m.observables.name;

    data=m.options.data;

    if isa(data,'ts')

        data=pages2struct(data);

    end

    tex=get(m,'tex');

end

end


function d = simulateDataError(d)
global ERROR_ODDS_CONST
global logger

logger = InitLogger(logger);

if nargin == 0
    d = [];
    return
end
if isempty(d)
    return
end
if isempty(ERROR_ODDS_CONST)
    return
end
if ERROR_ODDS_CONST == 0
    return
end

% Set error odds in percent units
r = round(ERROR_ODDS_CONST*rand());
if r==1
    percentErrs = 7;
    n = length(d(:,1));
    idxs = floor(n * rand(1, uint32((n*percentErrs)/100)));
    k = find(idxs==0);
    idxs(k) = 1;
    d0 = d;
    d(idxs,1) = d(idxs,1) + d(idxs,1).*rand(length(idxs),1);
    logger.Write('\n**** Simulated %d errors:    d(%d,1) orig:  %0.4g,  d(%d,1) new:  %0.4g,  error size = %0.4g ****\n\n',  ...
          length(idxs), idxs(1), d0(idxs(1),1), idxs(1), d(idxs(1),1), abs(d0(idxs(1),1)-d(idxs(1),1)));
end


function SPGR_PlotSimCurve(MTdata, MTnoise, Prot, Sim, SimCurveResults)

leg = {};
if ~isempty(MTdata)
    semilogx(Prot.Offsets, MTdata,'kx', 'MarkerSize', 8); hold on;
    leg{1} = 'Raw data';
end
if (Sim.Opt.AddNoise)
    semilogx(Prot.Offsets, MTnoise,'bo','MarkerSize',8);
end

semilogx(SimCurveResults.Offsets, SimCurveResults.curve, 'LineWidth', 2);

if (Sim.Opt.AddNoise)
   leg{2} = 'Noisy data';
end

nAngles  = size(SimCurveResults.curve,2);
nOffsets = length(Prot.Offsets)/nAngles;
for i = 1:nAngles
    if Prot.Angles(1) == Prot.Angles(2)
        leg{end+1} = sprintf('Fitted curve (angle = %0.0f)',Prot.Angles(nOffsets*i));
    else
        leg{end+1} = sprintf('Fitted curve (angle = %0.0f)',Prot.Angles(i));
    end
end

if ~moxunit_util_platform_is_octave
    hleg = legend(leg, 'FontSize', 12);
    legend('boxoff')
    set(hleg,'Location', 'best')
else
    hleg = legend(leg);
    set(hleg,'FontSize',8)
    set(hleg,'location', 'southeast')
end
xlabel('Offset (Hz)','FontWeight','bold','FontSize',10);
ylabel('|Mz|','FontWeight','bold','FontSize',10);

set(gca, 'XScale', 'log');


function [scd] = ft_scalpcurrentdensity(cfg, data)

% FT_SCALPCURRENTDENSITY computes an estimate of the SCD using the
% second-order derivative (the surface Laplacian) of the EEG potential
% distribution
%
% The relation between the surface Laplacian and the SCD is explained
% in more detail on http://tinyurl.com/ptovowl.
%
% Use as
%   [data] = ft_scalpcurrentdensity(cfg, data)
% or
%   [timelock] = ft_scalpcurrentdensity(cfg, timelock)
% where the input data is obtained from FT_PREPROCESSING or from
% FT_TIMELOCKANALYSIS. The output data has the same format as the input
% and can be used in combination with most other FieldTrip functions
% such as FT_FREQNALYSIS or FT_TOPOPLOTER.
%
% The configuration should contain
%   cfg.method       = 'finite' for finite-difference method or
%                      'spline' for spherical spline method
%                      'hjorth' for Hjorth approximation method
%   cfg.elec         = structure with electrode positions or filename, see FT_READ_SENS
%   cfg.trials       = 'all' or a selection given as a 1xN vector (default = 'all')
%   cfg.feedback     = string, 'no', 'text', 'textbar', 'gui' (default = 'text')
%
% The finite method require the following
%   cfg.conductivity = conductivity of the skin (default = 0.33 S/m)
%
% The spline and finite method require the following
%   cfg.conductivity = conductivity of the skin (default = 0.33 S/m)
%   cfg.lambda       = regularization parameter (default = 1e-05)
%   cfg.order        = order of the splines (default = 4)
%   cfg.degree       = degree of legendre polynomials (default for
%                       <=32 electrodes  = 9,
%                       <=64 electrodes  = 14,
%                       <=128 electrodes = 20,
%                       else             = 32
%
% The hjorth method requires the following
%   cfg.neighbours   = neighbourhood structure, see FT_PREPARE_NEIGHBOURS
%
% For the spline method you can specify the following
%   cfg.badchannel      = cell-array, see FT_CHANNELSELECTION for details (default = [])
%
% Note that the skin conductivity, electrode dimensions and the potential
% all have to be expressed in the same SI units, otherwise the units of
% the SCD values are not scaled correctly. The spatial distribution still
% will be correct.
%
% To facilitate data-handling and distributed computing you can use
%   cfg.inputfile   =  ...
%   cfg.outputfile  =  ...
% If you specify one of these (or both) the input data will be read from a *.mat
% file on disk and/or the output data will be written to a *.mat file. These mat
% files should contain only a single variable, corresponding with the
% input/output structure.
%
% The 'finite' method implements
%   TF Oostendorp, A van Oosterom; The surface Laplacian of the potential:
%   theory and application. IEEE Trans Biomed Eng, 43(4): 394-405, 1996.
%   G Huiskamp; Difference formulas for the surface Laplacian on a
%   triangulated sphere. Journal of Computational Physics, 2(95): 477-496,
%   1991.
%
% The 'spline' method implements
%   F. Perrin, J. Pernier, O. Bertrand, and J. F. Echallier.
%   Spherical splines for scalp potential and curernt density mapping.
%   Electroencephalogr Clin Neurophysiol, 72:184-187, 1989
% including their corrections in
%   F. Perrin, J. Pernier, O. Bertrand, and J. F. Echallier.
%   Corrigenda: EEG 02274, Electroencephalography and Clinical
%   Neurophysiology 76:565.
%
% The 'hjorth' method implements
%   B. Hjort; An on-line transformation of EEG scalp potentials into
%   orthogonal source derivation. Electroencephalography and Clinical
%   Neurophysiology 39:526-530, 1975.
%
% See also FT_PREPROCESSING, FT_TIMELOCKANALYSIS, FT_FREQNALYSIS, FT_TOPOPLOTER.

% Copyright (C) 2004-2012, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble debug
ft_preamble loadvar data
ft_preamble provenance data

% the ft_abort variable is set to true or false in ft_preamble_init
if ft_abort
  return
end

% check if the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'forbidden',  {'trial'}); % prevent accidental typos, see issue 1729

% set the defaults
cfg.method          = ft_getopt(cfg, 'method',       'spline');
cfg.conductivity    = ft_getopt(cfg, 'conductivity', 0.33); % in S/m
cfg.trials          = ft_getopt(cfg, 'trials',       'all', 1);
cfg.feedback        = ft_getopt(cfg, 'feedback',     'text');
cfg.badchannel      = ft_getopt(cfg, 'badchannel',     {});

switch cfg.method
  case 'hjorth'
    cfg = ft_checkconfig(cfg, 'required', {'neighbours'});
  case 'spline'
    cfg.lambda  = ft_getopt(cfg, 'lambda', 1e-5);
    cfg.order   = ft_getopt(cfg, 'order', 4);
    cfg.degree  = ft_getopt(cfg, 'degree', []);

    if isempty(cfg.degree) % determines degree of Legendre polynomials bases on number of electrodes
      nchan = numel(data.label);
      if nchan<=32
        cfg.degree = 9;
      elseif nchan<=64
        cfg.degree = 14;
      elseif nchan<=128
        cfg.degree = 20;
      else
        cfg.degree = 32;
      end
    end
  otherwise
    cfg = ft_checkconfig(cfg); % perform a simple consistency check
end

% store original datatype
dtype = ft_datatype(data);

% check if the input data is valid for this function
data = ft_checkdata(data, 'datatype', 'raw', 'feedback', 'yes', 'ismeg', []);

% get the electrode positions
tmpcfg = cfg;
tmpcfg.senstype = 'EEG';
elec = ft_fetch_sens(tmpcfg, data);

% select channels and trials of interest
tmpcfg = keepfields(cfg, {'trials', 'showcallinfo', 'trackcallinfo', 'trackusage', 'trackdatainfo', 'trackmeminfo', 'tracktimeinfo', 'checksize'});
tmpcfg.channel = elec.label;
data = ft_selectdata(tmpcfg, data);
% restore the provenance information
[cfg, data] = rollback_provenance(cfg, data);

Ntrials = numel(data.trial);

if isempty(cfg.badchannel)
  % check if the first sample of the first trial contains NaNs; if so treat it as a bad channel
  cfg.badchannel = ft_channelselection(find(isnan(data.trial{1}(:,1))), data.label);
end

% match the order of the data channels with the channel positions, order them according to the data
[datindx, elecindx] = match_str(data.label, elec.label);
[goodindx, tmp]     = match_str(data.label, setdiff(data.label, cfg.badchannel, 'stable'));

if ~isempty(cfg.badchannel)
  ft_info('detected channel %s as bad\n', cfg.badchannel{:});
  tmpcfg         = [];
  tmpcfg.channel = data.label(goodindx);
  data           = ft_selectdata(tmpcfg, data);
end

allchanpos  = elec.chanpos(elecindx,:); % the position of all channels, ordered according to the data
goodchanpos = allchanpos(goodindx,:);   % the position of good channels

% compute SCD for each trial
if strcmp(cfg.method, 'spline')
  fprintf('Checking spherical fit... ');
  [c, r] = fitsphere(allchanpos);
  d = allchanpos - repmat(c, size(allchanpos,1), 1);
  d = sqrt(sum(d.^2, 2));
  d = mean(abs(d) / r);
  if abs(d-1) > 0.1
    ft_warning('bad spherical fit (residual: %.2f%%). The interpolation will be inaccurate.', 100*(d-1));
  elseif abs(d-1) < 0.01
    fprintf('perfect spherical fit (residual: %.1f%%)\n', 100*(d-1));
  else
    fprintf('good spherical fit (residual: %.1f%%)\n', 100*(d-1));
  end
  % Builds the spatial filter only once.
  fprintf('Calculating the filter to build the SCD.\n');
  [WVo, WLo] = sphsplint(goodchanpos, allchanpos, cfg.order, cfg.degree, cfg.lambda);
  % Creates a montage to apply the spatial filter.
  montage.tra      = WLo;
  montage.labelold = elec.label(elecindx(goodindx));
  montage.labelnew = elec.label(elecindx);
  % Applies the montage to both the data and electrode definition
  scd  = ft_apply_montage(data, montage);
  elec = ft_apply_montage(elec, montage);

elseif strcmp(cfg.method, 'finite')
  if ~isempty(cfg.badchannel)
    ft_error('the method "%s" does not support the specification of bad channels', cfg.method);
  end
  % the finite difference approach requires a triangulation
  prj = elproj(allchanpos);
  tri = delaunay(prj(:,1), prj(:,2));
  % the new electrode montage only needs to be computed once for all trials
  montage.tra = lapcal(allchanpos, tri);
  montage.labelold = data.label;
  montage.labelnew = data.label;
  % apply the montage to the data, also update the electrode definition
  scd  = ft_apply_montage(data, montage);
  elec = ft_apply_montage(elec, montage);

elseif strcmp(cfg.method, 'hjorth')
  if ~isempty(cfg.badchannel)
    ft_error('the method "%s" does not support the specification of bad channels', cfg.method);
  end
  % convert the neighbourhood structure into a montage
  labelnew = {};
  labelold = {};
  for i=1:length(cfg.neighbours)
    labelnew = cat(2, labelnew, cfg.neighbours(i).label);
    labelold = cat(2, labelold, cfg.neighbours(i).neighblabel(:)');
  end
  labelold = cat(2, labelnew, labelold);
  labelold = unique(labelold);
  tra = zeros(length(labelnew), length(labelold));
  for i=1:length(cfg.neighbours)
    thischan   = match_str(labelold, cfg.neighbours(i).label);
    thisneighb = match_str(labelold, cfg.neighbours(i).neighblabel);
    tra(i, thischan) = 1;
    tra(i, thisneighb) = -1/length(thisneighb);
  end
  % combine it in a montage
  montage.tra = tra;
  montage.labelold = labelold;
  montage.labelnew = labelnew;
  % apply the montage to the data, also update the electrode definition
  scd  = ft_apply_montage(data, montage);
  elec = ft_apply_montage(elec, montage);

else
  ft_error('unknown method "%s"', cfg.method);
end

if strcmp(cfg.method, 'spline') || strcmp(cfg.method, 'finite')
  % correct the units
  ft_warning('trying to correct the units, assuming uV and mm');
  for trlop=1:Ntrials
    % The surface laplacian is proportional to potential divided by squared distance which means that, if
    % - input potential is in uV, which is 10^6 too large
    % - units of electrode positions are in mm, which is 10^3 too large
    % these two cancel out against each other. Hence the computed laplacian
    % is in SI units (MKS).
    scd.trial{trlop} = cfg.conductivity * -1 * scd.trial{trlop};
  end
  fprintf('output surface laplacian is in V/m^2\n');
else
  fprintf('output Hjorth filtered potential is in uV\n');
end

% Adds the electrode definition to the data.
scd.elec = elec;

% convert back to input type if necessary
switch dtype
  case 'timelock'
    scd = ft_checkdata(scd, 'datatype', 'timelock');
  otherwise
    % keep the output as it is
end

% do the general cleanup and bookkeeping at the end of the function
ft_postamble debug
ft_postamble previous data

% rename the output variable to accomodate the savevar postamble
data = scd;

ft_postamble provenance data
ft_postamble history    data
ft_postamble savevar    data


%cropRectanglesMex crops multiple bounding boxes from the initial image and resizes them to the standard output size.
% The operation is performed on a GPU using NVIDIA Performance Primitives (NPP) library
% cropRectanglesMex was created to prepare batches for training CNNs using MatConvNet (http://www.vlfeat.org/matconvnet/).
%
% Usage:
% crops = cropRectanglesMex( im, boundingBoxes, outputSize);
%
% Inputs:
% im  - the image to crop from, should be a 3 channel image (dimension order: height, width, channels) of type single.
%        Normalization (e.g. [0,1] or [0, 255]) is not important. The image should be stored in RAM (not GPU).
% boundingBoxes - bounding boxes to crop, double[ numBoundingBoxes x 4 ], each line corresponds to one bounding box.
%       The bounding box format is y1, x1, y2, x2, where the origin is in the top-left corner.
%       Pixels are indexed starting from 1 (e.g. [1 1 2 2] corresponds to the box containing the 4 top-left pixels of the image).
%       Bounding boxes can be partially outside of the image. The default value for filling such areas is 0 in all the channels.
% outputSize - the target size of the resized crops, double[2 x 1]. outputSize(1) - the height, outputSize(2) - the width.
%
% Outputs:
% crops - the cropped and resized patches, gpuArray, single[ outputSize(1), outputSize(2), numChannels = 3, numBoundingBoxes ]
%
% The function can be compiled using build_cropResizeMex.m.
% example_cropRectanglesMex.m provides the example of usage

% Anton Osokin, firstname.lastname@gmail.com, March 2015


function [im] = imgRead(iid,format)
% function [im] = imgRead(iid,format)

if nargin<2, format='color'; end

im = double(imread(imgFilename(iid))) / 255;

if strcmp(format,'gray'),
  im = rgb2gray(im);
end


function [uOutput] = import_KJRelm(nFunction, sFilename)

% Filter function switchyard
if nFunction == FilterOp.getDescription
  uOutput = 'RELM - Kagan & Jackson PDE-based catalog';
elseif nFunction == FilterOp.importCatalog
  % Read formated data
  mData = textread(sFilename, '%s', 'delimiter', '\n', 'whitespace', '');
  % Create empty catalog
  uOutput = zeros(length(mData), 9);
  % Loop thru all lines of catalog and convert them
  for i = 1:length(mData)
    if rem(i,100) == 0 ; disp([ num2str(i) ' of ' num2str(length(mData)) ' events processed ']); end
    try
      uOutput(i,1) = str2num(mData{i}(33:40));  % Longitude
      uOutput(i,2) = str2num(mData{i}(25:31));  % Latitude
      uOutput(i,3) = str2num(mData{i}(7:10));   % Year
      uOutput(i,4) = str2num(mData{i}(12:13));  % Month
      uOutput(i,5) = str2num(mData{i}(15:16));  % Day
      uOutput(i,6) = str2num(mData{i}(59:62));  % Magnitude
      uOutput(i,7) = str2num(mData{i}(53:57));  % Depth
      uOutput(i,8) = str2num(mData{i}(19:20));  % Hour
      uOutput(i,9) = str2num(mData{i}(22:23));  % Minute
      %Create decimal year
      uOutput(i,3) = decyear([uOutput(i,3) uOutput(i,4) uOutput(i,5) uOutput(i,8) uOutput(i,9)]);
    catch
      msg.dbfprintf('Import: Problem in line %d of %s. Line ignored.\n',i, sFilename);
      uOutput(i,:)=nan;
    end
  end
  l = isnan(uOutput(:,1));
  uOutput(l,:) = [];
end


function checkPropLevelsWarningsErrors(stateLog, celBodyData)
%checkPropLevelsWarningsErrors Summary of this function goes here
%   Detailed explanation goes here
    chunkedStateLog = breakStateLogIntoSoIChunks(stateLog);

    lowFuelOxEventsBodiesWarn = zeros(0,2);
    lowMonopropEventsBodiesWarn = zeros(0,2);
    lowXenonEventsBodiesWarn = zeros(0,2);

    lowFuelOxEventsBodiesAlert = zeros(0,2);
    lowMonopropEventsBodiesAlert = zeros(0,2);
    lowXenonEventsBodiesAlert = zeros(0,2);

    minWarnThresh = 0.1;
    minAlertThresh = 0.01;

    iniState = stateLog(1,:);
    iniFuelOx = iniState(10);
    iniMono = iniState(11);
    iniXenon = iniState(12);

    for(i=1:size(chunkedStateLog,1)) %#ok<*NO4LP>
        for(j=1:size(chunkedStateLog,2))
            subLog = chunkedStateLog{i,j};

            if(isempty(subLog) || (size(subLog,1)==0 || size(subLog,2)==0))
                continue;
            end

            state = subLog(end,:);

            bodyID = state(8);
            %bodyInfo = getBodyInfoByNumber(bodyID, celBodyData);
            eventNum = state(13);

            fuelOx = state(10);
            monoprop = state(11);
            xenon = state(12);

            if(fuelOx / iniFuelOx <= minWarnThresh && fuelOx / iniFuelOx > minAlertThresh)
                lowFuelOxEventsBodiesWarn(end+1,:) = [eventNum, bodyID];
            elseif(fuelOx / iniFuelOx < minAlertThresh)
                lowFuelOxEventsBodiesAlert(end+1,:) = [eventNum, bodyID];
            end

            if(monoprop / iniMono <= minWarnThresh && monoprop / iniMono > minAlertThresh)
                lowMonopropEventsBodiesWarn(end+1,:) = [eventNum, bodyID];
            elseif(monoprop / iniMono < minAlertThresh)
                lowMonopropEventsBodiesAlert(end+1,:) = [eventNum, bodyID];
            end

            if(xenon / iniXenon <= minWarnThresh && xenon / iniXenon > minAlertThresh)
                lowXenonEventsBodiesWarn(end+1,:) = [eventNum, bodyID];
            elseif(xenon / iniXenon < minAlertThresh)
                lowXenonEventsBodiesAlert(end+1,:) = [eventNum, bodyID];
            end
        end
    end

    if(~isempty(lowFuelOxEventsBodiesAlert))
        eventNum = lowFuelOxEventsBodiesAlert(1,1);
        bodyID = lowFuelOxEventsBodiesAlert(1,2);
        addToExecutionErrors(['Low Fuel/Ox Alert (Events: ', makeEventsStr(lowFuelOxEventsBodiesAlert), ')'], -1, -1, celBodyData);
    end

    if(~isempty(lowFuelOxEventsBodiesWarn))
        eventNum = lowFuelOxEventsBodiesWarn(1,1);
        bodyID = lowFuelOxEventsBodiesWarn(1,2);
        C = setdiff(lowFuelOxEventsBodiesWarn,lowFuelOxEventsBodiesAlert,'rows');
        addToExecutionWarnings(['Low Fuel/Ox Warning (Events: ', makeEventsStr(C), ')'], -1, -1, celBodyData);
    end

    if(~isempty(lowMonopropEventsBodiesAlert))
        eventNum = lowMonopropEventsBodiesAlert(1,1);
        bodyID = lowMonopropEventsBodiesAlert(1,2);
        addToExecutionErrors(['Low Monoprop Alert (Events: ', makeEventsStr(lowMonopropEventsBodiesAlert), ')'], -1, -1, celBodyData);
    end

    if(~isempty(lowMonopropEventsBodiesWarn))
        eventNum = lowMonopropEventsBodiesWarn(1,1);
        bodyID = lowMonopropEventsBodiesWarn(1,2);
        C = setdiff(lowMonopropEventsBodiesWarn,lowMonopropEventsBodiesAlert,'rows');
        addToExecutionWarnings(['Low Monoprop Warning (Events: ', makeEventsStr(C), ')'], -1, -1, celBodyData);
    end

    if(~isempty(lowXenonEventsBodiesAlert))
        eventNum = lowXenonEventsBodiesAlert(1,1);
        bodyID = lowXenonEventsBodiesAlert(1,2);
        addToExecutionErrors(['Low Xenon Alert (Events: ', makeEventsStr(lowXenonEventsBodiesAlert), ')'], -1, -1, celBodyData);
    end

    if(~isempty(lowXenonEventsBodiesWarn))
        eventNum = lowXenonEventsBodiesWarn(1,1);
        bodyID = lowXenonEventsBodiesWarn(1,2);
        C = setdiff(lowXenonEventsBodiesWarn,lowXenonEventsBodiesAlert,'rows');
        addToExecutionWarnings(['Low Xenon Warning (Events: ', makeEventsStr(C), ')'], -1, -1, celBodyData);
    end
end

function str = makeEventsStr(eventsBodies)
    eventNums = unique(eventsBodies(:,1));
    str = '';
    for(i=1:length(eventNums))
        if(i==length(eventNums))
            endChar = '';
        else
            endChar = ', ';
        end

        str = [str, num2str(eventNums(i)),endChar];
    end
end


%  Matlab (MatConvNet) implementation of our paper
%  DFM: A Performance Baseline for Deep Feature Matching
%  at CVPR 2021 Image Matching Workshop.
%
%  See details at https://github.com/ufukefe/DFM
%
% @authors: ufukefe, kutalmisince
% Created on March 23, 2021
% @Middle East Technical University, Center for Image Analysis
%  Last Edited on July 1, 2021

function [pointsA, pointsB] = DFM_VGG_stage1(imgA, imgB, model, ratios)

    resize_coeff_A = 1;
    resize_coeff_B = 1;
    % Check the image size
    if size(imgA,1)>1600 || size(imgA,2)>1600
        resize_coeff_A = 1600/max(size(imgA,1),size(imgA,2));
        imgA = imresize(imgA,resize_coeff_A);
    end

    if size(imgB,1)>1600 || size(imgB,2)>1600
        resize_coeff_B = 1600/max(size(imgB,1),size(imgB,2));
        imgB = imresize(imgB,resize_coeff_B);
    end

    size_org_A = size(imgA);
    size_org_B = size(imgB);

    % Normalize Images
    imgA = single(imgA);
    imgA = bsxfun(@minus, imgA, model.meta.normalization.averageImage);

    imgB = single(imgB);
    imgB = bsxfun(@minus, imgB, model.meta.normalization.averageImage);

    % zero padding for vgg (canvas should be a multiple of 16)
    imgA = ZeroPadding4VGG(imgA);
    imgB = ZeroPadding4VGG(imgB);

    % Assign layers to be used
    layers_to_use_A = {'conv5_2';'conv4_2';'conv3_2';'conv2_2';'conv1_2'};
    layers_to_use_B = {'conv5_2';'conv4_2';'conv3_2';'conv2_2';'conv1_2'};
    model = ArrangeNetwork(model,layers_to_use_A);

    % Assign ratio tests for layers
    ratios_s1 = ratios(5:-1:1);

    % get activations
    activationsA = GetActivations(imgA, model, layers_to_use_A);
    activationsB = GetActivations(imgB, model, layers_to_use_B);

    % initiate matches
    [pointsA, pointsB] = DenseFeatureMatching(activationsA{1,2}, activationsB{1,2},ratios_s1(1));
    [pointsA, pointsB] = insideImage(pointsA,pointsB,size_org_A,size_org_B,16);

    for k = 2:5
        [pointsA, pointsB] = RefinePoints(pointsA, pointsB, activationsA{k,2}, activationsB{k,2}, ratios_s1(k));
    end

    % Reject matches at the side of the images
    [pointsA,pointsB] = rejectSideMatches(pointsA,pointsB,size_org_A,size_org_B,16);

    if resize_coeff_A ~= 1
       pointsA = (1/resize_coeff_A)*(pointsA-0.5)+0.5;
    end

    if resize_coeff_B ~= 1
       pointsB = (1/resize_coeff_B)*(pointsB-0.5)+0.5;
    end

end