function [elc, lab] = elec1020_locate(pnt, dhk, nas, ini, lpa, rpa, feedback)

% ELEC1020_LOCATE determines 10-20 (20%, 10% and 5%) electrode positions
% on a scalp surface that is described by its surface triangulation

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

if nargin<7
  feedback = false;
end

% determine the approximate location of the vertex
ori = (lpa+rpa+nas+ini)/4;      % center of head
ver =  cross(rpa-lpa, nas-ini); % orientation
ver = ver /sqrt(norm(ver));     % make correct length
ver = ori + 0.7*ver;            % location from center of head

if feedback
  figure
  ft_plot_mesh(struct('pos', pnt, 'tri', dhk), 'edgecolor', 'none', 'facecolor', 'skin')
  lighting gouraud
  material dull
  lightangle(0, 90);
  alpha 0.9
  ft_plot_mesh(nas, 'vertexsize', 30)
  ft_plot_mesh(lpa, 'vertexsize', 30)
  ft_plot_mesh(ini, 'vertexsize', 30)
  ft_plot_mesh(rpa, 'vertexsize', 30)
  ft_plot_mesh(ver, 'vertexsize', 30)
  grid on
  hold on
  view([1 1 0.5])
end

% point near LPA that is at 50% of left lower contour
[cnt1, cnt2] = elec1020_follow(pnt, dhk, nas, lpa, ini, feedback);
mle = elec1020_fraction(cnt1, cnt2, 0.5);

% point near RPA that is at 50% of right lower contour
[cnt1, cnt2] = elec1020_follow(pnt, dhk, nas, rpa, ini, feedback);
mre = elec1020_fraction(cnt1, cnt2, 0.5);

% determine two points that approximate the vertex
[cnt1, cnt2] = elec1020_follow(pnt, dhk, nas, ver, ini, feedback);
ver1 = elec1020_fraction(cnt1, cnt2, 0.5);
[cnt1, cnt2] = elec1020_follow(pnt, dhk, mle, ver, mre, feedback);
ver2 = elec1020_fraction(cnt1, cnt2, 0.5);

% refined estimate is the average of these two
ver = (ver1+ver2)/2;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% start contouring
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% ant-post contour through vertex
fprintf('constructing vertical ant-post contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, nas, ver, ini, feedback);
Nz   = elec1020_fraction(cnt1, cnt2,  0/20);
NFpz = elec1020_fraction(cnt1, cnt2,  1/20);
Fpz  = elec1020_fraction(cnt1, cnt2,  2/20);
AFpz = elec1020_fraction(cnt1, cnt2,  3/20);
AFz  = elec1020_fraction(cnt1, cnt2,  4/20);
AFFz = elec1020_fraction(cnt1, cnt2,  5/20);
Fz   = elec1020_fraction(cnt1, cnt2,  6/20);
FFCz = elec1020_fraction(cnt1, cnt2,  7/20);
FCz  = elec1020_fraction(cnt1, cnt2,  8/20);
FCCz = elec1020_fraction(cnt1, cnt2,  9/20);
Cz   = elec1020_fraction(cnt1, cnt2, 10/20);
CCPz = elec1020_fraction(cnt1, cnt2, 11/20);
CPz  = elec1020_fraction(cnt1, cnt2, 12/20);
CPPz = elec1020_fraction(cnt1, cnt2, 13/20);
Pz   = elec1020_fraction(cnt1, cnt2, 14/20);
PPOz = elec1020_fraction(cnt1, cnt2, 15/20);
POz  = elec1020_fraction(cnt1, cnt2, 16/20);
POOz = elec1020_fraction(cnt1, cnt2, 17/20);
Oz   = elec1020_fraction(cnt1, cnt2, 18/20);
OIz  = elec1020_fraction(cnt1, cnt2, 19/20);
Iz   = elec1020_fraction(cnt1, cnt2, 20/20);

% left-right through vertex
fprintf('constructing C contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, mle, ver, mre, feedback);
T9   = elec1020_fraction(cnt1, cnt2,  0/20);
T9h  = elec1020_fraction(cnt1, cnt2,  1/20);
T7   = elec1020_fraction(cnt1, cnt2,  2/20);
T7h  = elec1020_fraction(cnt1, cnt2,  3/20);
C5   = elec1020_fraction(cnt1, cnt2,  4/20);
C5h  = elec1020_fraction(cnt1, cnt2,  5/20);
C3   = elec1020_fraction(cnt1, cnt2,  6/20);
C3h  = elec1020_fraction(cnt1, cnt2,  7/20);
C1   = elec1020_fraction(cnt1, cnt2,  8/20);
C1h  = elec1020_fraction(cnt1, cnt2,  9/20);
Cz   = elec1020_fraction(cnt1, cnt2, 10/20);
C2h  = elec1020_fraction(cnt1, cnt2, 11/20);
C2   = elec1020_fraction(cnt1, cnt2, 12/20);
C4h  = elec1020_fraction(cnt1, cnt2, 13/20);
C4   = elec1020_fraction(cnt1, cnt2, 14/20);
C6h  = elec1020_fraction(cnt1, cnt2, 15/20);
C6   = elec1020_fraction(cnt1, cnt2, 16/20);
T8h  = elec1020_fraction(cnt1, cnt2, 17/20);
T8   = elec1020_fraction(cnt1, cnt2, 18/20);
T10h = elec1020_fraction(cnt1, cnt2, 19/20);
T10  = elec1020_fraction(cnt1, cnt2, 20/20);

% horizontal ant-post through T7
fprintf('constructing horizontal left contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, Fpz, T7, Oz, feedback);
Fp1h = elec1020_fraction(cnt1, cnt2,  1/20);
Fp1  = elec1020_fraction(cnt1, cnt2,  2/20);
AFp7 = elec1020_fraction(cnt1, cnt2,  3/20);
AF7  = elec1020_fraction(cnt1, cnt2,  4/20);
AFF7 = elec1020_fraction(cnt1, cnt2,  5/20);
F7   = elec1020_fraction(cnt1, cnt2,  6/20);
FFT7 = elec1020_fraction(cnt1, cnt2,  7/20);
FT7  = elec1020_fraction(cnt1, cnt2,  8/20);
FTT7 = elec1020_fraction(cnt1, cnt2,  9/20);
T7   = elec1020_fraction(cnt1, cnt2, 10/20);
TTP7 = elec1020_fraction(cnt1, cnt2, 11/20);
TP7  = elec1020_fraction(cnt1, cnt2, 12/20);
TPP7 = elec1020_fraction(cnt1, cnt2, 13/20);
P7   = elec1020_fraction(cnt1, cnt2, 14/20);
PPO7 = elec1020_fraction(cnt1, cnt2, 15/20);
PO7  = elec1020_fraction(cnt1, cnt2, 16/20);
POO7 = elec1020_fraction(cnt1, cnt2, 17/20);
O1   = elec1020_fraction(cnt1, cnt2, 18/20);
O1h  = elec1020_fraction(cnt1, cnt2, 19/20);

% horizontal ant-post through T8
fprintf('constructing horizontal right contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, Fpz, T8, Oz, feedback);
Fp2h = elec1020_fraction(cnt1, cnt2,  1/20);
Fp2  = elec1020_fraction(cnt1, cnt2,  2/20);
AFp8 = elec1020_fraction(cnt1, cnt2,  3/20);
AF8  = elec1020_fraction(cnt1, cnt2,  4/20);
AFF8 = elec1020_fraction(cnt1, cnt2,  5/20);
F8   = elec1020_fraction(cnt1, cnt2,  6/20);
FFT8 = elec1020_fraction(cnt1, cnt2,  7/20);
FT8  = elec1020_fraction(cnt1, cnt2,  8/20);
FTT8 = elec1020_fraction(cnt1, cnt2,  9/20);
T8   = elec1020_fraction(cnt1, cnt2, 10/20);
TTP8 = elec1020_fraction(cnt1, cnt2, 11/20);
TP8  = elec1020_fraction(cnt1, cnt2, 12/20);
TPP8 = elec1020_fraction(cnt1, cnt2, 13/20);
P8   = elec1020_fraction(cnt1, cnt2, 14/20);
PPO8 = elec1020_fraction(cnt1, cnt2, 15/20);
PO8  = elec1020_fraction(cnt1, cnt2, 16/20);
POO8 = elec1020_fraction(cnt1, cnt2, 17/20);
O2   = elec1020_fraction(cnt1, cnt2, 18/20);
O2h  = elec1020_fraction(cnt1, cnt2, 19/20);

fprintf('constructing AFp contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, AFp7, AFpz, AFp8, feedback);
AFp7h  = elec1020_fraction(cnt1, cnt2,  1/16);
AFp5   = elec1020_fraction(cnt1, cnt2,  2/16);
AFp5h  = elec1020_fraction(cnt1, cnt2,  3/16);
AFp3   = elec1020_fraction(cnt1, cnt2,  4/16);
AFp3h  = elec1020_fraction(cnt1, cnt2,  5/16);
AFp1   = elec1020_fraction(cnt1, cnt2,  6/16);
AFp1h  = elec1020_fraction(cnt1, cnt2,  7/16);
AFp2h  = elec1020_fraction(cnt1, cnt2,  9/16);
AFp2   = elec1020_fraction(cnt1, cnt2, 10/16);
AFp4h  = elec1020_fraction(cnt1, cnt2, 11/16);
AFp4   = elec1020_fraction(cnt1, cnt2, 12/16);
AFp6h  = elec1020_fraction(cnt1, cnt2, 13/16);
AFp6   = elec1020_fraction(cnt1, cnt2, 14/16);
AFp8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing AF contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, AF7, AFz, AF8, feedback);
AF7h  = elec1020_fraction(cnt1, cnt2,  1/16);
AF5   = elec1020_fraction(cnt1, cnt2,  2/16);
AF5h  = elec1020_fraction(cnt1, cnt2,  3/16);
AF3   = elec1020_fraction(cnt1, cnt2,  4/16);
AF3h  = elec1020_fraction(cnt1, cnt2,  5/16);
AF1   = elec1020_fraction(cnt1, cnt2,  6/16);
AF1h  = elec1020_fraction(cnt1, cnt2,  7/16);
AF2h  = elec1020_fraction(cnt1, cnt2,  9/16);
AF2   = elec1020_fraction(cnt1, cnt2, 10/16);
AF4h  = elec1020_fraction(cnt1, cnt2, 11/16);
AF4   = elec1020_fraction(cnt1, cnt2, 12/16);
AF6h  = elec1020_fraction(cnt1, cnt2, 13/16);
AF6   = elec1020_fraction(cnt1, cnt2, 14/16);
AF8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing AFF contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, AFF7, AFFz, AFF8, feedback);
AFF7h  = elec1020_fraction(cnt1, cnt2,  1/16);
AFF5   = elec1020_fraction(cnt1, cnt2,  2/16);
AFF5h  = elec1020_fraction(cnt1, cnt2,  3/16);
AFF3   = elec1020_fraction(cnt1, cnt2,  4/16);
AFF3h  = elec1020_fraction(cnt1, cnt2,  5/16);
AFF1   = elec1020_fraction(cnt1, cnt2,  6/16);
AFF1h  = elec1020_fraction(cnt1, cnt2,  7/16);
AFF2h  = elec1020_fraction(cnt1, cnt2,  9/16);
AFF2   = elec1020_fraction(cnt1, cnt2, 10/16);
AFF4h  = elec1020_fraction(cnt1, cnt2, 11/16);
AFF4   = elec1020_fraction(cnt1, cnt2, 12/16);
AFF6h  = elec1020_fraction(cnt1, cnt2, 13/16);
AFF6   = elec1020_fraction(cnt1, cnt2, 14/16);
AFF8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing F contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, F7, Fz, F8, feedback);
F7h  = elec1020_fraction(cnt1, cnt2,  1/16);
F5   = elec1020_fraction(cnt1, cnt2,  2/16);
F5h  = elec1020_fraction(cnt1, cnt2,  3/16);
F3   = elec1020_fraction(cnt1, cnt2,  4/16);
F3h  = elec1020_fraction(cnt1, cnt2,  5/16);
F1   = elec1020_fraction(cnt1, cnt2,  6/16);
F1h  = elec1020_fraction(cnt1, cnt2,  7/16);
F2h  = elec1020_fraction(cnt1, cnt2,  9/16);
F2   = elec1020_fraction(cnt1, cnt2, 10/16);
F4h  = elec1020_fraction(cnt1, cnt2, 11/16);
F4   = elec1020_fraction(cnt1, cnt2, 12/16);
F6h  = elec1020_fraction(cnt1, cnt2, 13/16);
F6   = elec1020_fraction(cnt1, cnt2, 14/16);
F8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing FFC contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, FFT7, FFCz, FFT8, feedback);
FFT7h  = elec1020_fraction(cnt1, cnt2,  1/16);
FFC5   = elec1020_fraction(cnt1, cnt2,  2/16);
FFC5h  = elec1020_fraction(cnt1, cnt2,  3/16);
FFC3   = elec1020_fraction(cnt1, cnt2,  4/16);
FFC3h  = elec1020_fraction(cnt1, cnt2,  5/16);
FFC1   = elec1020_fraction(cnt1, cnt2,  6/16);
FFC1h  = elec1020_fraction(cnt1, cnt2,  7/16);
FFC2h  = elec1020_fraction(cnt1, cnt2,  9/16);
FFC2   = elec1020_fraction(cnt1, cnt2, 10/16);
FFC4h  = elec1020_fraction(cnt1, cnt2, 11/16);
FFC4   = elec1020_fraction(cnt1, cnt2, 12/16);
FFC6h  = elec1020_fraction(cnt1, cnt2, 13/16);
FFC6   = elec1020_fraction(cnt1, cnt2, 14/16);
FFT8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing FC contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, FT7, FCz, FT8, feedback);
FT7h  = elec1020_fraction(cnt1, cnt2,  1/16);
FC5   = elec1020_fraction(cnt1, cnt2,  2/16);
FC5h  = elec1020_fraction(cnt1, cnt2,  3/16);
FC3   = elec1020_fraction(cnt1, cnt2,  4/16);
FC3h  = elec1020_fraction(cnt1, cnt2,  5/16);
FC1   = elec1020_fraction(cnt1, cnt2,  6/16);
FC1h  = elec1020_fraction(cnt1, cnt2,  7/16);
FC2h  = elec1020_fraction(cnt1, cnt2,  9/16);
FC2   = elec1020_fraction(cnt1, cnt2, 10/16);
FC4h  = elec1020_fraction(cnt1, cnt2, 11/16);
FC4   = elec1020_fraction(cnt1, cnt2, 12/16);
FC6h  = elec1020_fraction(cnt1, cnt2, 13/16);
FC6   = elec1020_fraction(cnt1, cnt2, 14/16);
FT8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing FCC contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, FTT7, FCCz, FTT8, feedback);
FTT7h  = elec1020_fraction(cnt1, cnt2,  1/16);
FCC5   = elec1020_fraction(cnt1, cnt2,  2/16);
FCC5h  = elec1020_fraction(cnt1, cnt2,  3/16);
FCC3   = elec1020_fraction(cnt1, cnt2,  4/16);
FCC3h  = elec1020_fraction(cnt1, cnt2,  5/16);
FCC1   = elec1020_fraction(cnt1, cnt2,  6/16);
FCC1h  = elec1020_fraction(cnt1, cnt2,  7/16);
FCC2h  = elec1020_fraction(cnt1, cnt2,  9/16);
FCC2   = elec1020_fraction(cnt1, cnt2, 10/16);
FCC4h  = elec1020_fraction(cnt1, cnt2, 11/16);
FCC4   = elec1020_fraction(cnt1, cnt2, 12/16);
FCC6h  = elec1020_fraction(cnt1, cnt2, 13/16);
FCC6   = elec1020_fraction(cnt1, cnt2, 14/16);
FTT8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing CCP contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, TTP7, CCPz, TTP8, feedback);
TTP7h  = elec1020_fraction(cnt1, cnt2,  1/16);
CCP5   = elec1020_fraction(cnt1, cnt2,  2/16);
CCP5h  = elec1020_fraction(cnt1, cnt2,  3/16);
CCP3   = elec1020_fraction(cnt1, cnt2,  4/16);
CCP3h  = elec1020_fraction(cnt1, cnt2,  5/16);
CCP1   = elec1020_fraction(cnt1, cnt2,  6/16);
CCP1h  = elec1020_fraction(cnt1, cnt2,  7/16);
CCP2h  = elec1020_fraction(cnt1, cnt2,  9/16);
CCP2   = elec1020_fraction(cnt1, cnt2, 10/16);
CCP4h  = elec1020_fraction(cnt1, cnt2, 11/16);
CCP4   = elec1020_fraction(cnt1, cnt2, 12/16);
CCP6h  = elec1020_fraction(cnt1, cnt2, 13/16);
CCP6   = elec1020_fraction(cnt1, cnt2, 14/16);
TTP8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing CP contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, TP7, CPz, TP8, feedback);
TP7h  = elec1020_fraction(cnt1, cnt2,  1/16);
CP5   = elec1020_fraction(cnt1, cnt2,  2/16);
CP5h  = elec1020_fraction(cnt1, cnt2,  3/16);
CP3   = elec1020_fraction(cnt1, cnt2,  4/16);
CP3h  = elec1020_fraction(cnt1, cnt2,  5/16);
CP1   = elec1020_fraction(cnt1, cnt2,  6/16);
CP1h  = elec1020_fraction(cnt1, cnt2,  7/16);
CP2h  = elec1020_fraction(cnt1, cnt2,  9/16);
CP2   = elec1020_fraction(cnt1, cnt2, 10/16);
CP4h  = elec1020_fraction(cnt1, cnt2, 11/16);
CP4   = elec1020_fraction(cnt1, cnt2, 12/16);
CP6h  = elec1020_fraction(cnt1, cnt2, 13/16);
CP6   = elec1020_fraction(cnt1, cnt2, 14/16);
TP8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing CPP contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, TPP7, CPPz, TPP8, feedback);
TPP7h  = elec1020_fraction(cnt1, cnt2,  1/16);
CPP5   = elec1020_fraction(cnt1, cnt2,  2/16);
CPP5h  = elec1020_fraction(cnt1, cnt2,  3/16);
CPP3   = elec1020_fraction(cnt1, cnt2,  4/16);
CPP3h  = elec1020_fraction(cnt1, cnt2,  5/16);
CPP1   = elec1020_fraction(cnt1, cnt2,  6/16);
CPP1h  = elec1020_fraction(cnt1, cnt2,  7/16);
CPP2h  = elec1020_fraction(cnt1, cnt2,  9/16);
CPP2   = elec1020_fraction(cnt1, cnt2, 10/16);
CPP4h  = elec1020_fraction(cnt1, cnt2, 11/16);
CPP4   = elec1020_fraction(cnt1, cnt2, 12/16);
CPP6h  = elec1020_fraction(cnt1, cnt2, 13/16);
CPP6   = elec1020_fraction(cnt1, cnt2, 14/16);
TPP8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing P contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, P7, Pz, P8, feedback);
P7h  = elec1020_fraction(cnt1, cnt2,  1/16);
P5   = elec1020_fraction(cnt1, cnt2,  2/16);
P5h  = elec1020_fraction(cnt1, cnt2,  3/16);
P3   = elec1020_fraction(cnt1, cnt2,  4/16);
P3h  = elec1020_fraction(cnt1, cnt2,  5/16);
P1   = elec1020_fraction(cnt1, cnt2,  6/16);
P1h  = elec1020_fraction(cnt1, cnt2,  7/16);
P2h  = elec1020_fraction(cnt1, cnt2,  9/16);
P2   = elec1020_fraction(cnt1, cnt2, 10/16);
P4h  = elec1020_fraction(cnt1, cnt2, 11/16);
P4   = elec1020_fraction(cnt1, cnt2, 12/16);
P6h  = elec1020_fraction(cnt1, cnt2, 13/16);
P6   = elec1020_fraction(cnt1, cnt2, 14/16);
P8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing PPO contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, PPO7, PPOz, PPO8, feedback);
PPO7h  = elec1020_fraction(cnt1, cnt2,  1/16);
PPO5   = elec1020_fraction(cnt1, cnt2,  2/16);
PPO5h  = elec1020_fraction(cnt1, cnt2,  3/16);
PPO3   = elec1020_fraction(cnt1, cnt2,  4/16);
PPO3h  = elec1020_fraction(cnt1, cnt2,  5/16);
PPO1   = elec1020_fraction(cnt1, cnt2,  6/16);
PPO1h  = elec1020_fraction(cnt1, cnt2,  7/16);
PPO2h  = elec1020_fraction(cnt1, cnt2,  9/16);
PPO2   = elec1020_fraction(cnt1, cnt2, 10/16);
PPO4h  = elec1020_fraction(cnt1, cnt2, 11/16);
PPO4   = elec1020_fraction(cnt1, cnt2, 12/16);
PPO6h  = elec1020_fraction(cnt1, cnt2, 13/16);
PPO6   = elec1020_fraction(cnt1, cnt2, 14/16);
PPO8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing PO contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, PO7, POz, PO8, feedback);
PO7h  = elec1020_fraction(cnt1, cnt2,  1/16);
PO5   = elec1020_fraction(cnt1, cnt2,  2/16);
PO5h  = elec1020_fraction(cnt1, cnt2,  3/16);
PO3   = elec1020_fraction(cnt1, cnt2,  4/16);
PO3h  = elec1020_fraction(cnt1, cnt2,  5/16);
PO1   = elec1020_fraction(cnt1, cnt2,  6/16);
PO1h  = elec1020_fraction(cnt1, cnt2,  7/16);
PO2h  = elec1020_fraction(cnt1, cnt2,  9/16);
PO2   = elec1020_fraction(cnt1, cnt2, 10/16);
PO4h  = elec1020_fraction(cnt1, cnt2, 11/16);
PO4   = elec1020_fraction(cnt1, cnt2, 12/16);
PO6h  = elec1020_fraction(cnt1, cnt2, 13/16);
PO6   = elec1020_fraction(cnt1, cnt2, 14/16);
PO8h  = elec1020_fraction(cnt1, cnt2, 15/16);

fprintf('constructing POO contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, POO7, POOz, POO8, feedback);
POO7h  = elec1020_fraction(cnt1, cnt2,  1/16);
POO5   = elec1020_fraction(cnt1, cnt2,  2/16);
POO5h  = elec1020_fraction(cnt1, cnt2,  3/16);
POO3   = elec1020_fraction(cnt1, cnt2,  4/16);
POO3h  = elec1020_fraction(cnt1, cnt2,  5/16);
POO1   = elec1020_fraction(cnt1, cnt2,  6/16);
POO1h  = elec1020_fraction(cnt1, cnt2,  7/16);
POO2h  = elec1020_fraction(cnt1, cnt2,  9/16);
POO2   = elec1020_fraction(cnt1, cnt2, 10/16);
POO4h  = elec1020_fraction(cnt1, cnt2, 11/16);
POO4   = elec1020_fraction(cnt1, cnt2, 12/16);
POO6h  = elec1020_fraction(cnt1, cnt2, 13/16);
POO6   = elec1020_fraction(cnt1, cnt2, 14/16);
POO8h  = elec1020_fraction(cnt1, cnt2, 15/16);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% start contouring the low electrode locations
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% low horizontal ant-post through T9
fprintf('constructing low horizontal left contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, Nz, T9, Iz, feedback);
AFp9 = elec1020_fraction(cnt1, cnt2,  3/20);
AF9  = elec1020_fraction(cnt1, cnt2,  4/20);
AFF9 = elec1020_fraction(cnt1, cnt2,  5/20);
F9   = elec1020_fraction(cnt1, cnt2,  6/20);
FFT9 = elec1020_fraction(cnt1, cnt2,  7/20);
FT9  = elec1020_fraction(cnt1, cnt2,  8/20);
FTT9 = elec1020_fraction(cnt1, cnt2,  9/20);
T9   = elec1020_fraction(cnt1, cnt2, 10/20);
TTP9 = elec1020_fraction(cnt1, cnt2, 11/20);
TP9  = elec1020_fraction(cnt1, cnt2, 12/20);
TPP9 = elec1020_fraction(cnt1, cnt2, 13/20);
P9   = elec1020_fraction(cnt1, cnt2, 14/20);
PPO9 = elec1020_fraction(cnt1, cnt2, 15/20);
PO9  = elec1020_fraction(cnt1, cnt2, 16/20);
POO9 = elec1020_fraction(cnt1, cnt2, 17/20);
I1   = elec1020_fraction(cnt1, cnt2, 18/20);
I1h  = elec1020_fraction(cnt1, cnt2, 19/20);

[cnt1, cnt2] = elec1020_follow(pnt, dhk, NFpz, T9h, OIz, feedback);
AFp9h = elec1020_fraction(cnt1, cnt2,  3/20);
AF9h  = elec1020_fraction(cnt1, cnt2,  4/20);
AFF9h = elec1020_fraction(cnt1, cnt2,  5/20);
F9h   = elec1020_fraction(cnt1, cnt2,  6/20);
FFT9h = elec1020_fraction(cnt1, cnt2,  7/20);
FT9h  = elec1020_fraction(cnt1, cnt2,  8/20);
FTT9h = elec1020_fraction(cnt1, cnt2,  9/20);
T9h   = elec1020_fraction(cnt1, cnt2, 10/20);
TTP9h = elec1020_fraction(cnt1, cnt2, 11/20);
TP9h  = elec1020_fraction(cnt1, cnt2, 12/20);
TPP9h = elec1020_fraction(cnt1, cnt2, 13/20);
P9h   = elec1020_fraction(cnt1, cnt2, 14/20);
PPO9h = elec1020_fraction(cnt1, cnt2, 15/20);
PO9h  = elec1020_fraction(cnt1, cnt2, 16/20);
POO9h = elec1020_fraction(cnt1, cnt2, 17/20);
OI1   = elec1020_fraction(cnt1, cnt2, 18/20);
OI1h  = elec1020_fraction(cnt1, cnt2, 19/20);

% low horizontal ant-post through T10
fprintf('constructing low horizontal right contour\n');
[cnt1, cnt2] = elec1020_follow(pnt, dhk, Nz, T10, Iz, feedback);
AFp10 = elec1020_fraction(cnt1, cnt2,  3/20);
AF10  = elec1020_fraction(cnt1, cnt2,  4/20);
AFF10 = elec1020_fraction(cnt1, cnt2,  5/20);
F10   = elec1020_fraction(cnt1, cnt2,  6/20);
FFT10 = elec1020_fraction(cnt1, cnt2,  7/20);
FT10  = elec1020_fraction(cnt1, cnt2,  8/20);
FTT10 = elec1020_fraction(cnt1, cnt2,  9/20);
T10   = elec1020_fraction(cnt1, cnt2, 10/20);
TTP10 = elec1020_fraction(cnt1, cnt2, 11/20);
TP10  = elec1020_fraction(cnt1, cnt2, 12/20);
TPP10 = elec1020_fraction(cnt1, cnt2, 13/20);
P10   = elec1020_fraction(cnt1, cnt2, 14/20);
PPO10 = elec1020_fraction(cnt1, cnt2, 15/20);
PO10  = elec1020_fraction(cnt1, cnt2, 16/20);
POO10 = elec1020_fraction(cnt1, cnt2, 17/20);
I2    = elec1020_fraction(cnt1, cnt2, 18/20);
I2h   = elec1020_fraction(cnt1, cnt2, 19/20);

[cnt1, cnt2] = elec1020_follow(pnt, dhk, NFpz, T10h, OIz, feedback);
AFp10h = elec1020_fraction(cnt1, cnt2,  3/20);
AF10h  = elec1020_fraction(cnt1, cnt2,  4/20);
AFF10h = elec1020_fraction(cnt1, cnt2,  5/20);
F10h   = elec1020_fraction(cnt1, cnt2,  6/20);
FFT10h = elec1020_fraction(cnt1, cnt2,  7/20);
FT10h  = elec1020_fraction(cnt1, cnt2,  8/20);
FTT10h = elec1020_fraction(cnt1, cnt2,  9/20);
T10h   = elec1020_fraction(cnt1, cnt2, 10/20);
TTP10h = elec1020_fraction(cnt1, cnt2, 11/20);
TP10h  = elec1020_fraction(cnt1, cnt2, 12/20);
TPP10h = elec1020_fraction(cnt1, cnt2, 13/20);
P10h   = elec1020_fraction(cnt1, cnt2, 14/20);
PPO10h = elec1020_fraction(cnt1, cnt2, 15/20);
PO10h  = elec1020_fraction(cnt1, cnt2, 16/20);
POO10h = elec1020_fraction(cnt1, cnt2, 17/20);
OI2    = elec1020_fraction(cnt1, cnt2, 18/20);
OI2h   = elec1020_fraction(cnt1, cnt2, 19/20);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% collect all the computed electrode locations
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

lab = {
  'LPA'
  'RPA'
  'NAS'
  'INI'
  'Nz'
  'Fp1'
  'Fpz'
  'Fp2'
  'AF9'
  'AF7'
  'AF5'
  'AF3'
  'AF1'
  'AFz'
  'AF2'
  'AF4'
  'AF6'
  'AF8'
  'AF10'
  'F9'
  'F7'
  'F5'
  'F3'
  'F1'
  'Fz'
  'F2'
  'F4'
  'F6'
  'F8'
  'F10'
  'FT9'
  'FT7'
  'FC5'
  'FC3'
  'FC1'
  'FCz'
  'FC2'
  'FC4'
  'FC6'
  'FT8'
  'FT10'
  'T9'
  'T7'
  'C5'
  'C3'
  'C1'
  'Cz'
  'C2'
  'C4'
  'C6'
  'T8'
  'T10'
  'TP9'
  'TP7'
  'CP5'
  'CP3'
  'CP1'
  'CPz'
  'CP2'
  'CP4'
  'CP6'
  'TP8'
  'TP10'
  'P9'
  'P7'
  'P5'
  'P3'
  'P1'
  'Pz'
  'P2'
  'P4'
  'P6'
  'P8'
  'P10'
  'PO9'
  'PO7'
  'PO5'
  'PO3'
  'PO1'
  'POz'
  'PO2'
  'PO4'
  'PO6'
  'PO8'
  'PO10'
  'O1'
  'Oz'
  'O2'
  'I1'
  'Iz'
  'I2'
  'AFp9h'
  'AFp7h'
  'AFp5h'
  'AFp3h'
  'AFp1h'
  'AFp2h'
  'AFp4h'
  'AFp6h'
  'AFp8h'
  'AFp10h'
  'AFF9h'
  'AFF7h'
  'AFF5h'
  'AFF3h'
  'AFF1h'
  'AFF2h'
  'AFF4h'
  'AFF6h'
  'AFF8h'
  'AFF10h'
  'FFT9h'
  'FFT7h'
  'FFC5h'
  'FFC3h'
  'FFC1h'
  'FFC2h'
  'FFC4h'
  'FFC6h'
  'FFT8h'
  'FFT10h'
  'FTT9h'
  'FTT7h'
  'FCC5h'
  'FCC3h'
  'FCC1h'
  'FCC2h'
  'FCC4h'
  'FCC6h'
  'FTT8h'
  'FTT10h'
  'TTP9h'
  'TTP7h'
  'CCP5h'
  'CCP3h'
  'CCP1h'
  'CCP2h'
  'CCP4h'
  'CCP6h'
  'TTP8h'
  'TTP10h'
  'TPP9h'
  'TPP7h'
  'CPP5h'
  'CPP3h'
  'CPP1h'
  'CPP2h'
  'CPP4h'
  'CPP6h'
  'TPP8h'
  'TPP10h'
  'PPO9h'
  'PPO7h'
  'PPO5h'
  'PPO3h'
  'PPO1h'
  'PPO2h'
  'PPO4h'
  'PPO6h'
  'PPO8h'
  'PPO10h'
  'POO9h'
  'POO7h'
  'POO5h'
  'POO3h'
  'POO1h'
  'POO2h'
  'POO4h'
  'POO6h'
  'POO8h'
  'POO10h'
  'OI1h'
  'OI2h'
  'Fp1h'
  'Fp2h'
  'AF9h'
  'AF7h'
  'AF5h'
  'AF3h'
  'AF1h'
  'AF2h'
  'AF4h'
  'AF6h'
  'AF8h'
  'AF10h'
  'F9h'
  'F7h'
  'F5h'
  'F3h'
  'F1h'
  'F2h'
  'F4h'
  'F6h'
  'F8h'
  'F10h'
  'FT9h'
  'FT7h'
  'FC5h'
  'FC3h'
  'FC1h'
  'FC2h'
  'FC4h'
  'FC6h'
  'FT8h'
  'FT10h'
  'T9h'
  'T7h'
  'C5h'
  'C3h'
  'C1h'
  'C2h'
  'C4h'
  'C6h'
  'T8h'
  'T10h'
  'TP9h'
  'TP7h'
  'CP5h'
  'CP3h'
  'CP1h'
  'CP2h'
  'CP4h'
  'CP6h'
  'TP8h'
  'TP10h'
  'P9h'
  'P7h'
  'P5h'
  'P3h'
  'P1h'
  'P2h'
  'P4h'
  'P6h'
  'P8h'
  'P10h'
  'PO9h'
  'PO7h'
  'PO5h'
  'PO3h'
  'PO1h'
  'PO2h'
  'PO4h'
  'PO6h'
  'PO8h'
  'PO10h'
  'O1h'
  'O2h'
  'I1h'
  'I2h'
  'AFp9'
  'AFp7'
  'AFp5'
  'AFp3'
  'AFp1'
  'AFpz'
  'AFp2'
  'AFp4'
  'AFp6'
  'AFp8'
  'AFp10'
  'AFF9'
  'AFF7'
  'AFF5'
  'AFF3'
  'AFF1'
  'AFFz'
  'AFF2'
  'AFF4'
  'AFF6'
  'AFF8'
  'AFF10'
  'FFT9'
  'FFT7'
  'FFC5'
  'FFC3'
  'FFC1'
  'FFCz'
  'FFC2'
  'FFC4'
  'FFC6'
  'FFT8'
  'FFT10'
  'FTT9'
  'FTT7'
  'FCC5'
  'FCC3'
  'FCC1'
  'FCCz'
  'FCC2'
  'FCC4'
  'FCC6'
  'FTT8'
  'FTT10'
  'TTP9'
  'TTP7'
  'CCP5'
  'CCP3'
  'CCP1'
  'CCPz'
  'CCP2'
  'CCP4'
  'CCP6'
  'TTP8'
  'TTP10'
  'TPP9'
  'TPP7'
  'CPP5'
  'CPP3'
  'CPP1'
  'CPPz'
  'CPP2'
  'CPP4'
  'CPP6'
  'TPP8'
  'TPP10'
  'PPO9'
  'PPO7'
  'PPO5'
  'PPO3'
  'PPO1'
  'PPOz'
  'PPO2'
  'PPO4'
  'PPO6'
  'PPO8'
  'PPO10'
  'POO9'
  'POO7'
  'POO5'
  'POO3'
  'POO1'
  'POOz'
  'POO2'
  'POO4'
  'POO6'
  'POO8'
  'POO10'
  'OI1'
  'OIz'
  'OI2'
  'T3' % this is now called T7
  'T4' % this is now called T8
  'T5' % this is now called P7
  'T6' % this is now called P8
  'M1' % left mastoid
  'M2' % right mastoid
  'A1' % left ear lobe
  'A2' % right ear lobe
  };

% allow for upper case electrode position labels
NAS = nas;
INI = ini;
LPA = lpa;
RPA = rpa;

% it would be possible to assign locations to these old locations
% but there are no locations determined for M1/2 and A1/2
if false
  T3 = T7;
  T4 = T8;
  T5 = P7;
  T6 = P8;
end

% assign the known local electrode positions to the output matrix
nlab = numel(lab);
elc = ones(nlab,3) * nan;
for i=1:nlab
  if exist(lab{i}, 'var')
    eval(sprintf('elc(%d,:) = %s;', i, lab{i}));
  else
    fprintf('not placing electrode %s\n', lab{i});
  end
end

% remove unknown electrode positions
sel = ~isnan(elc(:,1));
elc = elc(sel, :);
lab = lab(sel);

if feedback
  elec = [];
  elec.elecpos = elc;
  elec.label = lab;
  ft_plot_sens(elec)
end


clear;
gcp;    % start a local cluster

filename = 'demoSue2x.tif';
if ~exist(filename,'file');
    url = 'https://www.dropbox.com/s/36xdfd28eone0hj/demoSue2x.tif?dl=1';
    fprintf('downloading the file...');
    outfilename = websave(filename,url);
    fprintf('done. \n');
end

addpath(genpath('../../../ca_source_extraction-master'));  % add packages to matlab path
addpath(genpath('../../../NoRMCorre-master'));
addpath(genpath('../../../ca_source_extraction'));  % add packages to matlab path
addpath(genpath('../../../NoRMCorre'));

%% read file and determine dynamic range

Y = read_file(filename);
[d1,d2,T] = size(Y);    % dimensions of file
Y = Y - min(Y(:));      % remove negative offset

minY = quantile(Y(1:1e7),0.0005);
maxY = quantile(Y(1:1e7),1-0.0005);

%%  view data
figure;play_movie({Y},{'raw data'},minY,maxY);

%% perform motion correction (start with rigid)
% parameters motion correction
% 'd1','d2': size of FOV
% 'bin_width': how often to update the template
% 'max_shift': maximum allowed rigid shift

options_rg = NoRMCorreSetParms('d1',size(Y,1),'d2',size(Y,2),'bin_width',100,'max_shift',15);

[M_rg,shifts_rg,template_rg] = normcorre_batch(Y,options_rg);

%% view data
tsub = 5;   % downsampling factor (only for display purposes)
Y_sub = downsample_data(Y,'time',tsub);
M_rgs = downsample_data(M_rg,'time',tsub);

play_movie({Y_sub,M_rgs},{'raw data','rigid'},minY,maxY);

%% perform non-rigid motion correction
% parameters motion correction
% 'd1','d2': size FOV movie
% 'grid_size','overlap_pre': parameters regulating size of patch (size patch ~ (grid_size + 2*overlap_pre))
% 'mot_uf': upsampling factor of the grid for shift application
% 'bin_width': how often to update the template
% 'max_shift': maximum allowed rigid shift
% 'max_dev': maximum deviation allowed for each patch from the rigid shift value

options_nr = NoRMCorreSetParms('d1',size(Y,1),'d2',size(Y,2),...
                    'grid_size',[48,48],'mot_uf',4,'overlap_pre',[16,16],...
                    'bin_width',100,'max_shift',15,'max_dev',8);

[M_nr,shifts_nr,template_nr] = normcorre_batch(Y,options_nr,template_rg);

%% view (downsampled) data

M_nrs = downsample_data(M_nr,'time',tsub);
play_movie({Y_sub,M_rgs,M_nrs},{'raw data','rigid','pw-rigid'},minY,maxY);

%% compute some metrics for motion correction quality assessment

[cY,mY,vY] = motion_metrics(Y,options_rg.max_shift);
[cM_rg,mM_rg,vM_rg] = motion_metrics(M_rg,options_rg.max_shift);
[cM_nr,mM_nr,vM_nr] = motion_metrics(M_nr,options_rg.max_shift);

%% plot shifts

shifts_r = squeeze(cat(3,shifts_rg(:).shifts));
shifts_n = cat(ndims(shifts_nr(1).shifts)+1,shifts_nr(:).shifts);
shifts_n = reshape(shifts_n,[],ndims(Y)-1,T);
shifts_x = squeeze(shifts_n(:,2,:))';
shifts_y = squeeze(shifts_n(:,1,:))';

patch_id = 1:size(shifts_x,2);
str = strtrim(cellstr(int2str(patch_id.')));
str = cellfun(@(x) ['patch # ',x],str,'un',0);

figure;
    ax1 = subplot(311); plot(1:T,cY,1:T,cM_rg,1:T,cM_nr); legend('raw data','rigid','non-rigid'); title('correlation coefficients','fontsize',14,'fontweight','bold')
            set(gca,'Xtick',[])
    ax2 = subplot(312); plot(shifts_x); hold on; plot(shifts_r(:,2),'--k','linewidth',2); title('displacements along x','fontsize',14,'fontweight','bold')
            set(gca,'Xtick',[])
    ax3 = subplot(313); plot(shifts_y); hold on; plot(shifts_r(:,1),'--k','linewidth',2); title('displacements along y','fontsize',14,'fontweight','bold')
            xlabel('timestep','fontsize',14,'fontweight','bold')
    linkaxes([ax1,ax2,ax3],'x')

%% plot metrics
figure;
    ax(1) = subplot(2,3,1); imagesc(mY,[minY,maxY]);  axis equal; axis tight; axis off; title('mean raw data','fontsize',14,'fontweight','bold')
    ax(2) = subplot(2,3,2); imagesc(mM_rg,[minY,maxY]); axis equal; axis tight; axis off; title('mean rigid corrected','fontsize',14,'fontweight','bold')
    ax(3) = subplot(2,3,3); imagesc(mM_nr,[minY,maxY]); axis equal; axis tight; axis off; title('mean non-rigid corrected','fontsize',14,'fontweight','bold')
    subplot(2,3,4); plot(1:T,cY,1:T,cM_rg,1:T,cM_nr); legend('raw data','rigid','non-rigid'); title('correlation coefficients','fontsize',14,'fontweight','bold')
    subplot(2,3,5); scatter(cY,cM_rg); hold on; plot([0.9*min(cY),1.05*max(cM_rg)],[0.9*min(cY),1.05*max(cM_rg)],'--r'); axis square;
        xlabel('raw data','fontsize',14,'fontweight','bold'); ylabel('rigid corrected','fontsize',14,'fontweight','bold');
    subplot(2,3,6); scatter(cM_rg,cM_nr); hold on; plot([0.95*min(cM_rg),1.05*max(cM_nr)],[0.95*min(cM_rg),1.05*max(cM_nr)],'--r'); axis square;
        xlabel('rigid corrected','fontsize',14,'fontweight','bold'); ylabel('non-rigid corrected','fontsize',14,'fontweight','bold');
    linkaxes(ax,'xy')

%% now perform source extraction by splitting the FOV in patches

sizY = size(M_nr);
patch_size = [30,30];                   % size of each patch along each dimension (optional, default: [32,32])
overlap = [8,8];                        % amount of overlap in each dimension (optional, default: [4,4])

patches = construct_patches(sizY(1:end-1),patch_size,overlap);
K = 4;                                            % number of components to be found
tau = 4;                                          % std of gaussian kernel (half size of neuron)
p = 0;                                            % order of autoregressive system (p = 0 no dynamics, p=1 just decay, p = 2, both rise and decay)

options = CNMFSetParms(...
    'd1',sizY(1),'d2',sizY(2),...
    'temporal_iter',2,...                       % number of block-coordinate descent steps
    'ssub',1,...                                % downsample in space
    'tsub',2,...                                % downsample in time
    'merge_thr',0.8,...                         % merging threshold
    'gSig',tau,...
    'gnb',2,...                                 % number of background components
    'spatial_method','regularized'...
    );

%% run CNMF algorithm on patches and combine
tic;
[A,b,C,f,S,P,RESULTS,YrA] = run_CNMF_patches(M_nr,K,patches,tau,p,options);
[ROIvars.rval_space,ROIvars.rval_time,ROIvars.max_pr,ROIvars.sizeA,keep] = classify_components(M_nr,A,C,b,f,YrA,options);
toc

%% a simple GUI
Cn = correlation_image_max(M_nr);
Coor = plot_contours(A,Cn,options,1); close;
run_GUI = false;
if run_GUI
    GUIout = ROI_GUI(A,options,Cn,Coor,keep,ROIvars);
    options = GUIout{2};
    keep = GUIout{3};
end

%% view contour plots of selected and rejected components (optional)
throw = ~keep;
figure;
    ax1 = subplot(121); plot_contours(A(:,keep),Cn,options,0,[],Coor,1,find(keep)); title('Selected components','fontweight','bold','fontsize',14);
    ax2 = subplot(122); plot_contours(A(:,throw),Cn,options,0,[],Coor,1,find(throw));title('Rejected components','fontweight','bold','fontsize',14);
    linkaxes([ax1,ax2],'xy')
%% inspect components

plot_components_GUI(M_nr,A(:,keep),C(keep,:),b,f,Cn,options);

%% refine temporal components
A_keep = A(:,keep);
C_keep = C(keep,:);
P.p = 0;
[C2,f2,P2,S2,YrA2] = update_temporal_components(reshape(M_nr,[],T),A_keep,b,C_keep,f,P,options);

%% detrend fluorescence and extract DF/F values

options.df_window = 1000;
[F_dff,F0] = detrend_df_f(A_keep,b,C2,f2,YrA2,options);

%% deconvolve data

nNeurons = size(F_dff,1);
C_dec = zeros(size(F_dff));
S = zeros(size(F_dff));
kernels = cell(nNeurons,1);
min_sp = 3;    % find spikes resulting in transients above min_sp x noise level

for i = 1:nNeurons
    [C_dec(i,:),S(i,:),kernels{i}] = deconvCa(F_dff(i,:), [], min_sp, true, false, [], 20, [], 0);
end

%% plot a random component

i = randi(nNeurons);

figure;plot(1:T,F_dff(i,:),'--k'); hold all; plot(1:T,C_dec(i,:),'r','linewidth',2);
    spt = find(S(i,:));
    if spt(1) == 1; spt(1) = []; end
    hold on; scatter(spt,repmat(-0.25,1,length(spt)),'m*')
    title(['Component ',num2str(i)]);

    legend('Fluorescence DF/F','Deconvolved','Spikes')


function [sol,m,Q,residuals,everything] = solvesos_find_blocks(F,obj,options,params,candidateMonomials)

tol = options.sos.numblkdg;
if tol > 1e-2
    disp(' ');
    disp('-> Are you sure you meant to have a tolerance in numblk that big!')
    disp('-> The options numblkdiag controls the tolerance, it is not a 0/1 switch.')
    disp(' ');
end
options.sos.numblkdg = 0;
[sol,m,Q,residuals,everything] = solvesos(F,obj,options,params,candidateMonomials);

% Save old structure to find out when we have stalled
for i = 1:length(Q)
    oldlengths{i} = length(Q{i});
end

go_on = (sol.problem == 0 | sol.problem == 4);
while go_on

    for sosfun = 1:length(Q)
        Qtemp = Q{sosfun};
        keep = diag(Qtemp)>tol;
        Qtemp(:,find(~keep)) = [];
        Qtemp(find(~keep),:) = [];

        m{sosfun} = m{sosfun}(find(keep));

        Qtemp(abs(Qtemp) < tol) = 0;
        [v1,dummy1,r1,dummy3]=dmperm(Qtemp+eye(length(Qtemp)));
        lengths{sosfun} = [];
        n{sosfun} = {};
        for blocks = 1:length(r1)-1
            i1 = r1(blocks);
            i2 = r1(blocks+1)-1;
            if i2>i1
                n{sosfun}{blocks} = m{sosfun}(v1(i1:i2));
            else
                n{sosfun}{blocks} = m{sosfun}(v1(i1));
            end
            lengths{sosfun} =  [lengths{sosfun}  length(n{sosfun}{blocks})];
        end
        lengths{sosfun} = sort(lengths{sosfun});
    end
    go_on = ~isequal(lengths,oldlengths);
    oldlengths = lengths;
    if go_on
        [sol,m,Q,residuals,everything] = solvesos(F,obj,options,params,n);
        go_on = go_on & (sol.problem == 0 | sol.problem == 4);
        if sol.problem == 1
            disp('-> Feasibility was lost during the numerical block-diagonalization.')
            disp('-> The setting sos.numblkdiag is probably too big')
        end
    end
end


function selectInteractive(job,varargin)
% compute votes from grain boundaries
%
% Syntax
%
%   % compute votes from all p2c and c2c boundaries
%   job.calcGBVotes('threshold', 2*degree)
%
%   % compute votes only from p2c boundaries -> growth algorithm
%   job.calcGBVotes('p2c', 'threshold', 3*degree, 'tol', 1.5*degree)
%
% Input
%  job - @parentGrainReconstructor
%
% Output
%  job.votes - table of votes
%
% Options
%  p2c  - consider only parent / child grain boundaries
%  c2c  - consider only child / child grain boundaries
%  threshold - threshold fitting angle between job.p2c and the boundary OR
%  tolerance - range over which the probability increases from 0 to 1 (default 1.5)
%  numFit - number of fits to be computed
%

% datacursormode does not work with grains due to a Matlab bug
datacursormode off

% define a hand written selector
set(gcf,'WindowButtonDownFcn',{@doSelection,job});

end

function doSelection(src,eventdata,job)

% remove old selection
ax = gca;
handleSelected = getappdata(ax,'handleSelected');
try delete(handleSelected); end %#ok<TRYNC>

% new grainid
pos = get(ax,'CurrentPoint');
localId = findByLocation(job.grains,[pos(1,1) pos(1,2)]);

if isempty(localId), return; end
grain = job.grains(localId);

% mark grains
hold on
handleSelected = plot(grain.boundary,'lineColor','w','linewidth',4);
hold off
setappdata(ax,'handleSelected',handleSelected);

votesFit = job.calcGBVotes(grain.id,'bestFit','reconsiderAll');
votesProb = job.calcGBVotes(grain.id,'reconsiderAll','numFit',24,'tolerance',5*degree,'curvatureFactor',1);

fig = figure(100);
clf(fig)
set(fig,'name',['grain: ' xnum2str(grain.id)])
numV = size(votesFit.parentId,2);
cKey = ipfHSVKey(job.csParent);

oriPV = variants(job.p2c,job.grainsPrior(localId).meanOrientation,votesFit.parentId);

bgColor = cKey.orientation2color(oriPV);
fgColor = bgColor .* sum(bgColor,2) < 1.5;

for n=1:numV

  handles.b{n} = uicontrol('Style','PushButton','Units','normalized',...
    'Position',[0.1 (n-1)/numV 0.8 0.9*1/numV],...
    'backGroundColor',bgColor(n,:),'ForegroundColor',fgColor(n,:),...
    'String',[xnum2str(votesFit.fit(n)./degree) ' - ' ...
    xnum2str(votesProb.prob(votesProb.parentId==votesFit.parentId(n))) ],...
    'Callback',{@setOri,job,localId,oriPV(n),ax});
end

end

function setOri(a,b,job,id,pOri,ax)

job.grains(id).meanOrientation = pOri;
job.grains.update;

hold(ax,'on')
plot(job.grains(id),pOri,'parent',ax);
hold(ax,'off')

end


%filename = 'CantileverSquareSYmmetricMesh';
filename = 'CantileverSquareMedium';
%'CantileverSquareSYmmetricMesh';
%filename = 'CantileverSquare';
%filename = 'CantileverSquareSmall';
%filename = 'CantileverSquareNew';
%'CantileverSquareNewFine';
%filename = 'Cantilever_quad_coarse';
%filename = 'LshapeTriFine';
%filename = 'LshapeTri';
%filename = 'LshapeTriSmall';
%filename = 'Lshape';
%filename = 'LshapeFine';
%filename = 'ArchTriFine';
%'Arch_quad_coarse';
%'Bridge_quad_coarse';
%'BridgeCool_Quadrilateral_Bilinear_Structured_Coarse';
%filename = 'Bridge';

ptype = 'MACRO';
initial_case = 'given';
m1 = 0.0101;
m2 = 0.0101;
%cost = {'compliance'};
cost = {'stressNorm'};
%cost = {'stressNorm','compliance'};
%weights = [0.55,0.45];
weights = 1;
constraint = {'volumeConstraint'};
filterType = 'PDE';
%filterType = 'P1';
constraint_case = 'EQUALITY';

Vfrac_initial = 0.3;
optimality_initial = 1e-4;
constr_initial = 1e-8;

Vfrac_final = 0.3;
optimality_final = 1e-4;
constr_final = 1e-8;

stressNormExponent_initial = 2;
stressNormExponent_final = 32;
%
optimizer = 'DualNestedInPrimal';
%optimizer = 'AlternatingPrimalDual';
optimizerUnconstrained = 'PROJECTED GRADIENT';

%optimizer = 'MMA';
%optimizer = 'IPOPT';

designVariable = 'MicroParams';
ub = 0.989;
lb = 0.011;
homegenizedVariablesComputer = 'ByVademecum';
%
%vademecumFileName = 'SuperEllipseQMax';
%vademecumFileName = 'SuperEllipseQ2';
vademecumFileName = 'SuperEllipseQOptAnalytic';

% designVariable = 'LevelSet';
% homegenizedVariablesComputer = 'ByInterpolation';
% method = 'SIMPALL';
% materialType = 'ISOTROPIC';
% initial_case = 'full';% optimizerUnconstrained = 'SLERP';

% designVariable = 'Density';
% homegenizedVariablesComputer = 'ByInterpolation';
% method = 'SIMPALL';
% materialType = 'ISOTROPIC';
% initial_case = 'full';
% rho0 = 0.3;

line_search_initiator = 'INCREASING LAST STEP';
incrementFactor = 1.95;
%

%kfrac = 2;
nsteps = 17;

plotting = true;
printing = true;
monitoring = true;
monitoring_interval = 3;
maxiter = 8000;

%
% % %
isDirichletPartX = @(x) x > -1e-12 & x < 0.1;
isDirichletPart1 = @(y) y > 0.20 & y < 0.30;
isDirichletPart2 = @(y) y > 0.70 & y < 0.80;
isDirichletPartY = @(y) isDirichletPart1(y) | isDirichletPart2(y);
isDirichletPart = @(x,y) isDirichletPartX(x) & isDirichletPartY(y);
isNeumannPartX = @(x) x > (1-0.05) & x < (1+1e-12);
isNeumannPartY = @(y) y > 0.40 & y < 0.60;

isNeumannPart = @(x,y) isNeumannPartX(x) & isNeumannPartY(y);
iNotOptimizable = @(coord) isDirichletPart(coord(:,1),coord(:,2)) & ~isNeumannPart(coord(:,1),coord(:,2));

costDomainNotOptimizable       = {iNotOptimizable};
constraintDomainNotOptimizable = {[]};

isDesignVariableFixed.nodes  = iNotOptimizable;
isDesignVariableFixed.values = @(x) [m1*ones(size(x,1),1);m2*ones(size(x,1),1)];


%krf_polar 'polar transform'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros rf_polar.pane file
%
% Parameters:
% InputFile: i 'Input (rect)', required: 'input image, rectangular coordinates'
% OutputFile: o 'Output (polar)', required: 'output image, log-polar coordinates'
% Double: rmin 'min', default: 1: 'minimum radius'
% Double: rmax 'max', default: 64: 'maximum radius'
% Double: radinc 'sampling increment', default: 1: 'radius sampling increment'
% Double: amin 'min', default: -90: 'minimum angle'
% Double: amax 'max', default: 90: 'maximum angle'
% Double: anginc 'sampling increment', default: 1: 'angle sampling increment'
%
% Example: o = krf_polar(i, {'i','';'o','';'rmin',1;'rmax',64;'radinc',1;'amin',-90;'amax',90;'anginc',1})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% rf_polar - polar transform
%
%  DESCRIPTION
% This is a spacial transform (warping) of an image.  Specifically, we
% map the specified section of an annulus in the input image to a
% rectangle in the output image.  This is done by mapping annulus pixels
% (m,n) to (r, theta) pixels, where r is the radius and theta is the
% angle from m-axis.
%
% The center of the annulus is also specified as the upper left corner
% of the image (0,0), or the center (N/2, N/2).  In both cases, angles
% are measured from the m (horizontal) axis, and positive in the
% clockwise direction (to remain consistant with the left-hand
% coordinate system typically used in image processing).
%
% The dimensions of the output image are set to either the minimum size
% that will retain the resolution of the input image, or that size
% rounded up to the nearest power of 2 depending on the -logradsz and
% -anglesz flags.
%
%
%
%  EXAMPLES
% See the html tutorial in $REGISTER/examples/html/README_FIRST.html
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1996 - 1997, University of New Mexico.  All rights reserved.
%

function varargout = krf_polar(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,..] = krf_polar(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'o', '__output';'rmin', 1;'rmax', 64;'radinc', 1;'amin', -90;'amax', 90;'anginc', 1};
maxval={0,0,2,2,2,360,360,2};
minval={0,0,2,2,2,-360,-360,2};
istoggle=[0,0,0,0,0,0,0,0];
was_set=istoggle * 0;
paramtype={'InputFile','OutputFile','Double','Double','Double','Double','Double','Double'};
% 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 'rf_polar"  '],Inputs,narglist);


function b = padarray(varargin)
%PADARRAY Pad an array.
%   B = PADARRAY(A,PADSIZE) pads array A with PADSIZE(k) number of zeros
%   along the k-th dimension of A.  PADSIZE should be a vector of
%   positive integers.
%
%   B = PADARRAY(A,PADSIZE,PADVAL) pads array A with PADVAL (a scalar)
%   instead of with zeros.
%
%   B = PADARRAY(A,PADSIZE,PADVAL,DIRECTION) pads A in the direction
%   specified by the string DIRECTION.  DIRECTION can be one of the
%   following strings.
%
%       String values for DIRECTION
%       'pre'         Pads before the first array element along each
%                     dimension .
%       'post'        Pads after the last array element along each
%                     dimension.
%       'both'        Pads before the first array element and after the
%                     last array element along each dimension.
%
%   By default, DIRECTION is 'post'.
%
%   B = PADARRAY(A,PADSIZE,METHOD,DIRECTION) pads array A using the
%   specified METHOD.  METHOD can be one of these strings:
%
%       String values for METHOD
%       'circular'    Pads with circular repetion of elements.
%       'replicate'   Repeats border elements of A.
%       'symmetric'   Pads array with mirror reflections of itself.
%
%   Class Support
%   -------------
%   When padding with a constant value, A can be numeric or logical.
%   When padding using the 'circular', 'replicate', or 'symmetric'
%   methods, A can be of any class.  B is of the same class as A.
%
%   Example
%   -------
%   Add three elements of padding to the beginning of a vector.  The
%   padding elements contain mirror copies of the array.
%
%       b = padarray([1 2 3 4],3,'symmetric','pre')
%
%   Add three elements of padding to the end of the first dimension of
%   the array and two elements of padding to the end of the second
%   dimension.  Use the value of the last array element as the padding
%   value.
%
%       B = padarray([1 2; 3 4],[3 2],'replicate','post')
%
%   Add three elements of padding to each dimension of a
%   three-dimensional array.  Each pad element contains the value 0.
%
%       A = [1 2; 3 4];
%       B = [5 6; 7 8];
%       C = cat(3,A,B)
%       D = padarray(C,[3 3],0,'both')
%
%   See also CIRCSHIFT, IMFILTER.

%   Copyright 1993-2002 The MathWorks, Inc.
%   $Revision: 1.11 $  $Date: 2002/03/15 15:28:49 $
%
%   This function is part of the Image Processing Toolbox.
%   At the Householder Meeting in Peebles, Scotland, May 17--21, 2002,
%   Cleve Moler has given us permission to include this function,
%   and mkconstarray.m, in our toolbox.  We have modified the
%   subfunction ParseInputs.m, to remove some dependencies on
%   other

[a, method, padSize, padVal, direction] = ParseInputs(varargin{:});

if isempty(a),% treat empty matrix similar for any method

   if strcmp(direction,'both')
      sizeB = size(a) + 2*padSize;
   else
      sizeB = size(a) + padSize;
   end

   b = mkconstarray(class(a), padVal, sizeB);

else
  switch method
    case 'constant'
        b = ConstantPad(a, padSize, padVal, direction);

    case 'circular'
        b = CircularPad(a, padSize, direction);

    case 'symmetric'
        b = SymmetricPad(a, padSize, direction);

    case 'replicate'
        b = ReplicatePad(a, padSize, direction);
  end
end

if (islogical(a))
    b = logical(b);
end

%%%
%%% ConstantPad
%%%
function b = ConstantPad(a, padSize, padVal, direction)

numDims = prod(size(padSize));

% Form index vectors to subsasgn input array into output array.
% Also compute the size of the output array.
idx   = cell(1,numDims);
sizeB = zeros(1,numDims);
for k = 1:numDims
    M = size(a,k);
    switch direction
        case 'pre'
            idx{k}   = (1:M) + padSize(k);
            sizeB(k) = M + padSize(k);

        case 'post'
            idx{k}   = 1:M;
            sizeB(k) = M + padSize(k);

        case 'both'
            idx{k}   = (1:M) + padSize(k);
            sizeB(k) = M + 2*padSize(k);
    end
end

% Initialize output array with the padding value.  Make sure the
% output array is the same type as the input.
b         = mkconstarray(class(a), padVal, sizeB);
b(idx{:}) = a;

%%%
%%% CircularPad
%%%
function b = CircularPad(a, padSize, direction)

numDims = prod(size(padSize));

% Form index vectors to subsasgn input array into output array.
% Also compute the size of the output array.
idx   = cell(1,numDims);
for k = 1:numDims
  M = size(a,k);
  dimNums = [1:M];
  p = padSize(k);

  switch direction
    case 'pre'
       idx{k}   = dimNums(mod([-p:M-1], M) + 1);

    case 'post'
      idx{k}   = dimNums(mod([0:M+p-1], M) + 1);

    case 'both'
      idx{k}   = dimNums(mod([-p:M+p-1], M) + 1);

  end
end
b = a(idx{:});

%%%
%%% SymmetricPad
%%%
function b = SymmetricPad(a, padSize, direction)

numDims = prod(size(padSize));

% Form index vectors to subsasgn input array into output array.
% Also compute the size of the output array.
idx   = cell(1,numDims);
for k = 1:numDims
  M = size(a,k);
  dimNums = [1:M M:-1:1];
  p = padSize(k);

  switch direction
    case 'pre'
      idx{k}   = dimNums(mod([-p:M-1], 2*M) + 1);

    case 'post'
      idx{k}   = dimNums(mod([0:M+p-1], 2*M) + 1);

    case 'both'
      idx{k}   = dimNums(mod([-p:M+p-1], 2*M) + 1);
  end
end
b = a(idx{:});

%%%
%%% ReplicatePad
%%%
function b = ReplicatePad(a, padSize, direction)

numDims = prod(size(padSize));

% Form index vectors to subsasgn input array into output array.
% Also compute the size of the output array.
idx   = cell(1,numDims);
for k = 1:numDims
  M = size(a,k);
  p = padSize(k);
  onesVector = ones(1,p);

  switch direction
    case 'pre'
      idx{k}   = [onesVector 1:M];

    case 'post'
      idx{k}   = [1:M M*onesVector];

    case 'both'
      idx{k}   = [onesVector 1:M M*onesVector];
  end
end
 b = a(idx{:});

%%%
%%% ParseInputs
%%%
function [a, method, padSize, padVal, direction] = ParseInputs(varargin)

% default values
a         = [];
method    = 'constant';
padSize   = [];
padVal    = 0;
direction = 'both';

%checknargin(2,4,nargin,mfilename);

a = varargin{1};

padSize = varargin{2};
%checkinput(padSize, {'double'}, {'real' 'vector' 'nonnan' 'nonnegative' ...
%                    'integer'}, mfilename, 'PADSIZE', 2);

% Preprocess the padding size
if (prod(size(padSize)) < ndims(a))
    padSize           = padSize(:);
    padSize(ndims(a)) = 0;
end

if nargin > 2

    firstStringToProcess = 3;

    if ~ischar(varargin{3})
        % Third input must be pad value.
        padVal = varargin{3};
%        checkinput(padVal, {'numeric' 'logical'}, {'scalar'}, ...
%                   mfilename, 'PADVAL', 3);

        firstStringToProcess = 4;

    end

    for k = firstStringToProcess:nargin
%        validStrings = {'circular' 'replicate' 'symmetric' 'pre' ...
%                        'post' 'both'};
%        string = checkstrs(varargin{k}, validStrings, mfilename, ...
%                           'METHOD or DIRECTION', k);
        string = varargin{k};
        switch string
         case {'circular' 'replicate' 'symmetric'}
          method = string;

         case {'pre' 'post' 'both'}
          direction = string;

         otherwise
          error('Images:padarray:unexpectedError', '%s', ...
                'Unexpected logic error.')
        end
    end
end

% Check the input array type
if strcmp(method,'constant') & ~(isnumeric(a) | islogical(a))
    id = sprintf('Images:%s:badTypeForConstantPadding', mfilename);
    msg1 = sprintf('Function %s expected A (argument 1)',mfilename);
    msg2 = 'to be numeric or logical for constant padding.';
    error(id,'%s\n%s',msg1,msg2);
end


%% Introduction to SURF (Speeded-Up Robust Features)
% SURF keypoint detection + keypoint drawing with OpenCV functions
%
% In this sample you will learn:
%
% * The basics of SURF.
% * How to use <matlab:doc('cv.SURF') cv.SURF> and its function
%   |cv.SURF.detect| to perform the detection process in order to find
%   interest points.
% * How to use the function <matlab:doc('cv.drawKeypoints') cv.drawKeypoints>
%   to draw the detected keypoints.
%
% Sources:
%
% * <https://docs.opencv.org/3.2.0/d7/d66/tutorial_feature_detection.html>
% * <https://docs.opencv.org/3.2.0/df/dd2/tutorial_py_surf_intro.html>
%

%% Theory
%
% We previously saw SIFT for keypoint detection and description. But it was
% comparatively slow and people needed more speeded-up version. In 2006, three
% people, Bay, H., Tuytelaars, T. and Van Gool, L, published another paper,
% "SURF: Speeded Up Robust Features" which introduced a new algorithm called
% SURF. As name suggests, it is a speeded-up version of SIFT.
%
% In SIFT, Lowe approximated Laplacian of Gaussian with Difference of Gaussian
% for finding scale-space. SURF goes a little further and approximates LoG
% with Box Filter. Below image shows a demonstration of such an approximation.
% One big advantage of this approximation is that, convolution with box filter
% can be easily calculated with the help of integral images. And it can be
% done in parallel for different scales. Also the SURF rely on determinant of
% Hessian matrix for both scale and location.
%
% <<https://docs.opencv.org/3.2.0/surf_boxfilter.jpg>>
%
% For orientation assignment, SURF uses wavelet responses in horizontal and
% vertical direction for a neighbourhood of size 6s. Adequate Gaussian weights
% are also applied to it. Then they are plotted in a space as given in below
% image. The dominant orientation is estimated by calculating the sum of all
% responses within a sliding orientation window of angle 60 degrees.
% Interesting thing is that, wavelet response can be found out using integral
% images very easily at any scale. For many applications, rotation invariance
% is not required, so no need of finding this orientation, which speeds up the
% process. SURF provides such a functionality called Upright-SURF or U-SURF.
% It improves speed and is robust upto $\pm 15^{\circ}$. OpenCV supports both,
% depending upon the flag, |Upright|. If it is 0, orientation is calculated.
% If it is 1, orientation is not calculated and it is faster.
%
% <<https://docs.opencv.org/3.2.0/surf_orientation.jpg>>
%
% For feature description, SURF uses Wavelet responses in horizontal and
% vertical direction (again, use of integral images makes things easier). A
% neighbourhood of size 20sX20s is taken around the keypoint where |s| is the
% size. It is divided into 4x4 subregions. For each subregion, horizontal and
% vertical wavelet responses are taken and a vector is formed like this,
% $v=( \sum{d_x}, \sum{d_y}, \sum{|d_x|}, \sum{|d_y|})$. This when represented
% as a vector gives SURF feature descriptor with total 64 dimensions. Lower
% the dimension, higher the speed of computation and matching, but provide
% better distinctiveness of features.
%
% For more distinctiveness, SURF feature descriptor has an extended 128
% dimension version. The sums of $d_x$ and $|d_x|$ are computed separately for
% $d_y < 0$ and $d_y \geq 0$. Similarly, the sums of $d_y$ and $|d_y|$ are
% split up according to the sign of $d_x$ , thereby doubling the number of
% features. It doesn't add much computation complexity. OpenCV supports both
% by setting the value of flag |Extended| with 0 and 1 for 64-dim and 128-dim
% respectively (default is 128-dim).
%
% Another important improvement is the use of sign of Laplacian (trace of
% Hessian Matrix) for underlying interest point. It adds no computation cost
% since it is already computed during detection. The sign of the Laplacian
% distinguishes bright blobs on dark backgrounds from the reverse situation.
% In the matching stage, we only compare features if they have the same type
% of contrast (as shown in image below). This minimal information allows for
% faster matching, without reducing the descriptor's performance.
%
% <<https://docs.opencv.org/3.2.0/surf_matching.jpg>>
%
% In short, SURF adds a lot of features to improve the speed in every step.
% Analysis shows it is 3 times faster than SIFT while performance is
% comparable to SIFT. SURF is good at handling images with blurring and
% rotation, but not good at handling viewpoint change and illumination change.
%
% OpenCV provides SURF functionalities just like SIFT. You initiate a SURF
% object with some optional conditions like 64/128-dim descriptors,
% Upright/Normal SURF, etc. All the details are well explained in docs. Then
% as we did in SIFT, we can use |cv.SURF.detect, |cv.SURF.compute|, etc. for
% finding keypoints and descriptors.
%

%% Code

%%
% Read image as grayscale
img = cv.imread(fullfile(mexopencv.root(),'test','butterfly.jpg'), ...
    'Grayscale',true);

%%
% Detect keypoints using SURF Detector
detector = cv.SURF();
detector.HessianThreshold = 400;
tic
keypoints = detector.detect(img);
toc

%%
whos keypoints
disp(keypoints(1))

%%
% Draw keypoints
out = cv.drawKeypoints(img, keypoints);
imshow(out);

%%
% We increase the Hessian Threshold to some large value.
% This is just to avoid drawing too many keypoints.
% In real applications, it is better to have a value between 300 and 500,
% as we may need all those keypoints when matching.
detector.HessianThreshold = 50000;
keypoints = detector.detect(img);
fprintf('%d keypoints\n', numel(keypoints));

%%
out = cv.drawKeypoints(img, keypoints, ...
    'Color',[255 0 0], 'DrawRichKeypoints',true);
imshow(out);

%%
% Now we apply U-SURF, so that it won't find the orientation.
detector.Upright = true;
keypoints = detector.detect(img);
out = cv.drawKeypoints(img, keypoints, ...
    'Color',[255 0 0], 'DrawRichKeypoints',true);
imshow(out);

%%
% Finally we change the descriptor size to 128.
disp(detector.descriptorSize)
detector.Extended = true;
disp(detector.descriptorSize)
descriptors = detector.compute(img, keypoints);
whos descriptors


function[overlap] = computeBlobOverlapAny(propBlobsA, propBlobsB, imageSize)
% [overlap] = computeBlobOverlapAny(propBlobsA, propBlobsB, imageSize)
%
% Take Sel. Search regions and reconstruct whether blobs overlap at all.
% (result is a matrix).
%
% Copyright by Holger Caesar, 2015

if numel(imageSize) == 3,
    imageSize = imageSize(1:2);
end;
propCountA = numel(propBlobsA);
propCountB = numel(propBlobsB);

% Precompute blob inds
blobsIndsA = cell(propCountA, 1);
blobsIndsB = cell(propCountB, 1);
for i = 1 : propCountA,
    blob = propBlobsA(i);
    blobsIndsA{i} = int32(blobToImageInds(blob, imageSize));
end;
if isequal(propBlobsA, propBlobsB),
    blobsIndsB = blobsIndsA;
else
    for i = 1 : propCountB,
        blob = propBlobsB(i);
        blobsIndsB{i} = int32(blobToImageInds(blob, imageSize));
    end;
end;

overlap = computeBlobOverlapAnyPair(blobsIndsA, blobsIndsB); % Mex-version is 6 times faster for Barcelona dataset

% function[overlap] = computeBlobOverlapAnyPair(blobsIndsA, blobsIndsB) %#ok<DEFNU>
% % [overlap] = computeBlobOverlapAnyPair(blobsIndsA, blobsIndsB)
% %
% % Compute if two blobs overlap at all (boolean).
% % To be replaced by a mex function.
%
% % Initialize
% propCountA = numel(blobsIndsA);
% propCountB = numel(blobsIndsB);
% overlap = zeros(propCountA, propCountB); %Dense is fine
%
% for i = 1 : propCountA,
%     for j = 1 : propCountB,
%         overlap(i, j) = any(builtin('_ismemberhelper', blobsIndsA{i}, blobsIndsB{j}));
%     end;
% end;


function model = lfmExpandParam(model, params)

% LFMEXPANDPARAM Expand the given parameters into a LFM structure.
% FORMAT
% DESC takes the given vector of parameters and places them in the
% model structure, it then updates any stored representations that
% are dependent on those parameters, for example kernel matrices
% etc..
% ARG model : the model structure for which parameters are to be
% updated.
% ARG params : a vector of parameters for placing in the model
% structure.
% RETURN model : a returned model structure containing the updated
% parameters.
%
% SEEALSO : lfmCreate, lfmExtractParam, modelExtractParam, lfmUpdateKernels
%
% COPYRIGHT : Neil D. Lawrence, 2007

% KERN

params = real(params);
if isfield(model, 'fix')
  for i = 1:length(model.fix)
    params(model.fix(i).index) = model.fix(i).value;
  end
end

if length(params) ~= model.numParams
  error('Parameter vector is incorrect length');
end
startVal = 1;
endVal = model.kern.nParams;
model.kern = kernExpandParam(model.kern, params(startVal:endVal));

% The mass, springs and dampers  are actually stored in the kernel.
% We'll put them here as well for convenience.
for i = 1:model.kern.numBlocks
  model.mass(i) = model.kern.comp{i}.mass;
  model.spring(i) = model.kern.comp{i}.spring;
  model.damper(i) = model.kern.comp{i}.damper;
  model.sensitivity(i) = model.kern.comp{i}.sensitivity;
end

model = lfmUpdateKernels(model);
lengthObs = size(model.t, 1);
ind = 1:lengthObs;
for i = 1:model.numDisplacements
  if isfield(model, 'mu')
    model.m(ind) = model.y(ind) - model.mu(i)*ones(lengthObs, 1);
  else
    model.m(ind) = model.y(ind);
  end
  ind = ind + lengthObs;
end


clear; close all; clc;

%% Excel data load
WP = xlsread('H:\NeuroImage\WM_acc.xlsx', 3, 'B3:D19');
PM = xlsread('H:\NeuroImage\WM_acc.xlsx', 3, 'J3:L19');
LM = xlsread('H:\NeuroImage\WM_acc.xlsx', 3, 'R3:T19');

col=[253, 174, 97;
    171, 221, 164;
    43, 131, 186];
col=col/255;

i = [2, 0, -2];
%% boxplot [WP]
figure()
boxplot(WP, 'Notch', 'on')
set(gca, 'xtick', []);

set(findobj(gca,'type','line'),'linew',3);
h = findobj(gca,'Tag','Box');

for j=1:length(h)
    x = patch(get(h(j+i(j)),'XData'),get(h(j+i(j)),'YData'), col(j,:),'FaceAlpha',.5);
    % MODIFICATION TO SET THE LINE COLOR TO PATCH COLOR:
    h(length(h)-j+1).Color = x.FaceColor; % reordered to match
    hold on;

    x=repmat(1:3,length(WP),1);
    scatter(x(:,j),WP(:,j),'filled','MarkerEdgeColor',col(:,j), 'MarkerFaceColor',col(:,j),'jitter','on','jitterAmount',0.15);
end
% set(findobj(gca,'type','line')','linew',2);
% hLegend = legend(findall(gca,'Tag','Box'), {'BN','AN','24H'});

%% boxplot [PM]
figure()
boxplot(PM, 'Notch', 'on')
set(gca, 'xtick', []);

set(findobj(gca,'type','line'),'linew',3);
h = findobj(gca,'Tag','Box');

for j=1:length(h)
    x = patch(get(h(j+i(j)),'XData'),get(h(j+i(j)),'YData'), col(j,:),'FaceAlpha',.5);
    % MODIFICATION TO SET THE LINE COLOR TO PATCH COLOR:
    h(length(h)-j+1).Color = x.FaceColor; % reordered to match
    hold on;

    x=repmat(1:3,length(PM),1);
    scatter(x(:,j),PM(:,j),'filled','MarkerEdgeColor',col(:,j), 'MarkerFaceColor',col(:,j),'jitter','on','jitterAmount',0.15);
end
% set(findobj(gca,'type','line')','linew',2);
% hLegend = legend(findall(gca,'Tag','Box'), {'BN','AN','24H'});

%% boxplot [LM]
figure()
boxplot(LM, 'Notch', 'on')
set(gca, 'xtick', []);

set(findobj(gca,'type','line'),'linew',3);
h = findobj(gca,'Tag','Box');

for j=1:length(h)
    x = patch(get(h(j+i(j)),'XData'),get(h(j+i(j)),'YData'), col(j,:),'FaceAlpha',.5);
    % MODIFICATION TO SET THE LINE COLOR TO PATCH COLOR:
    h(length(h)-j+1).Color = x.FaceColor; % reordered to match
    hold on;

    x=repmat(1:3,length(LM),1);
    scatter(x(:,j),LM(:,j),'filled','MarkerEdgeColor',col(:,j), 'MarkerFaceColor',col(:,j),'jitter','on','jitterAmount',0.15);
end
% set(findobj(gca,'type','line')','linew',2);
% hLegend = legend(findall(gca,'Tag','Box'), {'BN','AN','24H'});


function [delta,h,alpha] = iswnbr(w,thetaSQR)
% [delta,h,alpha] = iswnbr(vSQR,thetaSQR)
%
% ISWNBR  Checks feasibility w.r.t. wide region/neighborhood of Sturm-Zhang.
%   vTAR:= (1-alpha)*max(h,v) projection v onto theta-central region
%   delta = (sqrt(n)/theta) * norm(vTAR - v) / norm(v)
%
% **********  INTERNAL FUNCTION OF SEDUMI **********
%
% See also sedumi

% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA
%

%Indicate to the user Matlab cannot find the SeDuMi binaries
sedumi_binary_error();

% ----------------------------------------
% r = n/thetaSQR
% hSQR = sumwNT/(r-|T|),  hubSQR = sumwNT/(r-|T| - |Q|)
% sumdifv = h*|T| - sumvT   (sumvT = sum(v_T), growing )
% sumdifw = hSQR*|T| - sumwT
% alpha = sumdifv / (r*h)
% deltaSQR = r * ( 2*alpha-alpha^2 - (1-alpha)^2 * sumdifw/gap )
% WE UPDATE sumdifv AND sumdifw IN A STABLE WAY
% ----------------------------------------
n = length(w); gap = sum(w);
sumwNT = gap;
r = n / thetaSQR;
cardT = 0; wQ = []; sumdifv = 0; sumdifw = 0;
cardQ = n;
hSQR = sumwNT / (r - cardT);  hubSQR = sumwNT / (r-(n-1));
for j = 1:n
    wj = w(j);
    if wj >= hubSQR              % wj >= hubSQR ==> not in T
        cardQ = cardQ - 1;
        hubSQR = sumwNT / (r-cardT-cardQ);
    elseif wj < hSQR             % wj < hSQR ==> in T
        cardT = cardT + 1;
        cardQ = cardQ - 1;
        hubSQR = (1-wj/sumwNT) * hubSQR;
        sumwNT = sumwNT - wj;
        oldhSQR = hSQR;
        hSQR = sumwNT / (r - cardT);
        sumdifw = sumdifw + (oldhSQR-wj) + cardT * (hSQR-oldhSQR);
        sumdifv = sumdifv + (sqrt(oldhSQR)-sqrt(wj)) + ...
            cardT * (sqrt(hSQR)-sqrt(oldhSQR));
    else                    % Inconclusive: j in Q
        wQ = [wQ;wj]; %#ok
    end % if
end % for
% ----------------------------------------
% The same treatment for the Q set, but we
% sort the (presumably short) wQ first.
% ----------------------------------------
if ~isempty(wQ)
    sort(wQ);
    STOP = 0; j = 1;
    while ~STOP
        wj = wQ(j);
        if wj >= hSQR
            STOP = 1;
        else
            cardT = cardT + 1;
            sumwNT = sumwNT - wj;
            oldhSQR = hSQR;
            hSQR = sumwNT / (r - cardT);
            sumdifw = sumdifw + (oldhSQR-wj) + cardT * (hSQR-oldhSQR);
            sumdifv = sumdifv + (sqrt(oldhSQR)-sqrt(wj)) + ...
                cardT * (sqrt(hSQR)-sqrt(oldhSQR));
            j = j+1;
            if j > length(wQ)
                STOP = 1;
            end
        end
    end
end % treatment Q
% ----------------------------------------
% alpha = sumdifv/(r*h)
% deltaSQR = r * ( 2*alpha-alpha^2 - (1-alpha)^2 * sumdifw/gap )
%  (THE ABOVE DIFFERENCE SHOULD NOT BE NUMERICALLY DANGEROUS,
%    SINCE alpha IS *SIGNIF* BIGGER THAN sumdifw/gap )
% ----------------------------------------
h = sqrt(hSQR);
alpha = sumdifv/ (r*h);
deltaSQR = alpha*(2-alpha) - (1-alpha)^2 * sumdifw/gap;
delta = sqrt(r*deltaSQR);


function [vX] = spm_vec(X,varargin)
% Vectorise a numeric, cell or structure array - a compiled routine
% FORMAT [vX] = spm_vec(X)
% X  - numeric, cell or stucture array[s]
% vX - vec(X)
%
% See spm_unvec
%__________________________________________________________________________
%
% e.g.:
% spm_vec({eye(2) 3}) = [1 0 0 1 3]'
%__________________________________________________________________________
% Copyright (C) 2005-2013 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_vec.m 6110 2014-07-21 09:36:13Z karl $

%error('spm_vec.c not compiled - see Makefile')

% initialise X and vX
%--------------------------------------------------------------------------
if nargin > 1
    X = [{X},varargin];
end

% vectorise numerical arrays
%--------------------------------------------------------------------------
if isnumeric(X)
    vX = X(:);

% vectorise logical arrays
%--------------------------------------------------------------------------
elseif islogical(X)
    vX = X(:);

% vectorise structure into cell arrays
%--------------------------------------------------------------------------
elseif isstruct(X)
    vX = [];
    f   = fieldnames(X);
    X    = X(:);
    for i = 1:numel(f)
        vX = cat(1,vX,spm_vec({X.(f{i})}));
    end

% vectorise cells into numerical arrays
%--------------------------------------------------------------------------
elseif iscell(X)
    vX   = [];
    for i = 1:numel(X)
        vX = cat(1,vX,spm_vec(X{i}));
    end
else
    vX = [];
end


function [Vm]=patchCentre(F,V)

% function [Vm]=patchCentre(F,V)
% ------------------------------------------------------------------------
%
%
%
% Change log:
% 2014
% 2019/04/22 Fixed such that output matches dimentionality of input (output
% used to always be 3D even if input is 2D)
% 2019/04/22 Updated to handle cell input
% ------------------------------------------------------------------------

%%

if isa(F,'cell') %Cell of faces (e.g. potentially of different types)
    Vm=repmat({zeros(size(F,1),3)},size(F)); %Allocate Vm to be a cell like F
    for q=1:1:numel(F) %Loop over face sets
        Vm{q}=patchCentre(F{q},V); %Override cell entries by face centres
    end
else
    Vm=zeros(size(F,1),size(V,2)); %Allocate memory for
    for q=1:1:size(V,2)
        X=V(:,q);
        if size(F,1)==1 %Treat single element case since MATLAB is not consistent
            Vm(:,q)=mean(X(F));
        else
            Vm(:,q)=mean(X(F),2);
        end
    end
end

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function grad = getGradient(problem, x, storedb, key)
% Computes the gradient of the cost function at x.
%
% function grad = getGradient(problem, x)
% function grad = getGradient(problem, x, storedb)
% function grad = getGradient(problem, x, storedb, key)
%
% Returns the gradient at x of the cost function described in the problem
% structure.
%
% storedb is a StoreDB object, key is the StoreDB key to point x.
%
% See also: getDirectionalDerivative canGetGradient

% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, Dec. 30, 2012.
% Contributors:
% Change log:
%
%   April 3, 2015 (NB):
%       Works with the new StoreDB class system.
%
%  June 28, 2016 (NB):
%       Works with getPartialGradient.
%
%   Nov. 1, 2016 (NB):
%       Added support for gradient from directional derivatives.
%       Last resort is call to getApproxGradient instead of an exception.
%
%   Sep. 6, 2018 (NB):
%       The gradient is now cached by default. This is made practical by
%       the new storedb 'remove' functionalities that keep the number of
%       cached points down to a minimum. If the gradient is obtained via
%       costgrad, the cost is also cached.
%
%   Feb. 10, 2020 (NB):
%       Allowing M.egrad2rgrad to take (storedb, key) as extra inputs.

    % Allow omission of the key, and even of storedb.
    if ~exist('key', 'var')
        if ~exist('storedb', 'var')
            storedb = StoreDB();
        end
        key = storedb.getNewKey();
    end

    % Contrary to most similar functions, here, we get the store by
    % default. This is for the caching functionality described below.
    store = storedb.getWithShared(key);
    store_is_stale = false;

    % If the gradient has been computed before at this point (and its
    % memory is still in storedb), then we just look up the value.
    force_grad_caching = true;
    if force_grad_caching && isfield(store, 'grad__')
        grad = store.grad__;
        return;
    end

    % We don't normally compute the cost value, but if we get it as a side
    % result, then we may as well take note of it for caching.
    cost_computed = false;

    if isfield(problem, 'grad')
    %% Compute the gradient using grad.

        % Check whether this function wants to deal with storedb or not.
        switch nargin(problem.grad)
            case 1
                grad = problem.grad(x);
            case 2
                [grad, store] = problem.grad(x, store);
            case 3
                % Pass along the whole storedb (by reference), with key.
                grad = problem.grad(x, storedb, key);
                % The store structure in storedb might have been modified
                % (since it is passed by reference), so before caching
                % we'll have to update (see below).
                store_is_stale = true;
            otherwise
                up = MException('manopt:getGradient:badgrad', ...
                    'grad should accept 1, 2 or 3 inputs.');
                throw(up);
        end

    elseif isfield(problem, 'costgrad')
    %% Compute the gradient using costgrad.

        % Check whether this function wants to deal with storedb or not.
        switch nargin(problem.costgrad)
            case 1
                [cost, grad] = problem.costgrad(x);
            case 2
                [cost, grad, store] = problem.costgrad(x, store);
            case 3
                % Pass along the whole storedb (by reference), with key.
                [cost, grad] = problem.costgrad(x, storedb, key);
                store_is_stale = true;
            otherwise
                up = MException('manopt:getGradient:badcostgrad', ...
                    'costgrad should accept 1, 2 or 3 inputs.');
                throw(up);
        end

        cost_computed = true;

    elseif canGetEuclideanGradient(problem)
    %% Compute the Riemannian gradient using the Euclidean gradient.

        egrad = getEuclideanGradient(problem, x, storedb, key);
        % Convert to the Riemannian gradient
        switch nargin(problem.M.egrad2rgrad)
            case 2
                grad = problem.M.egrad2rgrad(x, egrad);
            case 4
                grad = problem.M.egrad2rgrad(x, egrad, storedb, key);
            otherwise
                up = MException('manopt:getGradient:egrad2rgrad', ...
                    'egrad2rgrad should accept 2 or 4 inputs.');
                throw(up);
        end
        store_is_stale = true;

    elseif canGetPartialGradient(problem)
    %% Compute the gradient using a full partial gradient.

        d = problem.ncostterms;
        grad = getPartialGradient(problem, x, 1:d, storedb, key);
        store_is_stale = true;

    elseif canGetDirectionalDerivative(problem)
    %% Compute gradient based on directional derivatives; expensive!

        B = tangentorthobasis(problem.M, x);
        df = zeros(size(B));
        for k = 1 : numel(B)
            df(k) = getDirectionalDerivative(problem, x, B{k}, storedb, key);
        end
        grad = lincomb(problem.M, x, B, df);
        store_is_stale = true;

    else
    %% Attempt the computation of an approximation of the gradient.

        grad = getApproxGradient(problem, x, storedb, key);
        store_is_stale = true;

    end

    % If we are not sure that the store structure is up to date, update.
    if store_is_stale
        store = storedb.getWithShared(key);
    end

    % Cache here.
    if force_grad_caching
        store.grad__ = grad;
    end
    % If we got the gradient via costgrad, then the cost has also been
    % computed and we can cache it.
    if cost_computed
        store.cost__ = cost;
    end

    storedb.setWithShared(store, key);

end


function getdata (option)
global A opt leg label

[fname,pname] = uigetfile({'*.csv';'*.xls';'*.txt'},'Select File');
dbfile= strcat(pname,fname);
if length(dbfile) == 0 return; end

% Check if the file IS there
d= dir(fname);
if isempty(d.name)
	errordlg ('Sorry, don''t find that file','Error');
	return;
end

% Open the file
fdata= fopen(fname,'rt');
A= [];
leg= {};

% Put a comma before first column. This is required to use tblread, get
% propper reading of column names but avoid that the user has to
% include it
fileout= fopen('Qdata.csv','wt');
while 1
	s = fgets(fdata);
	if ~ischar(s), break, end
	fprintf(fileout,'%s%s',',',s);
end
fclose(fdata);
fname= 'Qdata.csv';

% Read it
switch option
	case 1
		[A,leg]= tblread(fname,'comma');
	case 2
		[A,leg]= xlsread(dbfile);
	case 3
		[A,leg]= xlsread(dbfile,-1)
end

%Generate cell string array fot title if there aren't any
if isempty(leg) leg= cellstr( num2str( flipud(rot90([1:size(A,2)])) ) ); end

% Choosing default x-y-z columns
opt.xc= 1;
switch size(A,2)
	case 1
		opt.yc= 1;
		opt.ec= 1;
		opt.zc= 1;
	case 2
		opt.yc= 2;
		opt.ec= 2;
		opt.zc= 2;
	otherwise
		opt.yc= [2:size(A,2)-1];
		opt.ec= [fix(size(A,2)/2):size(A,2)];
		opt.zc= [3:size(A,2)];
end

return


function f = write_mhd(filename, image, varargin)
% Write mhd
% arguments:
% write_mhd(filename,image)
% write_mhd(filename,image, param, value,...)
% params and default value:
%   'NDims'                     =   3
%   'BinaryData'                =   true
%   'BinaryDataByteOrderMSB'    =   false
%   'CompressedData'            =   false
%   'TransformMatrix'           =   1 0 0 0 1 0 0 0 1 (coherent with NDims)
%   'CenterOfRotation'          =   0 0 0 (coherent with NDims)
%   'AnatomicalOrientation'     =   RAI
%   'ElementNumberOfChannels'   =   1
%   'ElementType'               =   MET_FLOAT
%
% modifications by Thomas Kuestner, 2015
% ---------------------------------------------------------------------

% revise this
element_types=struct('uchar','MET_UCHAR','double','MET_DOUBLE','single','MET_FLOAT','logical','MET_CHAR','int8','MET_UCHAR','uint8','MET_UCHAR','int16','MET_SHORT','uint16','MET_USHORT','int32','MET_INT','uint32','MET_UINT');
% element_types=struct('double','MET_DOUBLE','int8','MET_CHAR','uint8','MET_UCHAR','int16','MET_SHORT','uint16','MET_USHORT','int32','MET_INT','uint32','MET_UINT');

%Look for arguments
NDims                       = numel(image.size);
BinaryData                  = 'True';
BinaryDataByteOrderMSB      = 'False';
CompressedData              = 'False';

TransformMatrix  = num2str(reshape(image.orientation,1,NDims*NDims)); %'1 0 0 0 1 0 0 0 1';% (coherent with NDims)
CenterOfRotation = num2str(zeros(1,NDims)) ;

AnatomicalOrientation =   'RAI';
if (isa(image,'VectorImageType') || isfield(image,'datax'))
    ElementNumberOfChannels = 3;
else
    ElementNumberOfChannels = 1;
end

%ElementType =getfield(element_types,class(image.data));
EType ='double';

for i=1:size(varargin,2)
    switch (lower(varargin{i}))
        case 'ndims'
            NDims =  varargin{i+1};
        case 'binarydata'
            BinaryData  =   varargin{i+1};
        case 'binarydatabyteordermsb'
            BinaryDataByteOrderMSB =   varargin{i+1};
        case 'compresseddata'
            CompressedData =   varargin{i+1};
        case 'transformmatrix'
            TransformMatrix =   varargin{i+1};
        case 'centerofrotation'
            CenterOfRotation =   varargin{i+1};
        case 'anatomicalorientation'
            AnatomicalOrientation =   varargin{i+1};
        case 'elementnumberofchannels'
            ElementNumberOfChannels =   varargin{i+1};
        case 'elementtype'
            EType =  varargin{i+1};
    end
end
ElementType =  element_types.(EType );
% Extract path and filenames---
path_ = regexp(filename,'/','split');
path = [];
for i=2:(size(path_,2)-1)

    path = [path '/' path_{i}];
end

raw_ = regexp(filename,'\.','split');
raw = [];
for i=1:(size(raw_,2)-1)
    raw = [raw  raw_{i} '.'];
end
rawfile = [raw 'raw'];
rawfilename_ = regexp(rawfile,'/','split');
rawfilename = rawfilename_{size(rawfilename_,2)};
% write *.mhd file
fid=fopen(filename,'w','native');
fprintf(fid,'ObjectType = Image\n');
fprintf(fid,'NDims = %d\n',NDims);
fprintf(fid,'BinaryData = %s\n',BinaryData);
fprintf(fid,'BinaryDataByteOrderMSB = %s\n',BinaryDataByteOrderMSB);
fprintf(fid,'CompressedData = %s\n',CompressedData);
fprintf(fid,'TransformMatrix = %s\n',TransformMatrix);
fprintf(fid,'CenterOfRotation = %s\n',CenterOfRotation);
fprintf(fid,'AnatomicalOrientation = %s\n',AnatomicalOrientation);
fprintf(fid,'%s\n',['Offset = ' num2str(image.origin(:)') ]);
fprintf(fid,'%s\n',['ElementSpacing = ' num2str(image.spacing(:)') ]);
fprintf(fid,'%s\n',['DimSize = ' num2str(image.size(:)') ]);

fprintf(fid,'ElementNumberOfChannels = %d\n',ElementNumberOfChannels);
fprintf(fid,'ElementType = %s\n',ElementType);
fprintf(fid,'ElementDataFile = %s\n',rawfilename);

fclose(fid);

% write *.raw file

%dataToWrite=image.data;

%if (islogical(dataToWrite))
%     dataToWrite = cast(dataToWrite,'uint8');
% else

fid=fopen(rawfile,'w','native');
if (ElementNumberOfChannels ==1)
    %fwrite(fid,image.data,class(dataToWrite) );
    dataAll = cast(image.data,EType);
elseif (ElementNumberOfChannels==2)
    %do nothing
elseif (ElementNumberOfChannels==3)
    %write point per point
    dataAll = cast(permute(cat(NDims+1,image.datax,  image.datay, image.dataz),...
        [NDims+1 1:NDims]),EType);
elseif (ElementNumberOfChannels==4)
    %TODO
end
fwrite(fid,dataAll,EType);
fclose(fid);

f=fid;

end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  qdd = call_direct_dynamics_fast(input)
%  Auxiliar function for the simulink model SIMULATE_ROBOT_AND_CONTROLLER.
%  Rearranges the inputs coming from the simulink model and calls the
%  function accel.
%  As a result the instantaneous acceleration at each joint is returned.
%
%  See also ACCEL.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

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

global robot

% torque = input(1:2);   % Input torque at each joint
% q   = input(3:4);	   % Joint positions
% qd  = input(5:6);	   % Joint speeds
% fe=[0 0 0 0 0 0]'; %external forces applied
% torque
%
% % Compute acceleration
% qdd = forwarddynamics_2dofplanar(robot, q, qd, torque, 9.81, fe)

% global robot

%set friction to zero
%robot.friction = 0;

torque = input(1:2);   % Input torque at each joint
q   = input(3:4);	   % Joint positions
qd  = input(5:6);	   % Joint speeds

g = [0 -9.81 0]';
% Compute acceleration
qdd = accel(robot, q, qd, torque, g);


function [M, S] = instantiate(disc)
%INSTANTIATE   Convert a COEFFSDISCRETIZATION to discrete form.
%   M = INSTANTIATE(DISC) converts each item DISC.SOURCE to discrete form
%   using the information in discretization DISC. The result M is return a cell
%   array if DISC.SOURCE has more than one component.
%
%   [M, S] = INSTANTIATE(DISC) retusn a second output, S, which is a cell array
%   containing the dscrete form of the conversion operator for each block
%   of DISC.SOURCE. Only used by ULTRAS class.
%
%   DISC.SOURCE may be one or a cell array of:
%      linBlock (becomes a matrix)
%      chebfun (becomes a vector)
%      numeric (not changed)

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

data = disc.source;
if ( isa(data, 'chebmatrix') )
    data = data.blocks;
end

if ( iscell(data) )
    M = cell(size(data));
    S = cell(size(data));
    for j = 1:size(data, 1)
        for k = 1:size(data, 2)
            discJK = extractBlock(disc, j, k);
            [M{j,k}, S{j,k}] = instantiate(discJK);
        end
    end
    return
else
    [M, S] = instantiateOne(disc, data);
end

end

function [M, S] = instantiateOne(disc, item)
% Instantiate one block of data.

if ( isa(item, 'operatorBlock') )
    % Convert a square block.

    if ( ~isempty(disc.coeffs) )
        % Coefficients of the block are available, convert to a diffmat.
        [M, S] = quasi2diffmat(disc);
    else
        [M, S] = convertOperator(disc, item);
    end

elseif ( isa(item, 'functionalBlock') )
    % Convert a row block.

    [M, S] = convertFunctional(disc, item);

elseif ( isa(item, 'chebfun') )
    % Block is a CHEBFUN. Convert to value space.

    M = toValues(disc, item);
    if ( item.isTransposed )
        M = M.';
    end
    S = zeros(size(M));

elseif ( isnumeric(item) )
    % Block is numeric, don't need to do much.

    M = item;
    S = 1;

else

    error('COEFFSDISCRETIZATION:instantiate:inputType', ...
        'Unrecognized item type.')

end

end

function [M, S] = convertFunctional(disc, item)
    % Developer note: In general we can't represent functional
    % blocks via coeffs. To get around this we instantiate a
    % VALSDISCRETIZAION and convert it to coefficient space
    % using COEFFS2VALS(). (Note it's COEFFS2VALS() rather than
    % VALS2COEFFS() because it's a right-multiply (I think..).)

    % For convenience:
    dim = disc.dimension;
    dom = disc.domain;

    % Create a TECH and a VALSDISCRETIZATION:
    tech = disc.returnTech;
    tech = tech();
    valsDisc = tech.returnValsDisc;
    valsDisc = valsDisc(item, dim, dom);
    M = matrix(valsDisc);

    % Convert from value-space to coeff-space using COEFFS2VALS.
    cumsumDim = [0, cumsum(dim)];
    tmp = cell(1, numel(dom)-1);
    for l = 1:numel(tmp)
        Ml = M(cumsumDim(l) + (1:dim(l)));
        Ml = rot90(Ml);
        tmp{l} = rot90(tech.coeffs2vals(Ml), -1);
    end

    M = cell2mat(tmp);
    S = zeros(size(M));
end


function [out] = vertcat_fields_domains(s, exclude_last)

if nargin < 2 || isempty(exclude_last)
    exclude_last = false;
end

out = struct();
fields = fieldnames(s);
count = length(fields);
for i = 1:count
    field = fields{i};
    if ismatrix(s(1).(field))
        x = vertcat_domains(exclude_last, s.(field));
        if exclude_last
            x(end, :) = [];
        end
        out.(field) = x;
    end
end

end


function opts = updateMovie(S, dt, p, opts, t, v, compGrid, plotGrid)
%UPDATEMOVIE   Update the movie when solving a PDE specified by a SPINOP.

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

% Set-up:
nVars = S.numVars;
Ylim = opts{1};
dataToPlot = opts{2};
xx = compGrid{1};
xxx = plotGrid{1};
N = size(xx, 1) - 1;
Nplot = size(xxx, 1) - 1;

for k = 1:nVars

    % Extract each variable:
    idx = (k-1)*N + 1;
    vv = dataToPlot(v(idx:idx+N-1));
    vv = [vv; vv(1)]; %#ok<*AGROW> add repeated values (periodic endpoints)

    % Change axes if necessary:
    if ( nargout == 1 )
        minvnew = min(dataToPlot(vv));
        maxvnew = max(dataToPlot(vv));
        if ( maxvnew > Ylim(2*(k-1) + 2) )
            vscalenew = max(abs(minvnew), maxvnew);
            Ylim(2*(k-1) + 2) = maxvnew + .1*vscalenew;
        end
        if ( minvnew < Ylim(2*(k-1) + 1) )
            vscalenew = max(abs(minvnew), maxvnew);
            Ylim(2*(k-1) + 1) = minvnew - .1*vscalenew;
        end
    end

    % Interpolate each variable on a finer grid:
    if ( Nplot > N )
        vvv = interp1(xx, vv, xxx, 'spline');
    else
        vvv = vv;
    end

    % Update each variable:
    set(p{1,k}, 'ydata', vvv)
    set(p{1,k}.Parent, 'ylim', [Ylim(2*(k-1) + 1), Ylim(2*(k-1) + 2)])

    % Update each title:
    titleString = sprintf('N = %i (DoFs = %i), dt = %1.1e, t = %.4f', N, ...
        nVars*N, dt, t);
    set(p{2,k}, 'String', titleString)
    drawnow

end

% Update outputs:
opts{1} = Ylim;

end