function varargout = ReadData3D(varargin)
% This function ReadData3D allows the user to open medical 3D files. It
% supports the following formats :
%
%   Dicom Files ( .dcm , .dicom )
%   V3D Philips Scanner ( .v3d )
%   GIPL Guys Image Processing Lab ( .gipl )
%   HDR/IMG Analyze ( .hdr )
%   ISI Files ( .isi )
%   NifTi ( .nii )
%   RAW files ( .raw , .* )
%   VMP BrainVoyager ( .vmp )
%   XIF HDllab/ATL ultrasound ( .xif )
%   VTK Visualization Toolkit ( .vtk )
%   Insight Meta-Image ( .mha, .mhd )
%   Micro CT ( .vff )
%   PAR/REC Philips ( .par, .rec)
%
% usage:
%
% [V,info]=ReadData3D;
%
% or,
%
% [V,info]=ReadData3D(filename)
%
% or,
%
% [V,info]=ReadData3D(filename,real);
%
%
% outputs,
%   V : The 3D Volume
%   info : Struct with info about the data
%        Always the following fields are present
%        info.Filename : Name of file
%        info.Dimensions : Dimensions of Volume
%        info.PixelDimensions : Size of one pixel / voxel
%   real : If set to true (default), convert the raw data to
%        type Single-precision  and rescale data to real units
%        (in CT Hounsfield). When false, it returns the raw-data.
%
% Warning!
%  The read functions are not fully implemented as defined in
%  the file-format standards. thus do not use this function for
%  critical applications.
%
%
% Function is written by D.Kroon University of Twente (July 2010)

% Edit the above text to modify the response to help ReadData3D

% Last Modified by GUIDE v2.5 09-Nov-2010 14:12:50

% Begin initialization code - DO NOT EDIT
gui_Singleton = 0;
gui_State = struct('gui_Name',       mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @ReadData3D_OpeningFcn, ...
    'gui_OutputFcn',  @ReadData3D_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);
if (nargin>2) && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before ReadData3D is made visible.
function ReadData3D_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to ReadData3D (see VARARGIN)

% Choose default command line output for ReadData3D
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes ReadData3D wait for user response (see UIRESUME)
% uiwait(handles.figure1);

%---- Start supported file formats ----%
data.fileformat(1).ext='*.dcm';
data.fileformat(1).type='Dicom Files';
data.fileformat(1).folder='dicom';
data.fileformat(1).functioninfo='dicom_read_header';
data.fileformat(1).functionread='dicom_read_volume';

data.fileformat(2).ext='*.gipl';
data.fileformat(2).type='GIPL Guys Image Processing Lab';
data.fileformat(2).folder='gipl';
data.fileformat(2).functioninfo='gipl_read_header';
data.fileformat(2).functionread='gipl_read_volume';

data.fileformat(3).ext='*.hdr';
data.fileformat(3).type='HDR/IMG Analyze';
data.fileformat(3).folder='hdr';
data.fileformat(3).functioninfo='hdr_read_header';
data.fileformat(3).functionread='hdr_read_volume';

data.fileformat(4).ext='*.isi';
data.fileformat(4).type='ISI Files';
data.fileformat(4).folder='isi';
data.fileformat(4).functioninfo='isi_read_header';
data.fileformat(4).functionread='isi_read_volume';

data.fileformat(5).ext='*.nii';
data.fileformat(5).type='NifTi';
data.fileformat(5).folder='nii';
data.fileformat(5).functioninfo='nii_read_header';
data.fileformat(5).functionread='nii_read_volume';

data.fileformat(6).ext='*.raw';
data.fileformat(6).type='RAW files';
data.fileformat(6).folder='raw';
data.fileformat(6).functioninfo='raw_read_header';
data.fileformat(6).functionread='raw_read_volume';

data.fileformat(7).ext='*.v3d';
data.fileformat(7).type='V3D Philips Scanner';
data.fileformat(7).folder='v3d';
data.fileformat(7).functioninfo='v3d_read_header';
data.fileformat(7).functionread='v3d_read_volume';

data.fileformat(8).ext='*.vmp';
data.fileformat(8).type='VMP BrainVoyager';
data.fileformat(8).folder='vmp';
data.fileformat(8).functioninfo='vmp_read_header';
data.fileformat(8).functionread='vmp_read_volume';

data.fileformat(9).ext='*.xif';
data.fileformat(9).type='XIF HDllab/ATL ultrasound';
data.fileformat(9).folder='xif';
data.fileformat(9).functioninfo='xif_read_header';
data.fileformat(9).functionread='xif_read_volume';

data.fileformat(10).ext='*.vtk';
data.fileformat(10).type='VTK Visualization Toolkit';
data.fileformat(10).folder='vtk';
data.fileformat(10).functioninfo='vtk_read_header';
data.fileformat(10).functionread='vtk_read_volume';

data.fileformat(11).ext='*.mha';
data.fileformat(11).type='Insight Meta-Image';
data.fileformat(11).folder='mha';
data.fileformat(11).functioninfo='mha_read_header';
data.fileformat(11).functionread='mha_read_volume';

data.fileformat(12).ext='*.vff';
data.fileformat(12).type='Micro CT';
data.fileformat(12).folder='vff';
data.fileformat(12).functioninfo='vff_read_header';
data.fileformat(12).functionread='vff_read_volume';

data.fileformat(13).ext='*.par';
data.fileformat(13).type='Philips PAR/REC';
data.fileformat(13).folder='par';
data.fileformat(13).functioninfo='par_read_header';
data.fileformat(13).functionread='par_read_volume';

%---- End supported file formats ----%

% Get path of ReadData3D
functionname='ReadData3D.m';
functiondir=which(functionname);
functiondir=functiondir(1:end-length(functionname));

% Add the file-reader functions also to the matlab path
addpath([functiondir '/subfunctions']);
for i=1:length(data.fileformat), addpath(fullfile(functiondir, data.fileformat(i).folder)); end

% Make popuplist file formats
fileformatcell=cell(1,length(data.fileformat));
for i=1:length(data.fileformat), fileformatcell{i}=[data.fileformat(i).type '   (' data.fileformat(i).ext ')']; end
set(handles.popupmenu_format,'String',fileformatcell);

% Check if last filename is present from a previous time
data.configfile=[functiondir '/lastfile.mat'];
filename='';
fileformatid=1;
if(exist(data.configfile,'file')), load(data.configfile); end
data.handles=handles;
data.lastfilename=[];
data.volume=[];
data.info=[];

% If filename is selected, look if the extention is known
found=0;
if(~isempty(varargin))
    filename=varargin{1}; [pathstr,name,ext]=fileparts(filename);
    for i=1:length(data.fileformat)
        if(strcmp(data.fileformat(i).ext(2:end),ext)), found=1; fileformatid=i; end
    end
end

% Rescale the databack to original units.
if(length(varargin)>1), real=varargin{2}; else real=true; end

data.real=real;
data.filename=filename;
data.fileformatid=fileformatid;

set(handles.checkbox_real,'Value',data.real);
set(handles.edit_filename,'String',data.filename)
set(handles.popupmenu_format,'Value',data.fileformatid);

% Store all data
setMyData(data);

if(found==0)
    % Show Dialog File selection
    uiwait(handles.figure1);
else
    % Load the File directly
    loaddata();
end

% --- Outputs from this function are returned to the command line.
function varargout = ReadData3D_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
if(ishandle(hObject))
    data=getMyData();
else
    data=[];
end
if(~isempty(data))
    varargout{1} = data.volume;
    varargout{2} = data.info;
else
    varargout{1}=[];
    varargout{2}=[];
end
if(ishandle(hObject))
    close(hObject)
end

function edit_filename_Callback(hObject, eventdata, handles)
% hObject    handle to edit_filename (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of edit_filename as text
%        str2double(get(hObject,'String')) returns contents of edit_filename as a double

% --- Executes during object creation, after setting all properties.
function edit_filename_CreateFcn(hObject, eventdata, handles)
% hObject    handle to edit_filename (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in pushbutton_browse.
function pushbutton_browse_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_browse (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
data=getMyData();
[extlist extlistid]=FileDialogExtentionList(data);
[filename, dirname,filterindex] = uigetfile(extlist, 'Select a dicom file',fileparts(data.filename));
if(filterindex>0)
    if(extlistid(filterindex)~=0)
        data.fileformatid=extlistid(filterindex);
        set( handles.popupmenu_format,'Value',data.fileformatid);
    end
    if(filename==0), return; end
    filename=[dirname filename];
    data.filename=filename;
    setMyData(data);
    set(handles.edit_filename,'String',data.filename)
end

function [extlist extlistid]=FileDialogExtentionList(data)
extlist=cell(length(data.fileformat)+1,2);
extlistid=zeros(length(data.fileformat)+1,1);
ext=data.fileformat(data.fileformatid).ext;
type=data.fileformat(data.fileformatid).type;
extlistid(1)=data.fileformatid;
extlist{1,1}=ext; extlist{1,2}=[type ' (' ext ')'];
j=1;
for i=1:length(data.fileformat);
    if(i~=data.fileformatid)
        j=j+1;
        ext=data.fileformat(i).ext;
        type=data.fileformat(i).type;
        extlistid(j)=i;
        extlist{j,1}=ext; extlist{j,2}=[type ' (' ext ')'];
    end
end
extlist{end,1}='*.*';
extlist{end,2}='All Files (*.*)';

function setMyData(data)
% Store data struct in figure
setappdata(gcf,'dataload3d',data);

function data=getMyData()
% Get data struct stored in figure
data=getappdata(gcf,'dataload3d');

% --- Executes on button press in pushbutton_cancel.
function pushbutton_cancel_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_cancel (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
setMyData([]);
uiresume;

% --- Executes on selection change in popupmenu_format.
function popupmenu_format_Callback(hObject, eventdata, handles)
% hObject    handle to popupmenu_format (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns popupmenu_format contents as cell array
%        contents{get(hObject,'Value')} returns selected item from popupmenu_format
data=getMyData();
data.fileformatid=get( handles.popupmenu_format,'Value');
setMyData(data);

% --- Executes during object creation, after setting all properties.
function popupmenu_format_CreateFcn(hObject, eventdata, handles)
% hObject    handle to popupmenu_format (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in pushbutton_load.
function pushbutton_load_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_load (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
data=getMyData();
data.filename=get(handles.edit_filename,'string');
loaddata();
pause(0.1);
uiresume

function loaddata()
data=getMyData();
set(data.handles.figure1,'Pointer','watch'); drawnow('expose');
if(~strcmp(data.lastfilename,data.filename))
    % Get info
    fhandle = str2func( data.fileformat(data.fileformatid).functioninfo);
    data.info=feval(fhandle,data.filename);
    data.lastfilename=data.filename;
end
fhandle = str2func( data.fileformat(data.fileformatid).functionread);
data.volume=feval(fhandle,data.info);
if(data.real)
    data.volume=single(data.volume);
    if(isfield(data.info,'RescaleSlope')),
        data.volume=data.volume*data.info.RescaleSlope;
    else
        disp('RescaleSlope not available, assuming 1')
    end
    if(isfield(data.info,'RescaleIntercept')),
        data.volume=data.volume+data.info.RescaleIntercept;
    else
        disp('RescaleIntercept not available, assuming 0')
    end
end
setMyData(data);
set(data.handles.figure1,'Pointer','arrow')

% Save the filename, for the next time this function is used
filename=data.filename; fileformatid=data.fileformatid;
try save(data.configfile,'filename','fileformatid'); catch ME; disp(ME.message); end

% --- Executes on button press in pushbutton_info.
function pushbutton_info_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton_info (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
data=getMyData();
data.filename=get(handles.edit_filename,'string');
if(~strcmp(data.lastfilename,data.filename))
    % Get info
    set(data.handles.figure1,'Pointer','watch'); drawnow('expose');
    fhandle = str2func( data.fileformat(data.fileformatid).functioninfo);
    data.info=feval(fhandle,data.filename);
    data.lastfilename=data.filename;
    set(data.handles.figure1,'Pointer','arrow')
end
setMyData(data);
% Show info
InfoData3D(data.info);

% --- Executes on button press in checkbox_real.
function checkbox_real_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox_real (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox_real
data=getMyData();
data.real=get(handles.checkbox_real,'Value');
setMyData(data);


function x = callback_inpainting(y,dir,options)

% callback_inpainting - callback for inpainting applications
%
%   x = callback_inpainting(y,dir,options);
%
%   You must provide options.mask.
%   The missing pixels (removed) are mask==1.
%
%   Copyright (c) 2008 Gabriel Peyre

mask = getoptions(options, 'mask', [], 1);

x = y;
x(mask==1) = 0;


function varargout=lpczz2cc(varargin)
%
% For calling details please see v_lpczz2cc.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_lpczz2cc.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: lpczz2cc.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_lpczz2cc(varargin{:});
else
    v_lpczz2cc(varargin{:});
end


function h = hline(y, varargin)
%HLINE Easy plotting of a horizonal line.
% Usage:
%   hline
%   hline(y)
%   hline(ax, _)
%   hline(_, ...) % plot args (e.g., linespec)
%   h = hline(_)
%
% Args:
%   y: y-value
%
% See also: vline

if nargin < 1; y = []; end
ax = [];
if isax(y)
    ax = y;
    y = [];
    if nargin > 1
        arg1 = varargin{1};
        if isnumeric(arg1)
            y = arg1;
            varargin(1) = [];
        end
    end
end

if isempty(ax)
    ax = gca;
end

if isempty(y)
    y = mean(ylim(ax));
end

state = ax.NextPlot;
ax.NextPlot = 'add';

X = xlim(ax) .* ones(numel(y),1);
Y = [1 1] .* y(:);
if isvector(y)
    X = [X NaN(size(X,1),1)]';
    Y = [Y NaN(size(Y,1),1)]';
end

h = plot(ax, X(:), Y(:), varargin{:});

ax.NextPlot = state;

if nargout < 1; clear h; end

end


classdef TestPyrUp
    %TestPyrUp

    properties (Constant)
        im = fullfile(mexopencv.root(),'test','img001.jpg');
    end

    methods (Static)
        function test_uint8_img
            img = cv.imread(TestPyrUp.im, 'ReduceScale',2);
            result = cv.pyrUp(img);
        end

        function test_double_img
            img = cv.imread(TestPyrUp.im, 'ReduceScale',2);
            img = double(img) ./ 255;
            result = cv.pyrUp(img);
        end

        function test_custom_size
            img = cv.imread(TestPyrUp.im, 'ReduceScale',2);
            img = img(1:200,1:256,:);
            [h,w,~] = size(img);
            sz = [w,h].*2;
            result = cv.pyrUp(img, 'DstSize',sz);
        end

        function test_error_argnum
            try
                cv.pyrUp();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function result=plotbox(Target,Template,M);
%
%By Alaa Eleyan May,2008
%*********************************************************
[r1,c1]=size(Target);
[r2,c2]=size(Template);

[r,c]=max(M);
[r3,c3]=max(max(M));

i=c(c3);
j=c3;
result=Target;
for x=i:i+r2-1
   for y=j
       result(x,y)=255;
   end
end
for x=i:i+r2-1
   for y=j+c2-1
       result(x,y)=255;
   end
end
for x=i
   for y=j:j+c2-1
       result(x,y)=255;
   end
end
for x=i+r2-1
   for y=j:j+c2-1
       result(x,y)=255;
   end
end


function om = set_params(om, st, name, idx, params, vals)
%SET_PARAMS  Modifies parameters for variable, cost or constraint in model
%
%   This method can be used to modify parameters for an existing variable,
%   constraint or cost in the model.
%
%   OM.SET_PARAMS(SET_TYPE, NAME, PARAMS, VALS)
%   OM.SET_PARAMS(SET_TYPE, NAME, IDX, PARAMS, VALS)
%
%   Inputs:
%       SET_TYPE : one of 'var', 'lin', 'nle', 'nli', 'nlc', 'qdc' for
%           variables, linear constraints, nonlinear equality constraints,
%           nonlinear inequality constraints, general nonlinear costs,
%           and quadratic costs, respectively
%       NAME : name of set
%       IDX : index of named set (for an indexed set)
%       PARAMS : can be one of three options:
%           1 - 'all', indicating that VALS is a cell array whose elements
%               correspond to the input parameters of the respective
%               add_*() method
%           2 - the name of a PARAM, VAL is the value of that parameter
%           3 - a cell array of PARAM names, VALS is a cell array of
%               corresponding values
%           Note: Changing the dimension of a 'var' is not allowed
%               and changing the #1 ('all') is the only option for 'nle', 'nli', and 'nlc'
%       VALS : new value or cell array of new values for PARAMS
%
%   Valid PARAM names:
%       var - N, v0, vl, vu, vt
%       lin - A, l, u, vs
%       nle - N, fcn, hess, include, vs
%       nli - N, fcn, hess, include, vs
%       nlc - N, fcn, vs
%       qdc - Q, c, k, vs
%
%   Examples:
%       om.set_params('var', 'Pg', 'v0', Pg0);
%       om.set_params('lin', 'y', {2,3}, {'l', 'u'}, {l, u});
%       om.set_params('nle', 'Pmis', 'all', {N, @fcn, @hess, vs});
%
%   See also OPT_MODEL, ADD_VAR, ADD_LIN_CONSTRAINT, ADD_NLN_CONSTRAINT
%            ADD_QUAD_COST and ADD_NLN_COST.

%   MP-Opt-Model
%   Copyright (c) 2008-2020, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MP-Opt-Model.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://github.com/MATPOWER/mp-opt-model for more info.

if nargin < 6
    vals = params;
    params = idx;
    idx = {};
end

%% create default list of parameters to update based on set type & inputs
switch st
    case 'var'
        default_params = {'N', 'v0', 'vl', 'vu', 'vt'};
    case 'lin'
        default_params = {'A', 'l', 'u', 'vs'};
    case {'nle', 'nli'}
        default_params = {'N', 'fcn', 'hess', 'vs'};
    case 'nlc'
        default_params = {'N', 'fcn', 'vs'};
    case 'qdc'
        default_params = {'Q', 'c', 'k', 'vs'};
    otherwise
        error('@opt_model/set_params: ''%s'' is not a valid SET_TYPE', st);
end

%% standardize provided arguments in cell arrays params, vals
is_all = 0;     %% flag to indicate all params for set are being replaced
if ischar(params)
    if strcmp(params, 'all')
        is_all = 1;
        np = length(vals);      %% number of parameter values provided
        params = default_params(1:np);
    else
        np = 1;                 %% number of parameter values provided
        params = {params};
        vals = {vals};
    end
else
    np = length(vals);          %% number of parameter values provided
end

if ~isempty(idx)
    %% calls to substruct() are relatively expensive, so we pre-build the
    %% struct for addressing cell array fields
    %% sc = substruct('.', name, '{}', idx);
    sc = struct('type', {'.', '{}'}, 'subs', {name, idx});  %% cell array field
end

switch st
    case 'var'
        %% get current parameters
        [v0, vl, vu, vt] = om.params_var(name, idx);
        N0 = om.getN('var', name, idx);
        p = struct('N', N0, 'v0', v0, 'vl', vl, 'vu', vu, 'vt', vt);    %% current parameters
        u = struct('N',  0, 'v0',  0, 'vl',  0, 'vu',  0, 'vt',  0);    %% which ones to update

        %% replace with new parameters
        for k = 1:np
            p.(params{k}) = vals{k};
            u.(params{k}) = 1;
        end
        N = p.N;

        %% set missing default params for 'all'
        if is_all
            if np < 5
                p.vt = 'C';
                u.vt = 1;               %% update vt
                if np < 4
                    p.vu = Inf(N, 1);
                    u.vu = 1;           %% update vu
                    if np < 3
                        p.vl = -Inf(N, 1);
                        u.vl = 1;       %% update vl
                        if np < 2
                            p.v0 = zeros(N, 1);
                            u.v0 = 1;   %% update v0
                        end
                    end
                end
            end
        end

        %% check consistency of parameters
        %% no dimension change
        if N ~= N0
            error('@opt_model/set_params: dimension change for ''%s'' ''%s'' not allowed', st, nameidxstr(name, idx));
        end

        %% check sizes of new values of v0, vl, vu, vt
        for pn = {'v0', 'vl', 'vu', 'vt'}
            if u.(pn{1})
                nn = length(p.(pn{1}));
                if nn ~= N
                    if nn == 0
                        switch pn{1}
                            case 'v0'
                                p.(pn{1}) = zeros(N, 0);
                            case 'vl'
                                p.(pn{1}) = -Inf(N, 0);
                            case 'vu'
                                p.(pn{1}) =  Inf(N, 0);
                            case 'vt'
                                p.(pn{1}) = 'C';
                        end
                    elseif nn == 1
                        if pn{1} ~= 'vt'
                            p.(pn{1}) = p.(pn{1}) * ones(N, 1);   %% expand from scalar
                        end
                    else
                        error('@opt_model/set_params: parameter ''%s'' ''%s'' ''%s'' should have length %d (or 1)', st, nameidxstr(name, idx), pn{1}, N);
                    end
                end
            end
        end

        %% assign new parameters
        if isempty(idx)     %% simple named set
            for k = 2:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.var.data.(pn).(name) = p.(pn);
                end
            end
        else                %% indexed named set
            for k = 2:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.var.data.(pn) = subsasgn(om.var.data.(pn), sc, p.(pn));
                end
            end
        end
    case 'lin'
        %% get current parameters
        [A, l, u, vs] = om.params_lin_constraint(name, idx);
        [N0, M0] = size(A);
        if isempty(vs), vs = {vs}; end
        p = struct('A', A, 'l', l, 'u', u, 'vs', vs);   %% current parameters
        u = struct('A', 0, 'l', 0, 'u', 0, 'vs',  0);   %% which ones to update

        %% replace with new parameters
        for k = 1:np
            p.(params{k}) = vals{k};
            u.(params{k}) = 1;
        end

        %% set missing default params for 'all'
        [N, M] = size(p.A);
        if is_all
            u.A = 1;            %% always update A
            u.l = 1;            %% alwaus update l
            if np < 4
                p.vs = {};
                u.vs = 1;       %% update vs
                if np < 3
                    p.u = Inf(N, 1);
                    u.u = 1;    %% update u
                end
            end
        end

        %% check consistency of parameters
        %% no dimension change unless 'all'
        if N ~= N0 && ~is_all
            error('@opt_model/set_params: dimension change for ''%s'' ''%s'' not allowed except for ''all''', st, nameidxstr(name, idx));
        end

        %% check sizes of new values of l, u
        for pn = {'l', 'u'}
            if u.(pn{1})
                nn = length(p.(pn{1}));
                if nn ~= N
                    if nn == 0
                        switch pn{1}
                            case 'l'
                                p.(pn{1}) = -Inf(N, 0);
                            case 'u'
                                p.(pn{1}) =  Inf(N, 0);
                        end
                    elseif nn == 1
                        p.(pn{1}) = p.(pn{1}) * ones(N, 1);   %% expand from scalar
                    else
                        error('@opt_model/set_params: parameter ''%s'' ''%s'' ''%s'' should have length %d (or 1)', st, nameidxstr(name, idx), pn{1}, N);
                    end
                end
            end
        end

        %% check consistency of A and vs
        if u.A || u.vs
            p.vs = om.varsets_cell2struct(p.vs);
            nv = om.varsets_len(p.vs);      %% number of variables
            if M ~= nv
                error('@opt_model/set_params: for ''%s'' ''%s'' number of columns of ''A'' (%d) must be consistent with ''vs'' (%d)', st, nameidxstr(name, idx), M, nv);
            end
        end

        %% assign new parameters
        if isempty(idx)     %% simple named set
            for k = 1:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.lin.data.(pn).(name) = p.(pn);
                end
            end
        else                %% indexed named set
            for k = 1:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.lin.data.(pn) = subsasgn(om.lin.data.(pn), sc, p.(pn));
                end
            end
        end
    case 'qdc'
        %% get current parameters
        [Q, c, kk, vs] = om.params_quad_cost(name, idx);
        [MQ0, NQ0] = size(Q);
        [Mc0, Nc0] = size(c);
        Nk0 = length(kk);
        nx0 = max([MQ0 Mc0 Nk0]);
        N0 = om.getN('qdc', name, idx);
        if isempty(vs), vs = {vs}; end
        p = struct('Q', Q, 'c', c, 'k', kk, 'vs', vs);  %% current parameters
        u = struct('Q', 0, 'c', 0, 'k',  0, 'vs',  0);  %% which ones to update

        %% replace with new parameters
        for k = 1:np
            p.(params{k}) = vals{k};
            u.(params{k}) = 1;
        end

        %% set missing default params for 'all'
        [MQ, NQ] = size(p.Q);
        [Mc, Nc] = size(p.c);
        Nk = length(p.k);
        nx = max([MQ Mc Nk]);
        if NQ == 1 || (isempty(p.Q) && (Nk > 1 || k == 0))
            %% Q is a column vector (cost is element-wise, i.e. a vector)
            %% OR Q is empty and k is either a vector or zero
            N = nx;
        else            %% Q is a square matrix (cost is a scalar)
            N = 1;
        end
        if is_all
            u.Q = 1;                %% always update Q
            if np < 4
                p.vs = {};
                u.vs = 1;           %% update vs
                if np < 3
                    p.k = 0;
                    u.k = 1;        %% update k
                    if np < 2
                        p.c = [];
                        u.c = 1;    %% update c
                    end
                end
            end
        end

        %% check consistency of parameters
        %% no dimension change unless 'all'
        if (N ~= N0 || nx ~= nx0) && ~is_all
            error('@opt_model/set_params: dimension change for ''%s'' ''%s'' not allowed except for ''all''', st, nameidxstr(name, idx));
        end

        %% Q and c can't both be empty
        if ~MQ && ~Mc
            error('@opt_model/set_params: ''%s'' ''%s'' : ''Q'' and ''c'' cannot both be empty', st, nameidxstr(name, idx));
        end

        %% check sizes of new values of Q, c, k
        if ~isempty(p.Q) && (MQ ~= nx || (MQ ~= NQ && NQ ~= 1) )
            error('@opt_model/set_params: ''%s'' ''%s'' : ''%s'' is expected to be (%d x %d)', st, nameidxstr(name, idx), 'Q', MQ, NQ);
        end
        if ~isempty(p.c) && Mc ~= nx
            error('@opt_model/set_params: ''%s'' ''%s'' : ''%s'' is expected to be (%d x %d)', st, nameidxstr(name, idx), 'c', Mc, 1);
        end
        if ~isempty(p.k) && any(p.k) && Nk ~= N && Nk ~= 1
            error('@opt_model/set_params: ''%s'' ''%s'' : ''%s'' is expected to be (%d x %d)', st, nameidxstr(name, idx), 'k', N, 1);
        end

        %% check consistency of Q, c, k and vs
        if u.Q || u.c || u.vs
            p.vs = om.varsets_cell2struct(p.vs);
            nv = om.varsets_len(p.vs);      %% number of variables
            if nx ~= nv
                error('@opt_model/set_params: for ''%s'' ''%s'' dimensions of ''Q'', ''c'', ''k'' (%d) must be consistent with ''vs'' (%d)', st, nameidxstr(name, idx), nx, nv);
            end
        end

        %% assign new parameters
        if isempty(idx)     %% simple named set
            for k = 1:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.qdc.data.(pn).(name) = p.(pn);
                end
            end
        else                %% indexed named set
            for k = 1:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.qdc.data.(pn) = subsasgn(om.qdc.data.(pn), sc, p.(pn));
                end
            end
        end
    case {'nle', 'nli'}
        %% get current parameters
        if isempty(idx)
            [N0, fcn, hess, vs, include] = om.params_nln_constraint(st(3) == 'e', name, idx);
        else
            [N0, fcn, hess, vs] = om.params_nln_constraint(st(3) == 'e', name, idx);
            include = '';
        end
        if isempty(vs), vs = {vs}; end
        p = struct('N', N0, 'fcn', fcn, 'hess', hess, 'vs', vs);    %% current parameters
        u = struct('N',  0, 'fcn',   0, 'hess',    0, 'vs',  0);    %% which ones to update

        %% replace with new parameters
        for k = 1:np
            p.(params{k}) = vals{k};
            u.(params{k}) = 1;
        end
        N = p.N;

        %% set missing default params for 'all'
        if is_all
            u.N    = 1;         %% always update N
            u.fcn  = 1;         %% alwaus update fcn
            u.hess = 1;         %% alwaus update hess
            if np < 4
                p.vs = {};
                u.vs = 1;       %% update vs
            end
        end

        %% check consistency of parameters
        %% no dimension change unless 'all'
        if N ~= N0 && ~is_all
            error('@opt_model/set_params: dimension change for ''%s'' ''%s'' not allowed except for ''all''', st, nameidxstr(name, idx));
        end

        %% included constraints not yet implemented
        if ~isempty(include)
            error('@opt_model/set_params: modifications for ''%s'' ''%s'' not (yet) supported since it includes evaluation of other constraints', st, nameidxstr(name, idx));
        end

        %% convert vs to struct
        if u.vs
            p.vs = om.varsets_cell2struct(p.vs);
        end

        %% assign new parameters
        if isempty(idx)     %% simple named set
            for k = 2:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.(st).data.(pn).(name) = p.(pn);
                end
            end
        else                %% indexed named set
            for k = 2:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.(st).data.(pn) = subsasgn(om.(st).data.(pn), sc, p.(pn));
                end
            end
        end
    case 'nlc'
        %% get current parameters
        [N0, fcn, vs] = om.params_nln_cost(name, idx);
        if isempty(vs), vs = {vs}; end
        p = struct('N', N0, 'fcn', fcn, 'vs', vs);  %% current parameters
        u = struct('N',  0, 'fcn',   0, 'vs',  0);  %% which ones to update

        %% replace with new parameters
        for k = 1:np
            p.(params{k}) = vals{k};
            u.(params{k}) = 1;
        end
        N = p.N;

        %% set missing default params for 'all'
        if is_all
            u.N   = 1;          %% always update N
            u.fcn = 1;          %% alwaus update fcn
            if np < 3
                p.vs = {};
                u.vs = 1;       %% update vs
            end
        end

        %% check consistency of parameters
        %% no dimension change unless 'all'
        if N ~= N0 && ~is_all
            error('@opt_model/set_params: dimension change for ''%s'' ''%s'' not allowed except for ''all''', st, nameidxstr(name, idx));
        end

        %% vector valued costs not yet implemented
        if N ~= 1
            error('@opt_model/set_params: vector value for ''%s'' ''%s'' not yet implemented', st, nameidxstr(name, idx));
        end

        %% assign new parameters
        if isempty(idx)     %% simple named set
            for k = 2:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.nlc.data.(pn).(name) = p.(pn);
                end
            end
        else                %% indexed named set
            for k = 2:length(default_params)
                pn = default_params{k};     %% param name
                if u.(pn)   %% assign new val for this parameter
                    om.nlc.data.(pn) = subsasgn(om.nlc.data.(pn), sc, p.(pn));
                end
            end
        end
    otherwise
        error('@opt_model/set_params: ''%s'' is not a valid SET_TYPE', st);
end

%% update dimensions and indexing, if necessary
dN = N - N0;
if is_all && dN
    %% calls to substruct() are relatively expensive, so we pre-build the
    %% struct for addressing num array fields
    %% sn = substruct('.', name, '()', idx);
    sn = struct('type', {'.', '()'}, 'subs', {'', 1});  %% num array field
    om_ff = om.(st);
    update = 0;             %% not yet reached set being updated
    update_i1 = 0;          %% flag to indicate whether to update i1
    for k = 1:om_ff.NS
        o = om_ff.order(k);
        if ~update && strcmp(o.name, name) && isequal(o.idx, idx)
            update = 1;     %% arrived at set being updated
        end
        if update
            if isempty(o.idx)   %% simple named set
                if update_i1
                    om_ff.idx.i1.(o.name) = om_ff.idx.i1.(o.name) + dN;
                else
                    om_ff.idx.N.(o.name) = om_ff.idx.N.(o.name) + dN;
                end
                om_ff.idx.iN.(o.name) = om_ff.idx.iN.(o.name) + dN;
            else                %% indexed named set
                sn(1).subs = o.name;
                sn(2).subs = o.idx;
                if update_i1
                    v = subsref(om_ff.idx.i1, sn);
                    om_ff.idx.i1 = subsasgn(om_ff.idx.i1, sn, v + dN);
                else
                    v = subsref(om_ff.idx.N, sn);
                    om_ff.idx.N = subsasgn(om_ff.idx.N, sn, v + dN);
                end
                v = subsref(om_ff.idx.iN, sn);
                om_ff.idx.iN = subsasgn(om_ff.idx.iN, sn, v + dN);
            end
            update_i1 = 1;  %% update i1 from here on out
        end
    end
    om_ff.N = om_ff.N + dN;
    om.(st) = om_ff;
end

function str = nameidxstr(name, idx)
str = sprintf('%s%s', name, idxstr(idx));

function str = idxstr(idx)
if isempty(idx)
    str = '';
elseif length(idx) == 1
    str = sprintf('(%d)', idx{1});
else
    str = ['(' sprintf('%d', idx{1}) sprintf(',%d', idx{2:end}) ')'];
end


classdef TestCalcBlurriness
    %TestCalcBlurriness

    methods (Static)
        function test_1
            img = imread(fullfile(mexopencv.root(),'test','fruits.jpg'));
            f = cv.calcBlurriness(img);
            validateattributes(f, {'numeric'}, {'scalar', 'real'});
        end

        function test_error_argnum
            try
                cv.calcBlurriness();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function [saveLogic,savePath]=Qsave3DDICPPresults(structPath)
%% function for asking the user for saving options for the 3D-DIC results in STEP3.
% Including overwriting options
%
% INPUTS:
% * structPaths: 1-by-Npairs cell array, containing in each
%   cell the path to the DIC2DpairResults_C_#1_C_#2 structure file
%
% OUTPUTS:
% * saveLogic: logic true=save, false=not save
% * savePath: a path were to save the results. [] if saveLogic=false.

%%
saveButton = questdlg('Save 3D-DIC Post-Processing results?', 'Save?', 'Yes', 'No', 'Yes');

switch saveButton
    case 'Yes'
        saveLogic=true(1);
        continueLog=false(1);

        while ~continueLog
            % Path where to save the camera parameters
            savePath = uigetdir(fileparts(structPath),'Select a folder for saving the results');

            % check if DIC3DpairResults in this folder already exist
            fileExist=false;
            [~,name,~]=fileparts(structPath);
            filenames=[savePath '\DIC3DPPresults.mat'];
            if exist(filenames,'file')
                fileExist=true;
            end

            if fileExist
                promptMessage=cell(2,1);
                promptMessage{1}='The following output file already exists: ';
                promptMessage{5}='Do you want to overwrite?';
                [~,fileName,ext]=fileparts(filenames);
                promptMessage{3}=[fileName ext];

                titleBarCaption = 'Overwrite?';
                buttonText = questdlg(promptMessage, titleBarCaption, 'Yes', 'No', 'Yes');
                switch buttonText
                    case 'Yes'
                        % User wants to overwrite. % Set flag to continue
                        continueLog=true(1);
                    case 'No'
                        % User does not want to overwrite. % Set flag to not do the write.
                        waitfor(warndlg('Choose another folder to save the results','OK'));
                        % let user choose a different folder to save the file
                end
            else
                % if file doesn't esixt, cotinue.
                continueLog=true(1);
            end
        end

    case 'No'
        saveLogic=false(1);
        savePath=[];
end

end

%%
% MultiDIC: a MATLAB Toolbox for Multi-View 3D Digital Image Correlation
%
% License: <https://github.com/MultiDIC/MultiDIC/blob/master/LICENSE.txt>
%
% Copyright (C) 2018  Dana Solav
%
% If you use the toolbox/function for your research, please cite our paper:
% <https://engrxiv.org/fv47e>


function singleMetaboliteThermoFigure(model, miliMolarStandard, metAbbr)
% Creates a vertical errorbar figure of the reactions involving the
% metabolite given by the abbreviation
%
% .. todo = fix this up
%
% USAGE:
%
%    singleMetaboliteThermoFigure(model, miliMolarStandard, metAbbr)
%
% INPUTS:
%    model:                structure
%    miliMolarStandard:
%    metAbbr:
%
% .. Author: - Ronan M.T. Fleming

[nMet,nRxn]=size(model.S); %%%%%%%%%vertical%%%%%%%%%%%%%
if miliMolarStandard
    dGt0Min=model.dGt0Min;
    dGt0Max=model.dGt0Max;
    for n=1:nRxn
        model.dGt0Min(n)=model.rxn(n).dGtmMMin;
        model.dGt0Max(n)=model.rxn(n).dGtmMMax;
    end
end
%forward possibly reversible
dGfGCforwardReversibleBool=directions.ChangeForwardReversibleBool_dGfGC;
%forward, probably reverse
fwdProbReverse=directions.ChangeForwardReversibleBool_dGfGC_byConcRHS | ...
    directions.ChangeForwardReversibleBool_dGfGC_bydGt0RHS | ...
    directions.ChangeForwardReversibleBool_dGfGC_byConc_No_dGt0ErrorRHS;

%plot regions 5,6,7, with region 6 shaded
X1=1:nRxn;
%dGrt0
Y0=(model.dGt0Min+model.dGt0Max)/2;
L0=Y0-model.dGt0Min;
U0=model.dGt0Max-Y0;
%dGrt
Y=(model.dGtMin+model.dGtMax)/2;
L=Y-model.dGtMin;
U=model.dGtMax-Y;
%find the amount of reactions with normal cumulative distribution over
%range of dGt0
P = normcdf(0,Y0,L0);
%sort by probability that a reaction is forward (puts any NaN first)
[tmp,xip]=sort(P,'descend');
%     only take the indices of the problematic reactions, but be sure to
%     take them in order of descending P
xip2=zeros(nnz(fwdProbReverse),1);
p=1;
for n=1:nRxn
    if fwdProbReverse(xip(n))
        xip2(p)=xip(n);
        p=p+1;
    end
end
xip=xip2;
X1=1:length(xip);

%replace the NaN due to zero st dev
nNaNpRHS=nnz(directions.ChangeForwardReversibleBool_dGfGC_byConc_No_dGt0ErrorRHS);
if nNaNpRHS~=nnz(isnan((P(fwdProbReverse))))
    warning('ExtraCategory');
end
%nans are first in the ordering of indexes
NaNPInd=xip(1:nNaNpRHS);
%sorts indices of the zero std dev met by their mean dG0t
[tmp,xipNaNPInd]=sort(Y0(NaNPInd));
%new ordering with NaNs sorted to right
xip=[xip(nNaNpRHS+1:end); NaNPInd(xipNaNPInd(1:nNaNpRHS))];

% close all
figure1 = figure;
% Create axes
axes1 = axes('Parent',figure1,'Color',[0.702 0.7804 1]);
hold on;

%upper and lower X
minX=min(model.dGtMin(fwdProbReverse));
maxX=max(model.dGtMax(fwdProbReverse));
%baselines
PreversibleBar_byConcRHS=ones(1,nRxn)*minX;
%bar for 6
PreversibleBar_byConcRHS(directions.ChangeForwardReversibleBool_dGfGC_byConcRHS)=maxX;
bar_handle6=barh(X1,PreversibleBar_byConcRHS(xip),1,'BaseValue',minX,'FaceColor',[0.86 0.86 0.86],'EdgeColor','none');

%dGrt errorbar
%   PLOTERR(X,Y,{LX,UX},{LY,UY}) plots the graph of vector X vs. vector Y
%   with error bars specified by LX and UX in horizontal direction and
%   with error bars specified by LY and UY in vertical direction.
%   H = PLOTERR(...) returns a vector of line handles in this order:
%      H(1) = handle to datapoints
%      H(2) = handle to errorbar y OR errorbar x if error y not specified
%      H(3) = handle to errorbar x if error y specified
% LineSpec=[''LineStyle','none','LineWidth',2,'DisplayName','forwardReversible','Color','r'']
LineSpec='r.';
hE = ploterr(Y(xip),X1,{model.dGtMin(xip) model.dGtMax(xip)},[],LineSpec,'hhxy',0);
set(hE(2),'LineWidth',10);
% hE=errorbar(X1,Y(xip),L(xip),U(xip),'LineStyle','none','LineWidth',2,'DisplayName','forwardReversible','Color','r');
%dGrt0 errorbar on top and inside dGrt
LineSpec='b.';
hE = ploterr(Y0(xip),X1,{model.dGt0Min(xip) model.dGt0Max(xip)},[],LineSpec,'hhxy',0);
set(hE(2),'LineWidth',10);
% hE2=errorbar(X1,Y0(xip),L0(xip),U0(xip),'LineStyle','none','LineWidth',2,'DisplayName','forwardReversible','Color','b');

%mean dGrt0
plot(Y0(xip),X1,'.','LineStyle','none','Color',[0.3412 0.7961 0.1922]);
%zero line
%cumulative probability that reaction is really forward, assuming a
%normal distribution about the mean dGt0
[AX,H1,H2]=plotyy(zeros(1,length(X1)),X1,P(xip),X1);
set(gca,'XTick',[]);
set(AX(1),'XTickMode','manual','YTick',floor(minX/100)*200:50:maxX);%,'TickDirMode','manual','TickDir','out');
set(AX(2),'YTick',1:length(xip));
set(H1,'LineStyle','none')
set(H2,'LineStyle','-','LineWidth',2,'Color','k')
plot(zeros(1,length(X1)),X1,'w','LineWidth',2,'LineStyle','--');
%axis limits
set(AX(1),'FontSize',16,'YColor','k')
set(AX(1),'YTick',[],'YTickLabelMode','manual');
set(AX(1),'XTickMode','manual','XTick',floor(minX/100)*200:50:maxX);
set(get(AX(1),'Xlabel'),'String','\Delta_{r}G^{\primem}  (blue)    or     \Delta_{r}G^{\prime} (red) (kJ/mol)')
set(get(AX(1),'Xlabel'),'FontSize',16)
set(AX(1),'Position',[0.05 0.1 0.4 0.8]);
axis(AX(1),[minX maxX 0.5 length(X1)+0.5 ]);
% axis(AX(1),[-250 250 0 length(X1)+0.5 ]);

set(AX(2),'FontSize',16,'YColor','k')
set(AX(2),'YTick',1:length(X1),'YTickLabelMode','manual');
set(AX(2),'XAxisLocation','top');
set(get(AX(2),'Xlabel'),'String','P(\Delta_{r}G^{\primem}<0)');
set(get(AX(2),'Xlabel'),'FontSize',16);
axis(AX(2),[0 1 0.5 length(X1)+0.5 ]);
set(AX(2),'Position',[0.05 0.1 0.4 0.8]);

% ylabel('Reactions, sorted by P(\Delta_{r}G^{\primem}<0) (blue)');
title('Qualitatively forward, but probably quantitatively reverse, using group contribution estimates of \Delta_{r}G^{\primem}.','FontSize',16)

for n=1:length(xip)
%     textLen(n)=length(model.rxn(xip(n)).officialName)+length(model.rxn(xip(n)).equation);
%     textLen(n)=length(model.rxn(xip(n)).equation);
   textLen(n)=length(model.rxn(xip(n)).officialName);
end
textLenMax=max(textLen);
for n=1:length(xip)
%     YTickLabel{n}=[model.rxn(xip(n)).officialName blanks(textLenMax-textLen(n)+5) model.rxn(xip(n)).equation];
    YTickLabel{n}=[model.rxn(xip(n)).officialName ' ' model.rxn(xip(n)).equation];
    %get rid of the cytoplasmic compartment abbreviations
    YTickLabel{n} = strrep(YTickLabel{n}, '[c]', '');

   % no idea why this does not work
   %     fprintf('%s\n',[model.rxn(xip(n)).officialName blanks(textLenMax-textLen(n)+5) model.rxn(xip(n)).equation]);
end
set(AX(2),'YTickLabel',YTickLabel,'FontSize',16);
saveas(figure1 ,'fwdProbReverseGC','fig');

%change back
if miliMolarStandard
    model.dGt0Min=dGt0Min;
    model.dGt0Max=dGt0Max;
end

%horizontal bar
horizontal=0;
if horizontal
    [nMet,nRxn]=size(model.S);
    if miliMolarStandard
        dGt0Min=model.dGt0Min;
        dGt0Max=model.dGt0Max;
        for n=1:nRxn
            model.dGt0Min(n)=model.rxn(n).dGtmMMin;
            model.dGt0Max(n)=model.rxn(n).dGtmMMax;
        end
    end
    %forward possibly reversible
    dGfGCforwardReversibleBool=directions.ChangeForwardReversibleBool_dGfGC;
    %forward, probably reverse
    fwdProbReverse=directions.ChangeForwardReversibleBool_dGfGC_byConcRHS | ...
        directions.ChangeForwardReversibleBool_dGfGC_bydGt0RHS | ...
        directions.ChangeForwardReversibleBool_dGfGC_byConc_No_dGt0ErrorRHS;

    %plot regions 5,6,7, with region 6 shaded
    X1=1:nRxn;
    %dGrt0
    Y0=(model.dGt0Min+model.dGt0Max)/2;
    L0=Y0-model.dGt0Min;
    U0=model.dGt0Max-Y0;
    %dGrt
    Y=(model.dGtMin+model.dGtMax)/2;
    L=Y-model.dGtMin;
    U=model.dGtMax-Y;
    %find the amount of reactions with normal cumulative distribution over
    %range of dGt0
    P = normcdf(0,Y0,L0);
    %sort by probability that a reaction is forward (puts any NaN first)
    [tmp,xip]=sort(P,'descend');
    %     only take the indices of the problematic reactions, but be sure to
    %     take them in order of descending P
    xip2=zeros(nnz(fwdProbReverse),1);
    p=1;
    for n=1:nRxn
        if fwdProbReverse(xip(n))
            xip2(p)=xip(n);
            p=p+1;
        end
    end
    xip=xip2;
    X1=1:length(xip);

    %replace the NaN due to zero st dev
    nNaNpRHS=nnz(directions.ChangeForwardReversibleBool_dGfGC_byConc_No_dGt0ErrorRHS);
    if nNaNpRHS~=nnz(isnan((P(fwdProbReverse))))
        warning('ExtraCategory');
    end
    %nans are first in the ordering of indexes
    NaNPInd=xip(1:nNaNpRHS);
    %sorts indices of the zero std dev met by their mean dG0t
    [tmp,xipNaNPInd]=sort(Y0(NaNPInd));
    %new ordering with NaNs sorted to right
    xip=[xip(nNaNpRHS+1:end); NaNPInd(xipNaNPInd(1:nNaNpRHS))];

    figure1 = figure('PaperSize',[11 8.5],'PaperOrientation','landscape');
    % Create axes
    axes1 = axes('Parent',figure1,'Color',[0.702 0.7804 1]);
    hold on;
    %upper and lower Y
    minY=min(model.dGtMin(fwdProbReverse));
    maxY=max(model.dGtMax(fwdProbReverse));
    %baselines
    PreversibleBar_byConcRHS=ones(1,nRxn)*minY;
    %bar for 6
    PreversibleBar_byConcRHS(directions.ChangeForwardReversibleBool_dGfGC_byConcRHS & directions.ChangeForwardReversibleBool_dGfGC_bydGt0RHS)=maxY;
    bar_handle6=bar(X1,PreversibleBar_byConcRHS(xip),1,'BaseValue',minY,'FaceColor',[0.86 0.86 0.86],'EdgeColor','none');

    %dGrt errorbar
    hE=errorbar(X1,Y(xip),L(xip),U(xip),'LineStyle','none','LineWidth',2,'DisplayName','forwardReversible','Color','r');
    % adjust error bar width
    hE_c=get(hE, 'Children');
    errorbarXData= get(hE_c(2), 'XData');
    errorbarXData(4:9:end) = errorbarXData(1:9:end) - 0;
    errorbarXData(7:9:end) = errorbarXData(1:9:end) - 0;
    errorbarXData(5:9:end) = errorbarXData(1:9:end) + 0;
    errorbarXData(8:9:end) = errorbarXData(1:9:end) + 0;
    set(hE_c(2), 'XData', errorbarXData);
    %dGrt0 errorbar on top and inside dGrt
    hE2=errorbar(X1,Y0(xip),L0(xip),U0(xip),'LineStyle','none','LineWidth',2,'DisplayName','forwardReversible','Color','b');
    % adjust error bar width
    hE_c=get(hE2, 'Children');
    errorbarXData= get(hE_c(2), 'XData');
    errorbarXData(4:9:end) = errorbarXData(1:9:end) - 0;
    errorbarXData(7:9:end) = errorbarXData(1:9:end) - 0;
    errorbarXData(5:9:end) = errorbarXData(1:9:end) + 0;
    errorbarXData(8:9:end) = errorbarXData(1:9:end) + 0;
    set(hE_c(2), 'XData', errorbarXData);

    %mean dGrt0
    plot(X1,Y0(xip),'.','LineStyle','none','Color',[0.3412 0.7961 0.1922]);
    %zero line
    %cumulative probability that reaction is really forward, assuming a
    %normal distribution about the mean dGt0
    [AX,H1,H2]=plotyy(X1,zeros(1,length(X1)),X1,P(xip));
    set(AX(1),'YTickMode','manual','YTick',floor(minY/100)*200:50:maxY);%,'TickDirMode','manual','TickDir','out');
    set(AX(2),'YTick',[0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1]);
    set(H1,'LineStyle','none')
    set(H2,'LineStyle','-','LineWidth',2,'Color','k')
    plot(X1,zeros(1,length(X1)),'w','LineWidth',2,'LineStyle','--');
    %axis limits
    axis(AX(1),[0 length(X1) minY maxY])
    set(AX(1),'FontSize',16)
    set(AX(2),'FontSize',16,'YColor','k')
    axis(AX(2),[0 length(X1) 0 1])
    title({'Qualitatively forward, but quantitatively reversible' ; 'using group contribution estimates of \Delta_{r}G^{\primem}.'},'FontSize',16)
    set(get(AX(1),'Ylabel'),'String','\Delta_{r}G^{\primem}  (blue)    or     \Delta_{r}G^{\prime} (red) (kJ/mol)')
    set(get(AX(2),'Ylabel'),'String','P(\Delta_{r}G^{\primem}<0)')
    set(get(AX(1),'Ylabel'),'FontSize',16)
    set(get(AX(2),'Ylabel'),'FontSize',16)
    xlabel('Reactions, sorted by P(\Delta_{r}G^{\primem}<0) (blue)');
    saveas(figure1 ,'GCfwdProbFwd','fig');

    %change back
    if miliMolarStandard
        model.dGt0Min=dGt0Min;
        model.dGt0Max=dGt0Max;
    end
end


function p3 = rdivide(p1,p2)
%PREAL/RDIVIDE Overloaded rdivide (./) operator for class preal.

global useUnitsFlag

if ~(useUnitsFlag) % If physunits is disabled...
    p3=rdivide(double(p1),double(p2)); % ... treat as double.
    return
end

p1=preal(p1);
p2=preal(p2);
if isscalar(p1)
    p1=preal(p1.value*ones(size(p2)),p1.units);
elseif isscalar(p2)
    p2=preal(p2.value*ones(size(p1)),p2.units);
elseif ndims(p1)==ndims(p2)&size(p1)==size(p2)
    % do nothing
else
    error('Array dimensions must agree')
end
p3=preal(ones(size(p1)));
for k=1:numel(p3)
    p3(k).value=p1(k).value/p2(k).value;
    p3(k).units=p1(k).units-p2(k).units;
end


function [errorcode, varargout] = common_size (varargin)

if (nargin < 2)
  error ('common_size: only makes sense if nargin >= 2');
end

% Find scalar args.
nscal = cellfun (@numel, varargin) ~= 1;

i = find (nscal, 1);

if (isempty (i))
  errorcode = 0;
  varargout = varargin;
else
  match = cellfun (@size_equal, varargin, repmat(varargin(i),size(varargin)));
  if (any (nscal & ~match))
    errorcode = 1;
    varargout = varargin;
  else
    errorcode = 0;
    if (nargout > 1)
      scal = ~nscal;
      varargout = varargin;
      dims = size (varargin{i});
      for s = find(scal)
        varargout{s} = repmat(varargin{s}, dims);
      end
    end
  end
end
end


function g = modelOutputGradX(model, X)

% MODELOUTPUTGRADX Compute derivatives with respect to model inputs of model outputs.
% FORMAT
% DESC gives the gradients of the outputs from the model with
% respect to the inputs.
% ARG model : the model structure for which gradients are computed.
% ARG X : input locations where gradients are to be computed.
% RETURN g : gradients of the model output with respect to the
% model parameters for the given input locations.
%
% SEEALSO : modelCreate, modelOutputGrad, modelLogLikelihood, modelLogLikeGradients
%
% COPYRIGHT : Neil D. Lawrence, 2006

% MLTOOLS

fhandle = str2func([model.type 'OutputGradX']);
g = fhandle(model, X);


function x = i4vec_increment ( n, x )

%*****************************************************************************80
%
%% I4VEC_INCREMENT increments an I4VEC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 July 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in the array.
%
%    Input/output, integer X(N), the array to be incremented.
%
  x(1:n) = x(1:n) + 1;

  return
end


%EXPORT_XLS Export grid and data in Excel format.
%
%   EXPORT_XLS( FILENAME, FEA, EXPR, SOLNUM, FID_LOG )
%
%   Export of grid points and corresponding solution/expression data
%   in Excel format. The output file will consist of a header line
%   with the space coordinate names, dependent variable names, and
%   given expressions (columns). This is followed by the actual data
%   rows where one line corresponds to the data for the specific grid
%   point.
%
%   FILENAME gives the output file name. FEA must be a valid FEA data
%   struct, EXPR is optionally a cell array with expressions to
%   process (the grid coordinates and dependent variables in the FEA
%   struct will be prepended to EXPR). SOLNUM is optionally the
%   solution number of which to evaluate the expressions. FID_LOG is
%   an optional log file handle for message output (negative for gui
%   output or empty for no output).

% Copyright 2013-2022 Precise Simulation, Ltd.


function s = sct(V,varargin)
  % SCT
  %
  % s = sct(V,varargin)
  %
  % Shorthand for:
  %  s = scatter(V(:,1),V(:,2), ...

  switch size(V,2)
  case 3
    ss = scatter3(V(:,1),V(:,2),V(:,3),varargin{:});
  case 2
    ss = scatter(V(:,1),V(:,2),varargin{:});
  end

  if nargout>0, s = ss; end
end


function x = real( x )

%   Disciplined convex/geometric programming information for REAL:
%      REAL(X) may be freely applied to any CVX expression. However,
%      since REAL(X)=X for all real expressions (including convex,
%      concave, log-convex, and log-concave), it is only useful in
%      the complex affine case.

b = x.basis_;
if ~isreal( b ),
    x = cvx( x.size_, real( b ) );
end

% Copyright 2005-2014 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


classdef SettingsMeshUnfitted < AbstractSettings

    properties (Access = protected)
        defaultParamsName = 'paramsMeshUnfitted.json'
    end

    properties (Access = public)
        backgroundMesh
        boundaryMesh
    end

    methods (Access = public)

        function obj = SettingsMeshUnfitted(varargin)
            switch nargin
                case 1
                    obj.loadParams(varargin{1});
                case 2
                    obj.backgroundMesh = varargin{2};
                case 3
                    disp('eis');
                case 4
                    disp('eis');

            end
            obj.init();
        end

    end

    methods (Access = private)

        function init(obj)
            obj.createBackgroundMesh();
        end

        function createBackgroundMesh(obj)
            if ischar(obj.backgroundMesh)
                fileName = obj.backgroundMesh;
                femReader = FemInputReader_GiD();
                s = femReader.read(fileName);
                obj.backgroundMesh = s.mesh;
            end
        end

    end

end


function showsteerable(coeff)
% Show the subbands of steerable pyramid

figure();
ht=length(coeff);

for i=2:length(coeff)-1
    for j=1:4
        subplot(ht-2,4,(i-2)*4+j);
        imshow(coeff{i}{j},[]);
    end
end


function [paramtransformsettings, names] = ndsimKernExtractParamTransformSettings(kern)

% NDSIMKERNEXTRACTPARAMTRANSFORMSETTINGS Extract parameter transform settings from the SIM kernel structure.
% FORMAT
% DESC Extract parameters from the single input motif kernel structure
% into a vector of parameters for optimisation.
% ARG kern : the kernel structure containing the parameters to be
% extracted.
% RETURN param : vector of parameters extracted from the kernel. If
% the field 'transforms' is not empty in the kernel matrix, the
% parameters will be transformed before optimisation (for example
% positive only parameters could be logged before being returned).
%
% FORMAT
% DESC Extract parameters and their names from the single input
% motif kernel structure.
% ARG kern : the kernel structure containing the parameters to be
% extracted.
% RETURN param : vector of parameters extracted from the kernel. If
% the field 'transforms' is not empty in the kernel matrix, the
% parameters will be transformed before optimisation (for example
% positive only parameters could be logged before being returned).
% RETURN names : cell array of strings containing parameter names.
%
% SEEALSO simKernParamInit, simKernExpandParam, kernExtractParam, scg, conjgrad
%
% COPYRIGHT : Neil D. Lawrence, 2006, 2009
%
% COPYRIGHT : Jaakko Peltonen, 2011
%
% KERN

if isfield(kern, 'options') ...
      && isfield(kern.options, 'isNegativeS') ...
      && kern.options.isNegativeS,
  if isfield(kern, 'gaussianInitial') && kern.gaussianInitial,
    % positive transformations for: inversewidth, initial variance
    paramtransformsettings = {kern.transforms(1).transformsettings, kern.transforms(2).transformsettings};
    if nargout > 1, names = {'inverse width', 'initial variance'}; end;
  else
    % positive transformations for: inversewidth
    paramtransformsettings = {kern.transforms(1).transformsettings};
    if nargout > 1, names = {'inverse width'}; end;
  end;

else
  if isfield(kern, 'gaussianInitial') && kern.gaussianInitial,
    % positive transformations for: inversewidth, kernel-variance,
    % initial variance
    paramtransformsettings = {kern.transforms(1).transformsettings, kern.transforms(2).transformsettings, kern.transforms(3).transformsettings};
    if nargout > 1, names = {'inverse width', 'variance', 'initial variance'}; end;
  else
    % positive transformations for: inversewidth, kernel-variance
    paramtransformsettings = {kern.transforms(1).transformsettings, kern.transforms(2).transformsettings};
    if nargout > 1, names = {'inverse width', 'variance'}; end;
  end;
end;

%fprintf(1, 'simKern parameters physical values:\n');
%params
%names


function HRVparams = InitializeHRVparams(project_name)
%
%   settings = InitializeHRVparams('project_name')
%
%   OVERVIEW:
%       This file stores settings and should be configured before
%       each use of the PhysioNet Cardiovascular Signal Toolbox:
%       1.  Project Specific Input/Output Data type and Folders
%       2.  How much does the user trust the data
%       3.  Global Settings (Window Size) for signal segmentation
%       4.  Quality Threshold Settings
%       5.  Debug Settings
%       6.  SQI Settings
%       7.  Preprocess Settings
%       8. AF Detection Settings
%       9. Time Domain Analysis Settings
%       10. Frequency Domain Analysis Settings
%       11. SDANN and SDNNI Analysis Settings
%       12. PRSA Analysis Settings
%       13. Peak Detection Settings
%       14. Entropy  and Multiscale Entropy - MSE - Settings
%       15. Detrended Fluctuation Analysis - DFA - Settings
%       16. Poincar� plot - Settings
%       17. Heart Rate Turbulence (HRT) - Settings
%       18. Output Settings
%       19. Time of Process and Filename to Save Data
%
%   INPUT:
%       project_name = a string with the name of the project - this
%       will determine the naming convention of file folders
%
%   OUTPUT:
%       HRVparams - struct of various settings for the hrv_toolbox analysis
%
%   DEPENDENCIES & LIBRARIES:
%       PhysioNet Cardiovascular Signal Toolbox
%       https://github.com/cliffordlab/PhysioNet-Cardiovascular-Signal-Toolbox
%
%   REFERENCE:
%   Vest et al. "An Open Source Benchmarked HRV Toolbox for Cardiovascular
%   Waveform and Interval Analysis" Physiological Measurement (In Press), 2018.
%
%	REPO:
%       https://github.com/cliffordlab/PhysioNet-Cardiovascular-Signal-Toolbox
%   ORIGINAL SOURCE AND AUTHORS:
%       Adriana N. Vest
%       Giulia Da Poian
%       Dependent scripts written by various authors
%       (see functions for details)
%	COPYRIGHT (C) 2018
%   LICENSE:
%       This software is offered freely and without warranty under
%       the GNU (v3 or later) public license. See license file for
%       more information
%%

if isempty(project_name)
    project_name = 'none';
end

% Set up input options for a specific project
switch project_name
    % Define new project name and parameters
    case 'MyProjectName'                   % Update with your project name
        HRVparams.Fs = NaN;                % Spacify sampling frequency
        HRVparams.readdata = '';           % (Optional) Specify name for data input folder
        HRVparams.writedata = '';          % (Optional) Specify name for data output folder
        HRVparams.datatype = '';           % (Optional) Spacify Data type of input
        HRVparams.ext = '';                % (Optional) Spacify file extension of input (e.g., 'mat','qrs')

    % Existing demo projects
    case 'MVanalysis'                      % Morphological variability analysis ECG
        HRVparams.Fs = 1000;
        HRVparams.readdata = '';
        HRVparams.writedata = '';
        HRVparams.datatype = '';
        HRVparams.ext = '';
    case 'demo_NSR'      % Parameters for demo using MIT nsr data
        HRVparams.readdata = strcat('TestData', filesep, 'Physionet_nsr2db');
        HRVparams.writedata = strcat('OutputData', filesep, 'ResultsNSR');
        HRVparams.ext = 'ecg';
        HRVparams.Fs = 125;
    case 'demo_RRgen'
        HRVparams.writedata = strcat('OutputData', filesep, 'ResultsRRgen');
        HRVparams.Fs = 125;
        HRVparams.demo.length = 5*60*60;   % Length of demo RR intervals in seconds
        HRVparams.demo.pe = 0.0003;        % Probability of ectopy ~ 1 per hr
        HRVparams.demo.pn = 0.0048;        % Probability of noise ~ 16 per hr
        HRVparams.demo.seed = 1;           % Seed for RRGEN
    case 'demoICU'      % Parameters for ICU demo
        HRVparams.readdata = strcat('TestData');
        HRVparams.writedata = strcat('OutputData', filesep, 'ResultsICU');
        HRVparams.ext = 'mat';
        HRVparams.Fs = 128;
    case 'demoAF'      % Parameters for AF demo
        HRVparams.readdata = strcat('TestData');
        HRVparams.writedata = strcat('OutputData', filesep, 'ResultsAFData');
        HRVparams.ext = 'mat';
        HRVparams.Fs = 128;
    case 'demoHRT'      % Parameters for HRT demo
        HRVparams.readdata = strcat('TestData', filesep, 'Physionet_nsr2db');
        HRVparams.writedata = strcat('OutputData', filesep, 'ResultsHRT');
        HRVparams.Fs = 128;
    case 'demoPVC'      % Parameters for PVC demo
        HRVparams.readdata = strcat('TestData', filesep, 'mitdb-Arrhythmia');
        HRVparams.writedata = strcat('OutputData', filesep, 'ResultsPVC');
        HRVparams.Fs = 360;
    otherwise                  % Default
        HRVparams.Fs = NaN;                          % Spacify sampling frequency
        HRVparams.writedata = 'HRV_Output';          % (Optional) Specify name for data output folder

end

if  isempty(HRVparams.writedata)
    % Default data OUTPUT folder name based on project name
    HRVparams.writedata = strcat(project_name,'_Results');
    fprintf('New OUTPUT folder: "%s"\n', HRVparams.writedata)
    mkdir(HRVparams.writedata);          % Create output folder and
elseif ~exist([pwd filesep HRVparams.writedata], 'dir')
    fprintf('New OUTPUT folder: "%s"\n',HRVparams.writedata)
    mkdir(HRVparams.writedata);          % Create output folder and
end
addpath(genpath(HRVparams.writedata));   % Add folder to search path

%% 2. How much does the user trust the data:
% This setting determines how stringently filtered the data is prior to
% calculating HRV metrics. Raw ECG or Pulse data that has been labeled
% using a peak detector (like jqrs) would require the most stringent
% filtering, whereas RR interval data that has been reviewed by a human
% technician would require the least amount of filtering.

%   - qrs detection no beats labeled - most stringent filters
%   - automatic beat detection beat typed - moderately stringent filtered
%   - hand corrected - least filtered, maybe no filter

% EXPLAIN THE THRESHOLDS BETTER
% ADD THIS TO A DEMO

HRVparams.data_confidence_level = 1;
% 1 - raw data with automatic beat detection
% 2 - raw data with automatic beat detection, but beat typed (ie N, SV,etc)
% 3 - technician reviewed data

% * ^^^^ NOT YET IN USE ^^^^  *

%% 3. Global Settings (Window Size)

HRVparams.windowlength = 300;	      % Default: 300, seconds
HRVparams.increment = 30;             % Default: 30, seconds increment
HRVparams.numsegs = 5;                % Default: 5, number of segments to collect with lowest HR
HRVparams.RejectionThreshold = .20;   % Default: 0.2, amount (%) of data that can be rejected before a
                                      % window is considered too low quality for analysis
HRVparams.MissingDataThreshold = .15; % Default: 0.15, maximum percentage of data allowable to be missing
                                      % from a window .15 = 15%
%% 5. Debug Settings

HRVparams.rawsig = 0;           % Load raw signal if it is available for debugging
HRVparams.debug = 0;

%% 6. SQI Analysis Settings
HRVparams.sqi.LowQualityThreshold = 0.9; % Default: 0.9, Threshold for which SQI represents good data
HRVparams.sqi.windowlength = 10;         % Default: 10, seconds, length of the comparison window
HRVparams.sqi.increment = 1;             % Default: 1, seconds
HRVparams.sqi.TimeThreshold = 0.1;       % Default: 0.1, seconds
HRVparams.sqi.margin = 2;                % Default: 2, seconds, Margin time not include in comparison

%% 7. Preprocess Settings

HRVparams.preprocess.figures = 0;                   % Figures on = 1, Figures off = 0
HRVparams.preprocess.gaplimit = 2;                  % Default: 2, seconds; maximum believable gap in rr intervals
HRVparams.preprocess.per_limit = 0.2;               % Default: 0.2, Percent limit of change from one interval to the next
HRVparams.preprocess.forward_gap = 3;	            % Default: 3, Maximum tolerable gap at beginning of timeseries in seconds
HRVparams.preprocess.method_outliers = 'rem';       % Default: 'rem', Method of dealing with outliers
                                                    % 'cub' = replace outlier points with cubic spline method
                                                    % 'rem' = remove outlier points
                                                    % 'pchip' = replace with pchip method
HRVparams.preprocess.lowerphysiolim = 60/160;       % Default: 60/160
HRVparams.preprocess.upperphysiolim = 60/30;        % Default: 60/30
HRVparams.preprocess.method_unphysio = 'rem';       % Default: 'rem', Method of dealing with unphysiologically low beats
                                                    % 'cub' = replace outlier points with cubic spline method
                                                    % 'rem' = remove outlier points
                                                    % 'pchip' = replace with pchip method

% The following settings do not yet have any functional effect on
% the output of preprocess.m:
HRVparams.preprocess.threshold1 = 0.9 ;	        % Default: 0.9, Threshold for which SQI represents good data
HRVparams.preprocess.minlength = 30;            % Default: 30, The minimum length of a good data segment in seconds

%% 8. AF Detection Settings and PVC detection

HRVparams.af.on = 1;              % Default: 1, AF Detection On or Off
HRVparams.af.windowlength = 30;   % Default: 30, Set to include ~30 beats in each window
HRVparams.af.increment = 30;      % Default: 30, No overlap necessary in AF feat calc

HRVparams.PVC.qrsth = 0.1;        % Default: 0.1, threshold for qrs detection

%% 9. Time Domain Analysis Settings

HRVparams.timedomain.on = 1;             % Default: 1, Time Domain Analysis 1=On or 0=Off
HRVparams.timedomain.dataoutput = 0;     % 1 = Print results to .txt file
                                         % Anything else = utputs to return variables only
                                         % returned variables
HRVparams.timedomain.alpha = 50   ;      % Default: 50 ,In msec
HRVparams.timedomain.win_tol = .15;      % Default: .15, Maximum percentage of data allowable
                                         % to be missing from a window

%% 10. Frequency Domain Analysis Settings

HRVparams.freq.on = 1;              % Default: 1, Frequency Domain Analysis 1=On or 0=Off

ULF = [0 .0033];                    % Requires window > 300 s
VLF = [0.0033 .04];                 % Requires at least 300 s window
LF = [.04 .15];                     % Requires at least 25 s window
HF = [0.15 0.4];                    % Requires at least 7 s window

HRVparams.freq.limits = [ULF; VLF; LF; HF];
HRVparams.freq.zero_mean = 1;               % Default: 1, Option for subtracting the mean from the input data
HRVparams.freq.method = 'lomb';             % Default: 'lomb'
                                            % Options: 'lomb', 'burg', 'fft', 'welch'
HRVparams.freq.plot_on = 0;

% The following settings are for debugging spectral analysis methods
HRVparams.freq.debug_sine = 0;              % Default: 0, Adds sine wave to tachogram for debugging
HRVparams.freq.debug_freq = 0.15;           % Default: 0.15
HRVparams.freq.debug_weight = .03;          % Default: 0.03

% Lomb:
HRVparams.freq.normalize_lomb = 0;	        % Default: 0
                                            % 1 = Normalizes Lomb Periodogram,
                                            % 0 = Doesn't normalize

% Burg: (not recommended)
HRVparams.freq.burg_poles = 15;    % Default: 15, Number of coefficients
                                   % for spectral estimation using the Burg
                                   % method (not recommended)

% The following settings are only used when the user specifies spectral
% estimation methods that use resampling : 'welch','fft', 'burg'
HRVparams.freq.resampling_freq = 7;             % Default: 7, Hz
HRVparams.freq.resample_interp_method = 'cub';  % Default: 'cub'
                                                % 'cub' = cublic spline method
                                                % 'lin' = linear spline method
HRVparams.freq.resampled_burg_poles = 100;      % Default: 100

%% 11. SDANN and SDNNI Analysis Settings
HRVparams.sd.on = 1;                        % Default: 1, SD analysis 1=On or 0=Off
HRVparams.sd.segmentlength = 300;           % Default: 300, windows length in seconds

%% 12. PRSA Analysis Settings

HRVparams.prsa.on = 1;             % Default: 1, PRSA Analysis 1=On or 0=Off
HRVparams.prsa.win_length = 30;    % Default: 30, The length of the PRSA signal
                                   % before and after the anchor points
                                   % (the resulting PRSA has length 2*L)
HRVparams.prsa.thresh_per = 20;    % Default: 20%, Percent difference that one beat can
                                   % differ from the next in the prsa code
HRVparams.prsa.plot_results = 0;   % Default: 0
HRVparams.prsa.scale = 2;          % Default: 2, scale parameter for wavelet analysis (to compute AC and DC)
HRVparams.prsa.min_anch = 20;       % Default: 20, minimum number of anchors point required to create the "average signal"

%% 13. Peak Detection Settings

% The following settings are for jqrs.m

HRVparams.PeakDetect.REF_PERIOD = 0.250;   % Default: 0.25 (should be 0.15 for FECG), refractory period in sec between two R-peaks
HRVparams.PeakDetect.THRES = .6;           % Default: 0.6, Energy threshold of the detector
HRVparams.PeakDetect.fid_vec = [];         % Default: [], If some subsegments should not be used for finding the optimal
                                           % threshold of the P&T then input the indices of the corresponding points here
HRVparams.PeakDetect.SIGN_FORCE = [];      % Default: [], Force sign of peaks (positive value/negative value)
HRVparams.PeakDetect.debug = 0;            % Default: 0
HRVparams.PeakDetect.ecgType = 'MECG';     % Default : MECG, options (adult MECG) or featl ECG (fECG)
HRVparams.PeakDetect.windows = 15;         % Befautl: 15,(in seconds) size of the window onto which to perform QRS detection

%% 14. Entropy Settings
% Multiscale Entropy
HRVparams.MSE.on = 1;                      % Default: 1, MSE Analysis 1=On or 0=Off
HRVparams.MSE.windowlength = [];           % Default: [], windows size in hours, default perform MSE on the entire signal
HRVparams.MSE.increment = [];              % Default: [], window increment in hours
HRVparams.MSE.RadiusOfSimilarity = 0.15;   % Default: 0.15, Radius of similarity (% of std)
HRVparams.MSE.patternLength = 2;           % Default: 2, pattern length
HRVparams.MSE.maxCoarseGrainings = 20;     % Default: 20, Maximum number of coarse-grainings
HRVparams.MSE.method = 'fir';           % Default 'fir', method use to generate the coarse-grain
                                           %                time series  options 'fir', 'butter'
HRVparams.MSE.moment = 'mean';             % Default: 'mean', moment used to coarse-grain the time series
                                           %           options 'mean', 'variance'
HRVparams.MSE.constant_r = 1;              % Default: 1, 1 use r as function of std of original time
                                           %             series, 0 compute r as function of std at each scale

% SampEn an ApEn
HRVparams.Entropy.on = 1;                     % Default: 1, MSE Analysis 1=On or 0=Off
HRVparams.Entropy.RadiusOfSimilarity = 0.15;  % Default: 0.15, Radius of similarity (% of std)
HRVparams.Entropy.patternLength = 2;          % Default: 2, pattern length

%% 15. DFA Settings

HRVparams.DFA.on = 1;               % Default: 1, DFA Analysis 1=On or 0=Off
HRVparams.DFA.windowlength = [];    % Default [], windows size in hours, default perform DFA on the entair signal
HRVparams.DFA.increment = [];       % Default: [], window increment in hours
HRVparams.DFA.minBoxSize = 4 ;      % Default: 4, Smallest box width
HRVparams.DFA.maxBoxSize = [];      % Largest box width (default in DFA code: signal length/4)
HRVparams.DFA.midBoxSize = 16;      % Medium time scale box width (default in DFA code: 16)

%% 16. Poincar� plot

HRVparams.poincare.on = 1;     % Default: 1, Poincare Analysis 1=On or 0=Off

%% 17. Heart Rate Turbulence (HRT) - Settings

HRVparams.HRT.on = 1;                        % Default: 1, HRT Analysis 1=On or 0=Off
HRVparams.HRT.BeatsBefore = 2;               % Default: 2, # of beats before PVC
HRVparams.HRT.BeatsAfter = 16;               % Default: 16, # of beats after PVC and CP
HRVparams.HRT.GraphOn = 0;                   % Default: 0, do not plot
HRVparams.HRT.windowlength = 24;             % Default 24h, windows size in hours
HRVparams.HRT.increment = 24;                % Default 24h, sliding window increment in hours
HRVparams.HRT.filterMethod = 'mean5before';  % Default mean5before, HRT filtering option

%% 18. Output Settings

HRVparams.gen_figs = 0;             % Generate figures
HRVparams.save_figs = 0;            % Save generated figures
if HRVparams.save_figs == 1
    HRVparams.gen_figs = 1;
end

% Format settings for HRV Outputs
HRVparams.output.format = 'csv';        % 'csv' - creates csv file for output
                                        % 'mat' - creates .mat file for output
HRVparams.output.separate = 1;          % Default : 1 = separate files for each subject
                                        %           0 = all results in one file
HRVparams.output.num_win = [];          % Specify number of lowest hr windows returned
                                        % leave blank if all windows should be returned
                                        % Format settings for annotations generated
HRVparams.output.ann_format = 'binary'; % 'binary'  = binary annotation file generated
                                        % 'csv'     = ASCII CSV file generated

%% 19. Filename to Save Data
HRVparams.time = datestr(now, 'yyyymmdd');              % Setup time for filename of output
HRVparams.filename = [HRVparams.time '_' project_name];

%% Export Parameter as Latex Table
% Note that if you change the order of the parameters or add parameters
% this might not work

ExportHRVparams(HRVparams);

end


%kvgamth 'Generate a Binary Image by Thresholding a Color Image (K1)'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros vgamth.pane file
%
% Parameters:
% InputFile: i 'Input Image ', required: 'input image'
% Integer: b 'High Threshold Map Column 1 (RED) ', default: 128: 'high threshold for map column 1'
% Integer: c 'Low Threshold Map Column 1 (RED) ', default: 128: 'low threshold for map column 1'
% Integer: d 'High Threshold Map Column 2 (GREEN)', default: 128: 'high threshold for map column 2'
% Integer: e 'Low Threshold Map Column 2 (GREEN) ', default: 128: 'low threshold for map column 2'
% Integer: f 'High Threshold Map Column 3 (BLUE) ', default: 128: 'high threshold for map column 3'
% Integer: g 'Low Threshold Map Column 3 (BLUE) ', default: 128: 'low threshold for map column 3'
% Integer: v 'Non-Zero Output Value ', default: 128: 'non-zero output value'
% OutputFile: o 'Output Image', required: 'resulting image'
%
% Example: o = kvgamth(i, {'i','';'b',128;'c',128;'d',128;'e',128;'f',128;'g',128;'v',128;'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% vgamth - Generate a Binary Image by Thresholding a Color Image  (K1)
%
%  DESCRIPTION
% .I vgamth
% generates a binary image by thresholding a pseudo color input image.
% The result image is of data type BYTE, and the input image must also
% be of type BYTE.
%
% The output pixel is given the specified value if:
% 1) only the lower value option is given and the pixel
% value is larger then the lower threshold,
% 2) only the upper value option is given and the pixel
% value is less than the upper threshold,
% 3) the upper value and lower value options are given and the pixel
% value is between the upper and lower threshold,
% or
% 4) same as 3 but both thresholds are equal and the pixel
% value is same as the threshold level.
% Otherwise, the output pixel is given a zero value.
%
% The input image must contain a map with three columns
% The thresholding is actually performed
% on the maps; thus the input image must have a map scheme of
% FORCE, and the map data type must be BYTE.
%
% By choosing the appropriate limits is it possible to identify
% areas in an image that are above or below a certain value, or to
% isolate certain bands of intensities in each color map. There are
% many different combinations that can be used to produce the results
% required.
%
% Note that this type of image is NOT a Khoros BIT image!
% The output image is of the data type BYTE, but the only
% pixel values are 0 and non-zero.
%
%
%
%  EXAMPLES
% vgamth -i input.image -o output.image -b 125 -c 75 -d 125 -e 75 -f 125 -g 75
% -v 100
%
% This command performs a threshold on input.image and stores the
% result in output.image.  All pixel values between 75 and 125 are
% given the value 100 in the output image.  All pixel values that
% do not fall within this range are give the value 0.
%
%  "SEE ALSO"
%
%  RESTRICTIONS
% .I vgamth
% will only operate on 1 band images of data storage type BYTE, with the
% map enable FORCE, and map data type BYTE.
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kvgamth(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,..] = kvgamth(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'b', 128;'c', 128;'d', 128;'e', 128;'f', 128;'g', 128;'v', 128;'o', '__output'};
maxval={0,255,255,255,255,255,255,255,0};
minval={0,0,0,0,0,0,0,0,0};
istoggle=[0,1,1,1,1,1,1,1,0];
was_set=istoggle * 0;
paramtype={'InputFile','Integer','Integer','Integer','Integer','Integer','Integer','Integer','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 'vgamth"  '],Inputs,narglist);


function [ftHeadmodel, ftLeadfield, iChannels] = out_fieldtrip_headmodel(HeadModelFile, ChannelFile, iChannels, isIncludeRef)
% OUT_FIELDTRIP_HEADMODEL: Converts a head model file into a FieldTrip structure (see ft_datatype_headmodel).
%
% USAGE:  [ftHeadmodel, ftLeadfield, iChannels] = out_fieldtrip_headmodel(HeadModelFile, ChannelFile, isIncludeRef=1);
%         [ftHeadmodel, ftLeadfield, iChannels] = out_fieldtrip_headmodel(HeadModelMat,  ChannelMat,  isIncludeRef=1);
%
% INPUTS:
%    - HeadModelFile  : Relative path to a head model file available in the database
%    - HeadModelMat   : Brainstorm head model file structure
%    - ChannelFile    : Relative path to a channel file available in the database
%    - ChannelMat     : Brainstorm channel file structure
% OUTPUTS:
%    - ftHeadmodel    : Volume conductor model, typically returned by ft_prepare_headmodel
%    - ftLeadfield    : Leadfield matrix, typically returned by ft_prepare_leadfield
%    - iChannels      : Modified list of channels (after adding channels)

% @=============================================================================
% 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: Jeremy T. Moreau, Elizabeth Bock, Francois Tadel, 2015

% ===== PARSE INPUTS =====
if (nargin < 4) || isempty(isIncludeRef)
    isIncludeRef = 1;
end
ftHeadmodel = [];
ftLeadfield = [];

% ===== LOAD INPUTS =====
% Load head model file
if ischar(HeadModelFile)
    HeadModelMat = in_bst_headmodel(HeadModelFile);
elseif isstruct(HeadModelFile)
    HeadModelMat = HeadModelFile;
else
    error('Failed to load head model.');
end
% If this file was computed with FieldTrip, it should include the original FieldTrip headmodel
if isfield(HeadModelMat, 'ftHeadmodelMeg') && ~isempty(HeadModelMat.ftHeadmodelMeg)
    ftHeadmodel = HeadModelMat.ftHeadmodelMeg;
elseif isfield(HeadModelMat, 'ftHeadmodelEeg') && ~isempty(HeadModelMat.ftHeadmodelEeg)
    ftHeadmodel = HeadModelMat.ftHeadmodelEeg;
end
% Load channel file
if ischar(ChannelFile)
    ChannelMat = in_bst_channel(ChannelFile);
elseif isstruct(ChannelFile)
    ChannelMat = ChannelFile;
else
    error('Failed to load channel file.')
end
% Get sensor type
Modality = ChannelMat.Channel(iChannels(1)).Type;
% Get headmodel type
switch (Modality)
    case 'EEG',   HeadModelMethod = HeadModelMat.EEGMethod;
    case 'ECOG',  HeadModelMethod = HeadModelMat.ECOGMethod;
    case 'SEEG',  HeadModelMethod = HeadModelMat.SEEGMethod;
    case {'MEG','MEG MAG','MEG GRAD','MEG REF'}, HeadModelMethod = HeadModelMat.MEGMethod;
end

% ===== ADD MEG REF =====
if isIncludeRef && ismember(Modality, {'MEG','MEG MAG','MEG GRAD'})
    iRef = channel_find(ChannelMat.Channel, 'MEG REF');
    if ~isempty(iRef)
        iChannels = [iRef, iChannels];
    end
end

% ===== CREATE FIELDTRIP HEADMODEL =====
if isempty(ftHeadmodel)
    % Get subject
    sSubject = bst_get('SurfaceFile', HeadModelMat.SurfaceFile);
    % Headmodel type
    switch (HeadModelMethod)
        case {'meg_sphere', 'singlesphere'}
            ftHeadmodel.type = 'singlesphere';
            ftHeadmodel.r = HeadModelMat.Param(iChannels(1)).Radii(1);
            ftHeadmodel.o = HeadModelMat.Param(iChannels(1)).Center(:)';

        case {'eeg_3sphereberg', 'concentricspheres'}
            ftHeadmodel.type = 'concentricspheres';
            ftHeadmodel.r = HeadModelMat.Param(iChannels(1)).Radii(:)';
            ftHeadmodel.o = HeadModelMat.Param(iChannels(1)).Center(:)';
            % Get default conductivities
            BFSProperties = bst_get('BFSProperties');
            ftHeadmodel.c = BFSProperties(1:3);

        case {'os_meg', 'localspheres'}
            ftHeadmodel.type = 'localspheres';
            ftHeadmodel.r = [HeadModelMat.Param(iChannels).Radii]';
            ftHeadmodel.o = [HeadModelMat.Param(iChannels).Center]';

        case {'singleshell'}
            ftHeadmodel.type = HeadModelMethod;
            % Check if the surfaces are available
            if isempty(sSubject.iInnerSkull)
                error('No inner skull surface available for this subject.');
            else
                disp(['BST> ' HeadModelMethod ': Using the default inner skull surface available in the database.']);
            end
            % Load surfaces
            SurfaceFiles = {sSubject.Surface(sSubject.iInnerSkull).FileName};
            ftHeadmodel.bnd = out_fieldtrip_tess(SurfaceFiles);

        case {'openmeeg', 'dipoli', 'bemcp'}
            ftHeadmodel.type = HeadModelMethod;
            % Check if the surfaces are available
            if isempty(sSubject.iInnerSkull) || isempty(sSubject.iOuterSkull) || isempty(sSubject.iScalp)
                error('No BEM surfaces available for this subject.');
            else
                disp(['BST> ' HeadModelMethod ': Using the default surfaces available in the database (inner skull, outer skull, scalp).']);
            end
            % Load surfaces
            SurfaceFiles = {sSubject.Surface(sSubject.iScalp).FileName, ...
                            sSubject.Surface(sSubject.iOuterSkull).FileName, ...
                            sSubject.Surface(sSubject.iInnerSkull).FileName};
            ftHeadmodel.bnd = out_fieldtrip_tess(SurfaceFiles);
            % Default OpenMEEG options
            ftHeadmodel.cond         = [0.33, 0.004125, 0.33];
            ftHeadmodel.skin_surface = 1;
            ftHeadmodel.source       = 3;
            % ERROR: MISSING .mat field??

        otherwise
            error('out_fieldtrip_headmodel does not support converting this type of head model.');
    end
    % Unit and labels
    ftHeadmodel.unit  = 'm';
    ftHeadmodel.label = {ChannelMat.Channel(iChannels).Name}';
end

% ===== CREATE FIELDTRIP LEADFIELD =====
if (nargout >= 2)
    % Create FieldTrip structure
    nSources = length(HeadModelMat.GridLoc);
    ftLeadfield.pos             = HeadModelMat.GridLoc;
    ftLeadfield.unit            = 'm';
    ftLeadfield.inside          = true(nSources, 1);
    ftLeadfield.leadfielddimord = '{pos}_chan_ori';
    ftLeadfield.label           = {ChannelMat.Channel(iChannels).Name};
    ftLeadfield.leadfield       = cell(1, nSources);
    for i = 1:nSources
        ftLeadfield.leadfield{i} = HeadModelMat.Gain(iChannels, 3*(i-1)+[1 2 3]);
    end
end


function mesh = mmgRunLs(mmg)
% Copyright (c) 2018-2019
% Matthieu Aussal, CMAP, Ecole Polytechnique
% Algiane Froehly, CARDAMOME, INRIA-SOFT
% LGPL Lesser General Public License v3.0.
% Remeshing using Mmg tools : https://www.mmgtools.org

% Current and mmg directory
%here  = pwd;
there = which('mmg.m');
there = there(1:end-6);

oldMeshFileName = mmg.oldMeshFileName;
newMeshFileName = mmg.newMeshFileName;
levelSetOldFileName = mmg.levelSetOldFileName;
levelSetNewFileName = mmg.levelSetNewFileName;

% Move to mmg directory
%cd(there)

% Check mesh (3D nodes, triangle or tetra, colours are int)
mesh = mmg.Mesh;
if (size(mesh.vtx,2) ~= 3) || (size(mesh.elt,2) < 3) || (size(mesh.elt,2) > 4)
    error('mmgRun.m : unavailable case, please use 3D vertices.')
end

% Check colours are int
if (norm(mesh.col-floor(mesh.col),'inf') > 1e-12) || (min(mesh.col)<0)
    error('mmgRun.m : only integer values for colours.')
end

% Delete .mesh and .sol files
deleteFiles(oldMeshFileName,newMeshFileName,levelSetOldFileName,levelSetNewFileName)

%figure(1)
s.connec  = mesh.elt();
s.coord   = mesh.vtx(:,1:2);
mN1 = Mesh().create(s);
%mN1.plot();
msRelator = MasterSlaveRelator(s.coord);
masterSlave = msRelator.getRelation();
cell = CellNodesDescriptor(s.coord);
n1 = masterSlave(:);
n2 = cell.cornerNodes;
nT = [n1;n2];
mN1.computeEdges();
nodeInBoundaryEdges = mN1.edges.computeBoundaryEdges(nT);
edges = nodeInBoundaryEdges;
edges(:,3) = 0;

nodes = find(edges(:,3) ~= 10);

% Write original mesh in .mesh format
mmgMeshWrite(oldMeshFileName,mesh,mmg.Req,nodes,edges);

% Write size map in .sol format
if ~isempty(mmg.Map)
    mmgSolWrite(levelSetOldFileName,mmg.Map,is2d(mesh));
end

% Operating system
if ismac
    os = './mac_';
elseif ispc
    os = 'win_';
elseif isunix
    os = '/./uni_';
else
    disp('mmg.m : unavailable case')
end
os = [there,os];

% Element form
if (size(mesh.elt,2) == 3)
    if is2d(mesh)
        bin = 'mmg2d_O3';
    else
        bin = 'mmgs_O3';
    end
elseif (size(mesh.elt,2) == 4)
    bin = 'mmg3d_O3';
end

% Add extension (for windows only)
if ispc
    bin = [bin,'.exe '];
else
    bin = [bin,' '];
end

% Define temporary mesh files
file = ['-in ',oldMeshFileName,' -out ',newMeshFileName,' '];

% Convert input to command
field = fieldnames(mmg);
opt   = '';
for i = 1:length(field)
    cmd = getfield(mmg,field{i});
    if ~isempty(cmd) && ~strcmp(field{i},'Mesh') && ~strcmp(field{i},'Req')...
       && ~strcmp(field{i},'Map') ...
       && ~strcmp(field{i},'oldMeshFileName') && ~strcmp(field{i},'newMeshFileName') ...
       && ~strcmp(field{i},'levelSetOldFileName') && ~strcmp(field{i},'levelSetNewFileName')
       %&& ~strcmp(field{i},'original') && ~strcmp(field{i},'refined') ...
        opt = [opt,cmd,' '];
    end
end

if ~isempty(mmg.Map)
    cmd = ['-sol ',levelSetOldFileName];
    opt = [opt,cmd,' '];
    cmd = ['-ls 0'];
    opt = [opt,cmd,' '];
end

% Execute mmg binaries
command = [os,bin,file,opt];
[~,~] = system(command);

% Read refined mesh
[remesh,req,label,edges] = mmgMeshRead(newMeshFileName);

% Replace required entites by original ones
if ~isempty(req)
    % Read original mesh for double/single troubles
    origin = mmgMeshRead(oldMeshFileName);

    % Vertex indices from required elements
    I = mesh.elt(mmg.Req,:);
    J = remesh.elt(req,:);

    % Unicity of vertices
    I = unique(I(:));
    J = unique(J(:));

    % Appairement using knnsearch with foat original mesh (to be improved)
    idx = knnsearch(origin.vtx(I,:),remesh.vtx(J,:),'K',1);

    % Replace remesh required vertices using original mesh vertices
    remesh.vtx(J,:) = mesh.vtx(I(idx),:);
end

% Save output
mesh = remesh;

% Delete .mesh and .sol files
deleteFiles(oldMeshFileName,newMeshFileName,levelSetOldFileName,levelSetNewFileName);

% Back to current directory
%cd(here)
end

function deleteFiles(oldMeshFileName,newMeshFileName,levelSetOldFileName,levelSetNewFileName)
if exist(oldMeshFileName,'file')
    delete(oldMeshFileName);
end
if exist(newMeshFileName,'file')
    delete(newMeshFileName);
end
if exist(levelSetOldFileName,'file')
    delete(levelSetOldFileName);
end
if exist(levelSetNewFileName,'file')
    delete(levelSetNewFileName);
end

end


function z = min( x, y )

% MAX   Minimum, z = min(x,y)

if isa(x,'tfocs_tuple')
    z = x;
    if isa(y,'tfocs_tuple')
        z.value_ = cellfun( @min, x.value_, y.value_, 'UniformOutput', false );
    elseif isscalar(y)
        z.value_ = cellfun( @min, x.value_, {y}, 'UniformOutput', false );
    else
        z.value_ = cellfun( @min, x.value_, {y}, 'UniformOutput', false );
    end
else
    z = y;
    if isscalar(x)
        z.value_ = cellfun( @min, {x}, y.value_, 'UniformOutput', false );
    else
        z.value_ = cellfun( @min, {x}, y.value_, 'UniformOutput', false );
    end
end

% TFOCS v1.3 by Stephen Becker, Emmanuel Candes, and Michael Grant.
% Copyright 2013 California Institute of Technology and CVX Research.
% See the file LICENSE for full license information.