filename = 'CantileverSquareSym';%'CantileverSquareNewFine';%'LshapeTriFine';%'CantileverSquareNew';'ArchTriFine';%'CantileverSquare';%'ArchTriFine';%'CantileverSquare';%'Lshape';%'LshapeTriFine';%'CantileverSquareSmall';%'';%'Lshape';'CantileverSquare';'Lshape';%'CantileverSquare';%'LshapeFine';%'Bridge_quad_coarse';%'Arch_quad_coarse';%'BridgeCool_Quadrilateral_Bilinear_Structured_Coarse';%'Bridge';%'CantileverSquareSmall';
ptype = 'MACRO';
initial_case = 'given';
% m1 = 0.0101;
% m2 = 0.0101;
m1 = 0.8;
m2 = 0.8;
%cost = {'compliance'};
cost = {'stressNorm'};
%cost = {'stressNorm','compliance'};
%weights = [0.55,0.45];
weights = 1;
constraint = {'volumeConstraint'};
filterType = 'P1';
constraint_case = 'EQUALITY';

Vfrac_initial = 0.3;
optimality_initial = 1e-5;
constr_initial = 1e-5;

Vfrac_final = 0.3;
optimality_final = 1e-5;
constr_final = 1e-5;

stressNormExponent_initial = 2;
stressNormExponent_final = 32;

optimizer = 'DualNestedInPrimal';
optimizerUnconstrained = 'PROJECTED GRADIENT';

designVariable = 'MicroParams';
ub = 0.989;
lb = 0.011;
homegenizedVariablesComputer = 'ByVademecum';
%
vademecumFileName = 'SuperEllipseQMax';
%vademecumFileName = 'SuperEllipseQ2';
%vademecumFileName = 'SuperEllipseQOptAnalytic';
%
% designVariable = 'Density';
% homegenizedVariablesComputer = 'ByInterpolation';
% method = 'SIMPALL';
% materialType = 'ISOTROPIC';

kfrac = 2;
nsteps = 50;

plotting = false;
printing = true;
monitoring = true;
monitoring_interval = 1;
maxiter = 500;

line_search_initiator = 'INCREASING LAST STEP';
incrementFactor = 2;


% Check the configuration section to make the necessary adjustments to
% run this script.

% @
% Copyright (C) 2017 Jonas Ruesch
%
% 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/>.
% @

% Configuration
% ===================================================================================
tornadoDirectory = 'F:\svn\dev\matlab\tornado\T135_export'; % where is Tornado installed?
nameTornadoAircraftGeometry = 'ExperimentalCarrier'; % which Tornado model to use?
estimatedVelocity = 12; % 12; % the velocity at which aerodynamic coefficients are computed.
velocityDeviationTol = 0.5; % how much the found trimmed velocity can differ from the estimated velocity to accept the solution.
airDensity = 1.225;
elevatorFlapIndex = 1; % which is the elevator flap in the Tornado model?
rudderFlapIndex = 2; % which is the rudder flap in the Tornado model?
centerOfGravity = 0.092; % in meters from zero of Tornado aircraft model reference frame. Tornado x-axis extends aft (!) -> positive.
mass = 1.56; % aircraft mass in kg (overwrites the value set in the Tornado model).
InertiaTensor = [1 0 0; 0 1 0; 0 0 1]; % inertia tensor (TODO: compute a realistic one :)
% The alpha-sweep configuration
alphaStart = 4; %2;
alphaEnd = 6; % 6;
numAlphas = 5;
% The beta-sweep configuration
betaStart = -1;
betaEnd = 1;
numBetas = 5;
computeStaticMargin = 0; % [0/1]
% ===================================================================================

nameLongitudinalModel = 'ExperimentalCarrier_longitudinal';
nameLateralModel = 'ExperimentalCarrier_lateral';

disp(' ');

% Compute longitudinal and lateral LTIs for trimmed gliding.
[ltiLongitudinal, trimmedStateVariablesLongitudinal, ltiLateral, trimmedStateVariablesLateral, Cm_longitudinal, Cn_lateral] = computeLTIs(...
    tornadoDirectory, ... % absolute path to the Tornado root directory
    nameTornadoAircraftGeometry, ... % the name of the Tornado geometry file
    nameLongitudinalModel, ... % the name of the Simulink long. model.
    nameLateralModel,... % the name of the Simulink lateral model.
    alphaStart, alphaEnd, ... % range in degrees over which coefficients are computed for the longitudinal model
    numAlphas, ... % the number of alphas to sample
    betaStart, betaEnd, ... range in degrees over which coefficients are computed for the lateral model
    numBetas, ... the number of betas to sample
    estimatedVelocity, ... % velocity in m/s for which aerodyn. coeffs. are computed
    velocityDeviationTol, ... % factor [0 ... 1].
    airDensity, ... % kg/m^3 -> 1.225 at sea level
    elevatorFlapIndex, ...
    rudderFlapIndex, ...
    mass, ...
    centerOfGravity, ...
    InertiaTensor); % inertia tensor
trimmedAlphaRad = atan(trimmedStateVariablesLongitudinal(2)/trimmedStateVariablesLongitudinal(1)); % atan(w/u);
trimmedBetaRad = atan(trimmedStateVariablesLateral(1)/trimmedStateVariablesLongitudinal(1)); % atan(w/v);

% Compute static margin of the aircraft.
if(computeStaticMargin)
    disp('Computing static margin of longitudinal dynamics...');
    [ac, staticMarginMAC, staticMarginInMeters] = computeStaticMargin(nameTornadoAircraftGeometry, ...
        estimatedVelocity, airDensity, tornadoDirectory, centerOfGravity);
    disp(['Static margin as MAC factor  : ' num2str(staticMarginMAC)]);
    disp(['Static margin (sm)      (m)  : ' num2str(staticMarginInMeters)]);
    disp(['Aerodynamic center (ac) (m)  : ' num2str(ac)]);
    disp(['ac - sm = center of gravity  : ' num2str(ac - staticMarginInMeters)]);
end

% Longitudinal
% ========================================================================
% disp('The longitudinal LTI:');
% ltiLongitudinal

% sort complex numbers
polesLongitudinal = cplxpair(pole(ltiLongitudinal));  % sort first complex pairs (each with negative imag. part first, then pure real (ascending?)).

% Poles Map
figure();
h = subplot(2,2,1);
hold on;
plot(h, real(polesLongitudinal(1)), imag(polesLongitudinal(1)), 'rx');
plot(h, real(polesLongitudinal(2)), imag(polesLongitudinal(2)), 'bx');
plot(h, real(polesLongitudinal(3)), imag(polesLongitudinal(3)), 'ro');
plot(h, real(polesLongitudinal(4)), imag(polesLongitudinal(4)), 'bo');
hold off;
legend('phugoid mode 1', 'phugoid mode 2', 'short period mode 1', 'short period mode 2');
title('Longitudinal Poles Map');
xlabel('re');
ylabel('im');

% Step response
% Remember: for a trimmed glide, LTI state variables are all 0. Thus, the plot
% shows the resulting deviation of state variables from the trimmed state.
% Also note: with the current model (very little air resistance -> very
% good gliding ratio, the non-linear matlab model shows that it is sensible
% that w (the velocity in body-z) is becoming negative (moving 'upwards' in
% body-z).
h = subplot(2,2,2);
elevatorDeflectionStep = 2*pi/180;
stepOpt = stepDataOptions('StepAmplitude', elevatorDeflectionStep); % step response for elevatorDeflectionStep radian elevator deflection
stepplot(h, ltiLongitudinal, stepOpt);
title('Longitudinal Step Response');
hAllAxes = findobj(gcf,'type','axes');
hLeg = findobj(hAllAxes,'tag','legend');
hAxes = setdiff(hAllAxes,hLeg); % All axes which are not
for k=1:length(hAxes)
   if ~isempty(strfind(hAxes(k).YLabel.String, '(1)'))
       hAxes(k).Title.String = ['State change for an elevator step of ' num2str(elevatorDeflectionStep*180/pi) ' degrees'];
       hAxes(k).YLabel.String = 'u (m/s)'; % velocity in body x-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(2)'))
       hAxes(k).YLabel.String = 'w (m/s)'; % velocity in body z-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(3)'))
       hAxes(k).YLabel.String = 'q (rad/s)'; % rotation velocity around y-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(4)'))
       hAxes(k).YLabel.String = 'theta (rad)'; % angle body-x vs earth-x
   end
end

% Impulse response
h = subplot(2,2,3);
impulseplot(h, ltiLongitudinal);
title('Longitudinal Impulse Response');
hAllAxes = findobj(gcf,'type','axes');
hLeg = findobj(hAllAxes,'tag','legend');
hAxes = setdiff(hAllAxes,hLeg); % All axes which are not
for k=1:length(hAxes)
   if ~isempty(strfind(hAxes(k).YLabel.String, '(1)'))
       hAxes(k).Title.String = 'State change for an elevator dirac impulse';
       hAxes(k).YLabel.String = 'u (m/s)'; % velocity in body x-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(2)'))
       hAxes(k).YLabel.String = 'w (m/s)'; % velocity in body z-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(3)'))
       hAxes(k).YLabel.String = 'q (rad/s)'; % rotation velocity around y-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(4)'))
       hAxes(k).YLabel.String = 'theta (rad)'; % angle body-x vs earth-x
   end
end

% Plot pitch moment curve
h = subplot(2,2,4);
hold on;
plot(h, [alphaStart:(alphaEnd-alphaStart)/(numAlphas-1):alphaEnd], Cm_longitudinal, 'r-');
plot(h, trimmedAlphaRad*180/pi, 0, 'bx');
hold off;
legend('Cm', ['trimmed alpha = ' num2str(trimmedAlphaRad*180/pi) ' (deg)']);
title('Pitch moment');
xlabel('alpha');
ylabel('Cm');

% Compute damping, frequency, period from poles. See also p83 in Caughey.

% Short period poles
polesShortPeriod = polesLongitudinal(3:4); % choose last ones from sorted complex numbers
polesShortPeriodReal = real(polesShortPeriod);
polesShortPeriodImag = imag(polesShortPeriod);

Damping_sp = sqrt(1./(1+(polesShortPeriodImag./polesShortPeriodReal).^2)); % Damping ratio
Frequency_sp = -polesShortPeriodReal./Damping_sp; % Undampted, natural frequency per second
Period_sp = 2*pi./(Frequency_sp.*sqrt(1-Damping_sp.^2)); % seconds
Cycles_half_sp = ((log(2))/(2*pi))*sqrt(1-Damping_sp.^2)./Damping_sp; % Number of cycles to damp to half the amplitude

% Output result for longitudinal trimmed state
disp('Short Period Mode Properties (longitudinal): ');
disp('                                                 Pole 1      Pole 2');
disp('==============================================================================');
disp(sprintf(['Damping ratio                                 : ' num2str(Damping_sp(:)')]));
disp(sprintf(['Undampted, natural frequency             (1/s): ' num2str(Frequency_sp(:)')]));
disp(sprintf(['Period                                     (s): ' num2str(Period_sp(:)')]));
disp(sprintf(['Num. cycles to damp to half the amplitude     : ' num2str(Cycles_half_sp(:)')]));
disp(' ');

% Phugoid poles
polesPhugoid = polesLongitudinal(1:2); % choose first ones from sorted complex numbers
polesPhugoidReal = real(polesPhugoid);
polesPhugoidImag = imag(polesPhugoid);

Damping_ph = sqrt(1./(1+(polesPhugoidImag./polesPhugoidReal).^2)); % Damping ratio
Frequency_ph = -polesPhugoidReal./Damping_ph; % Undampted, natural frequency per second
Period_ph = 2*pi./(Frequency_ph.*sqrt(1-Damping_ph.^2)); % seconds
Cycles_half_ph = ((log(2))/(2*pi))*sqrt(1-Damping_ph.^2)./Damping_ph; % Number of cycles to damp to half the amplitude

% Output result for longitudinal trimmed state
disp('Phugoid Mode Properties (longitudinal): ');
disp('                                                 Pole 1      Pole 2');
disp('==============================================================================');
disp(sprintf(['Damping ratio                                 : ' num2str(Damping_ph(:)')]));
disp(sprintf(['Undampted, natural frequency             (1/s): ' num2str(Frequency_ph(:)')]));
disp(sprintf(['Period                                     (s): ' num2str(Period_ph(:)')]));
disp(sprintf(['Num. cycles to damp to half the amplitude     : ' num2str(Cycles_half_ph(:)')]));
disp(' ');

% Lateral
% ========================================================================

%disp('The lateral LTI:');
%ltiLateral

% sort complex numbers
polesLateral = cplxpair(pole(ltiLateral)); % sort first complex pairs (each with negative imag. part first, then pure real (ascending?)).

% Poles Map
figure();
h = subplot(2,2,1);
hold on;
plot(h, real(polesLateral(1)), imag(polesLateral(1)), 'rx');
plot(h, real(polesLateral(2)), imag(polesLateral(2)), 'bx');
plot(h, real(polesLateral(3)), imag(polesLateral(3)), 'ro');
plot(h, real(polesLateral(4)), imag(polesLateral(4)), 'bo');
hold off;
legend('dutch roll mode 1', 'dutch roll mode 2', 'rolling mode', 'spiral mode');
title('Lateral Poles Map');
xlabel('re');
ylabel('im');

% Step response
% Remember: for a trimmed glide, LTI state variables are all 0. Thus, the plot
% shows the resulting deviation of state variables from the trimmed state.
h = subplot(2,2,2);
rudderDeflectionStep = 2*pi/180;
stepOpt = stepDataOptions('StepAmplitude', rudderDeflectionStep); % step response for elevatorDeflectionStep radian elevator deflection
stepplot(h, ltiLateral, stepOpt);
title('Lateral Step Response');
hAllAxes = findobj(gcf,'type','axes');
hLeg = findobj(hAllAxes,'tag','legend');
hAxes = setdiff(hAllAxes,hLeg); % All axes which are not
for k=1:length(hAxes)
   if ~isempty(strfind(hAxes(k).YLabel.String, '(1)'))
       hAxes(k).Title.String = ['State change for a rudder step of ' num2str(rudderDeflectionStep*180/pi) ' degrees'];
       hAxes(k).YLabel.String = 'v (m/s)'; % velocity in body y-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(2)'))
       hAxes(k).YLabel.String = 'p (rad/s)'; % rotation velocity around x-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(3)'))
       hAxes(k).YLabel.String = 'phi (rad)'; % roll angle (euler phi)
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(4)'))
       hAxes(k).YLabel.String = 'r (rad/s)'; % rotation velocity around z-axis
   end
end

% Impulse response
h = subplot(2,2,3);
impulseplot(h, ltiLateral);
title('Lateral Impulse Response');
hAllAxes = findobj(gcf,'type','axes');
hLeg = findobj(hAllAxes,'tag','legend');
hAxes = setdiff(hAllAxes,hLeg); % All axes which are not
for k=1:length(hAxes)
   if ~isempty(strfind(hAxes(k).YLabel.String, '(1)'))
       hAxes(k).Title.String = 'State change for a rudder dirac impulse';
      hAxes(k).YLabel.String = 'v (m/s)'; % velocity in body y-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(2)'))
       hAxes(k).YLabel.String = 'p (rad/s)'; % rotation velocity around x-axis
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(3)'))
       hAxes(k).YLabel.String = 'phi (rad)'; % roll angle (euler phi)
   elseif ~isempty(strfind(hAxes(k).YLabel.String, '(4)'))
       hAxes(k).YLabel.String = 'r (rad/s)'; % rotation velocity around z-axis
   end
end

% Plot yaw moment curve
h = subplot(2,2,4);
hold on;
plot(h, [betaStart:(betaEnd-betaStart)/(numBetas-1):betaEnd], Cn_lateral, 'r-');
plot(h, trimmedBetaRad*180/pi, 0, 'bx');
hold off;
legend('Cn', ['trimmed beta = ' num2str(trimmedBetaRad*180/pi) ' (deg)']);
title('Yaw moment');
xlabel('beta');
ylabel('Cn');

% Compute damping, frequency, period from poles. See also p83 in Caughey.

% Roll pole
poleRoll = polesLateral(3);
poleRollReal = real(poleRoll);
poleRollImag = imag(poleRoll);

Damping_roll = sqrt(1./(1+(poleRollImag./poleRollReal).^2)); % Damping ratio
Frequency_roll = -poleRollReal./Damping_roll; % Undampted, natural frequency per second
Period_roll = 2*pi./(Frequency_roll.*sqrt(1-Damping_roll.^2)); % seconds
Cycles_half_roll = ((log(2))/(2*pi))*sqrt(1-Damping_roll.^2)./Damping_roll; % Number of cycles to damp to half the amplitude

disp('Roll Mode Properties (lateral): ');
disp('                                                 Pole 1');
disp('==============================================================================');
disp(sprintf(['Damping ratio                                 : ' num2str(Damping_roll(:)')]));
disp(sprintf(['Undampted, natural frequency             (1/s): ' num2str(Frequency_roll(:)')]));
disp(sprintf(['Period                                     (s): ' num2str(Period_roll(:)')]));
disp(sprintf(['Num. cycles to damp to half the amplitude     : ' num2str(Cycles_half_roll(:)')]));
disp(' ');

% Spiral pole
poleSpiral = polesLateral(4);
poleSpiralReal = real(poleSpiral);
poleSpiralImag = imag(poleSpiral);

Damping_spiral = sqrt(1./(1+(poleSpiralImag./poleSpiralReal).^2)); % Damping ratio
Frequency_spiral = -poleSpiralReal./Damping_spiral; % Undampted, natural frequency per second
Period_spiral = 2*pi./(Frequency_spiral.*sqrt(1-Damping_spiral.^2)); % seconds
Cycles_half_spiral = ((log(2))/(2*pi))*sqrt(1-Damping_spiral.^2)./Damping_spiral; % Number of cycles to damp to half the amplitude

disp('Spiral Mode Properties (lateral): ');
disp('                                                 Pole 1');
disp('==============================================================================');
disp(sprintf(['Damping ratio                                 : ' num2str(Damping_spiral(:)')]));
disp(sprintf(['Undampted, natural frequency             (1/s): ' num2str(Frequency_spiral(:)')]));
disp(sprintf(['Period                                     (s): ' num2str(Period_spiral(:)')]));
disp(sprintf(['Num. cycles to damp to half the amplitude     : ' num2str(Cycles_half_spiral(:)')]));
disp(' ');

% Dutch Roll poles
polesDutchRoll = polesLateral(1:2); % choose first ones from sorted complex numbers
polesDutchRollReal = real(polesDutchRoll);
polesDutchRollImag = imag(polesDutchRoll);

Damping_dutch = sqrt(1./(1+(polesDutchRollImag./polesDutchRollReal).^2)); % Damping ratio
Frequency_dutch = -polesDutchRollReal./Damping_dutch; % Undampted, natural frequency per second
Period_dutch = 2*pi./(Frequency_dutch.*sqrt(1-Damping_dutch.^2)); % seconds
Cycles_half_dutch = ((log(2))/(2*pi))*sqrt(1-Damping_dutch.^2)./Damping_dutch; % Number of cycles to damp to half the amplitude

% Output result for longitudinal trimmed state
disp('Dutch Roll Mode Properties (lateral): ');
disp('                                                 Pole 1      Pole 2');
disp('==============================================================================');
disp(sprintf(['Damping ratio                                 : ' num2str(Damping_dutch(:)')]));
disp(sprintf(['Undampted, natural frequency             (1/s): ' num2str(Frequency_dutch(:)')]));
disp(sprintf(['Period                                     (s): ' num2str(Period_dutch(:)')]));
disp(sprintf(['Num. cycles to damp to half the amplitude     : ' num2str(Cycles_half_dutch(:)')]));
disp(' ');

% =========================================================================

% Observability
disp(['Number of unobservable states (longitudinal)  : ' num2str(length(ltiLongitudinal.a) - rank(obsv(ltiLongitudinal)))]);
disp(['Number of unobservable states (lateral)       : ' num2str(length(ltiLateral.a) - rank(obsv(ltiLateral)))]);
disp(' ');

% Controllability
disp(['Number of uncontrollable states (longitudinal): ' num2str(length(ltiLongitudinal.a) - rank(ctrb(ltiLongitudinal)))]);
disp(['Number of uncontrollable states (lateral)     : ' num2str(length(ltiLateral.a) - rank(ctrb(ltiLateral)))]);
disp(' ');

% TODO
% ========================================================================

% 1) Run this whole thing for different center of gravity settings and plot
% Cm curve and poles.


function [xsol,objp,info,msg,times,x,y,z,s,w] = lipsol(A,b,c,lb,ub,opts)
% LIPSOL        - Main program for LIPSOL

% Yin Zhang, January, 1995
% Department of Mathematics and Statistics
% University of Maryland  Baltimore County
% Modified J.Currie AUT May 2013

global probData

if(nargin < 6)
    opts = lipsolset;
    opts.maxiter = 100;
    opts.maxtime = 1000;
    opts.tol = 1e-5;
end
if(nargin < 5), ub = []; end
if(nargin < 4), lb = []; end
if(nargin < 3), error('You must supply at least 3 arguments to lipsol(A,b,c)'); end

times = zeros(5,1);
t0 = tic;

%Problem Data Structure to avoid so many Global Variables
probData = struct('NNZA',0,'NNZL',0,'XLNZ',[],'PERM',[],'INVP',[],'LNZ',[],'LOOP_LEVEL',[],...
                  'XSUPER',[],'XLINDX',[],'LINDX',[],'SNODE',[],'SPLIT',[],'TMPSIZ',[],...
                  'LNZ0',[],'b_orig',b,'c_orig',c,'data_changed',0,'isFeasible',1,...
                  'Lbounds_non0',[],'Ubounds_exist',0,'nub',0,'Fixed_exist',0,...
                  'ifix',[],'infx',[],'xfix',[],'Zrcols_exist',0,'izrcol',[],...
                  'inzcol',[],'xzrcol',[],'Sgtons_exist',0,'isolved',[],...
                  'insolved',[],'xsolved',[],'nt',0,'message',[],...
                  'col_scaled',0,'colscl',[],'Dense_cols_exist',0,'Mdense',[],...
                  'idense',[],'ispars',[],'Hist',[],'Sherman_OK',[],'backed',[]);
%Initial Time
opts.t0 = tic;

%Save loop_level into problem structure
probData.LOOP_LEVEL = opts.loop_level;

%Pretty Printing
if(opts.verb), fprintf('----------------------------------------------\n'); end

%Preprocess the Input Data
[A,b,c,lb,ub] = ls_preprocess(A,b,c,lb,ub,opts);
times(1) = toc(t0);

%Check if preproccesor indicates infeasible
if(~probData.isFeasible)
    xsol = []; objp = []; info = [-1 0 0]; msg = 'Presolve Indicated Infeasible'; times = [];
    x = []; y = []; z = []; s = []; w = [];
    return;
end

%Scale the Input Data if Required
[A,b,c,ub] = scaling(A,b,c,ub,opts);
%Determine density of the problem
checkDense(A,opts);
times(2) = toc(t0) - times(1);

%Solve the Problem
[x,y,z,s,w,info] = ls_miip(A,b,c,ub,opts);
times(3) = toc(t0) - times(2);

%Display Solve Status
if(opts.verb && ~isempty(probData.message)), fprintf('\n  Status: %s\n',probData.message); end

%Post Process the Solution
[xsol, objp, times ] = ls_postprocess(x,y,lb,opts.verb,times,t0);
msg = probData.message;

%Pretty Printing
if(opts.verb), fprintf('----------------------------------------------\n'); end

function [A,b,c,ub] = scaling(A,b,c,ub,opts)
% SCALING     - Scale matrix A. Usage: [A,b,c,ubounds] = scaling(A,b,c,ubounds)
% Yin Zhang, January, 1995
% Department of Mathematics and Statistics
% University of Maryland  Baltimore County

global probData

[m, n] = size(A);
badscl = 1.e-4;

absnzs = abs(nonzeros(A));
thescl = min(absnzs)/max(absnzs);
clear absnzs

if (thescl < badscl)
    if(opts.verb), fprintf('Scaling ...\n'); end

    % ----- scaling vectors ------
    AA = abs(A);
    colscl = full(sqrt(max(AA)'));
    rowscl = full(sqrt(max(AA,[],2)));
    clear AA;

    % ----- column scaling -----
    if (probData.Ubounds_exist), ub = ub.*colscl; end
    colscl = reciprocal(colscl);
    A = A*sparse(1:n,1:n,colscl);
    c = c.*colscl;
    probData.col_scaled = 1;

    % ----- row scaling -----
    rowscl = reciprocal(rowscl);
    A = sparse(1:m,1:m,rowscl)*A;
    b = b.*rowscl;
    bnrm = norm(b);
    if (bnrm > 0)
      q = median([1 norm(c)/bnrm 1.e+8]);
      if (q > 10), A = q*A; b = q*b; end
    end
    probData.data_changed = 1;
    probData.colscl = colscl;
end

function checkDense(A,opts) %#ok<INUSD>
% CHECKDENSE - Determine and locate dense columns of matrix A.
% Yin Zhang, January, 1995
% Department of Mathematics and Statistics
% University of Maryland  Baltimore County

%PROBLEM IN PCG - SKIPPING DENSE COLUMN MANAGEMENT [J.C. 19/5/13]

% global probData
%
% [m, n] = size(A);
% probData.ispars = 1:n;
% nzratio = 1;
% if (m >  500), nzratio = 0.20; end;
% if (m > 1000), nzratio = 0.10; end;
% if (m > 5000), nzratio = 0.05; end;
%
% if (nzratio < 1)
%    checking = sum(spones(A))/m <= nzratio;
%    if any(checking == 0)
%       probData.Dense_cols_exist = 1;
%       probData.idense = find(sparse(1-checking));   % Dense  column indices
%       probData.ispars = find(checking);             % Sparse column indices
%       if(opts.verb), fprintf('Dense columns (nnz/m > %g): %i\n',nzratio,length(probData.idense)); end
%    else
%       if(opts.verb), fprintf('No Significant Dense Columns\n'); end
%    end
%    clear checking
% else
%     if(opts.verb), fprintf('Problem is Small Enough to Ignore Dense Columns\n'); end
% end

function Y = reciprocal(X)
% RECIPROCAL  - Invert the nonzero entries of a matrix elementwise.
%             Y = RECIPROCAL(X) has the same sparsity pattern as X
%	      (except possibly for underflow).

% Yin Zhang, January, 1995
% Department of Mathematics and Statistics
% University of Maryland  Baltimore County

if issparse(X)
   [m, n]  = size(X);
   [i,j,Y] = find(X);
   Y = sparse(i,j,1./Y,m,n);
else
   Y = 1./X;
end
ceiling = 1.e+16; Y = min(ceiling,Y);


% Codes for CVPR-15 work `Face Alignment by Coarse-to-Fine Shape Searching'
% Any question please contact Shizhan Zhu: zhshzhutah2@gmail.com
% Released on July 25, 2015

function reg_model = trainLR_averagedHalfBagging(X,y,iter,regressorInfo)

% train regressor using all the samples only once

assert(size(X,1) == size(y,1));
m = size(X,1);
REG = zeros(size(X,2)+1,size(y,2));

for i = 1:regressorInfo.times
    train_ind = randperm(m,ceil(m/2));
    REG = REG + (1/regressorInfo.times) * ...
        regressorInfo.trainMethod(X(train_ind,:),y(train_ind,:),regressorInfo.lambda(iter));
end;
reg_model = REG;

end


function [funOut, indexStart, problemDom, coeffs, totalDiffOrders] = ...
    toFirstOrder(funIn, rhs, domain, numArgs, cellArg)
%TOFIRSTORDER   Convert higher order anonymous functions to first order systems.
%   Calling sequence:
%      [FUNOUT, INDEXSTART, PROBLEMDOM, COEFFS, TOTALDIFFORDERS] = ...
%          TOFIRSTORDER(FUNIN, RHS, DOMAIN)
%   where the inputs are:
%      FUNIN:  An anonymous function which describes an ODE, usually including
%              higher order derivatives, e.g. @(x,u) diff(u, 2) + sin(u).
%              Usually, the anonymous function comes from the OP field of a
%              CHEBOP.
%      RHS:    The right hand side of the differential equation being solved
%              with a CHEBOP, that is, the right argument of a CHEBOP
%              backslash.
%      DOMAIN: The domain of the problem we're trying to solve.
%   and the outputs are:
%      FUNOUT:     An anonymous function that is the first order reformulation
%                  of FUNIN, which can be passed to the MATLAB solvers.
%      INDEXSTART: A vector that denotes at which index we should start
%                  indexing each variable from so that they're in the correct
%                  order for the MATLAB ODE solvers.
%      PROBLEMDOM: The domain on which the problem can be specified, which may
%                  include breakpoints originally not included in DOMAIN.
%      COEFFS:     A cell array of the coefficients the multiply the highest
%                  order derivatives in problem. For example, for the problem
%                  @(x,u) 5*diff(u, 2) + u, we will have COEFFS{1} = 5.
%      TOTALDIFFORDERS:
%                  A vector that contains the maximum diffOrder applying to
%                  each variable in the problem.
%
%   In addition, one can pass the following arguments to the function, which are
%   only required if working in CHEBMATRIX syntax, for example,
%   @(x,u)[diff(u{1}) + u{2};...]:
%       NVARS:   The number of unknown variables in the ODE.
%       CELLARG: Specify as TRUE if FUNIN is specified in CHEBMATRIX syntax.

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

% Independent variable on the domain
t = chebfun(@(t) t, domain);

% See if we need to determine the number of variables involved, or if it was
% passed as an argument.
if ( nargin < 4)
    % We always have at least one argument to FUNIN, even in the scalar case. In
    % the system case, the first argument to funIn must be the independent time
    % variable. So the number of treeVar arguments needed is one less:
    numArgs = max(1, nargin(funIn) - 1);
    % If working in CHEBMATRIX syntax, we need all possible input variables to
    % be passed in as arguments:
    cellArg = false;
end
args = cell(numArgs, 1);
argsVec = zeros(1, numArgs);

% Populate the args cell
for argCount = 1:numArgs
    argsVec(argCount) = 1;
    args{argCount} = treeVar(argsVec, domain);
    % Reset the index vector
    argsVec = 0*argsVec;
end

% Evaluate FUNIN with the TREEVAR arguments. Need different calling sequences
% depending on whether we're working with CHEBMATRIX syntax and cells or not:
if ( cellArg )
    fevalResult = funIn(t, args);
else
    % If FUNIN only takes one argument, we just give it the TREEVAR argument.
    % Otherwise, the first input will be the independent variable on the domain:
    if ( nargin(funIn) == 1 )
        fevalResult = funIn(args{:});
    else
        fevalResult = funIn(t, args{:});
    end
end

% If we got passed the problem as N\0, i.e. a RHS that did not match the
% dimensions, we need to repmat it so that the RHS variable has the correct
% dimensions below:
if ( isnumeric(rhs) && length(rhs) == 1 )
    rhs = repmat(rhs, size(fevalResult));
end

% Ensure RHS is a CHEBMATRIX
if ( ~isa(rhs, 'chebmatrix') )
    rhs = chebmatrix(rhs, domain);
end

% Initialize cells to store the infix forms of the expressions, the coefficients
% multiplying the highest order derivatives and any variables that appear in the
% anonymous functions:
systemInfix = cell(length(fevalResult), 1);
coeffs = systemInfix;
varArrays = systemInfix;

% We want to return all potential breakpoints caused by piecewise coefficients
% in the problem. So loop through fevalResult, and take the union of the
% breakpoints:
problemDom = fevalResult(1).domain;
for resCounter = 2:length(fevalResult)
    problemDom = union(problemDom, fevalResult(resCounter).domain);
end

% Ensure we also include potential breakpoints from the RHS:
problemDom = union(problemDom, rhs.domain);

% First look at all diffOrders to ensure we start with the correct indices.
% INDEXSTART denotes at which index we should start indexing each variable from.
% E.g., in the coupled system
%   [v'' + w; v + w'']
% we will have v = u(1), v' = u(2), w = u(3), w' = u(4), so INDEXSTART = [1, 3],
% since v and its derivatives starts getting counted at 1, and w and its
% derivatives start getting counted at 3.
%
% The vector INDEXSTARTDER is similar, but here, we also assign the highest
% order derivative of each variable it's own index. This is so that later on, we
% can correctly evaluate the coefficient multiplying the highest order
% derivative in problem. Thus, in the example above, we'd have
%   v = u(1), v' = u(2), v'' = u(3), w = u(4), w' = u(5), w'' = u(6)
% Here, INDEXSTARTDER = [1 4].

% First, we need to find out the maximum diffOrder of each variable appearing in
% the problem. We loop through the each component of the evaluation tree:
totalDiffOrders = zeros(1, numArgs);
for wCounter = 1:length(fevalResult)
    totalDiffOrders = max(totalDiffOrders, ...
        fevalResult(wCounter).tree.diffOrder);
end

% We always start indexing the first variable and its derivative(s) at 1. The
% index of the other variables depend on the cumulative diffOrders of the
% variables with lower indices.
indexStart = [ 1, cumsum(totalDiffOrders(1:end-1)) + 1 ];
% To get the indices of the derivatives as well, we shift all the previous
% indices right by 1, in cumulative fashion:
indexStartDer = indexStart + (0:numArgs-1);

% COEFFARG will be used to evaluate the functions that gives us information
% about the coefficients multiplying the highest order derivative in each
% equation. The vector has to be equally long to the total number of derivatives
% appearing in the problem; we'll then change one of the entries to 1 at a time
% to get the coefficient information.
coeffArg = zeros(1, indexStartDer(end) + totalDiffOrders(end));

% Go through each componenent from the result of evaluating FUNIN,
% and change it to infix format.
for wCounter = 1:length(fevalResult)

    % The current result we're looking at.
    res = fevalResult(wCounter);

    % Current diffOrders
    diffOrders = res.tree.diffOrder;

    % Ensure that we never have the highest derivatives of more than one
    % variable appearing in a single equation:
    if ( sum(totalDiffOrders == diffOrders) > 1 )
        error('CHEBFUN:TREEVAR:toFirstOrder:diffOrders', ...
            ['The highest order derivative of more than one variable ' ...
            'appears to be\npresent in the same equation. ' ...
            'Unable to convert to first order format.'])
    end

    % Expand the tree, so that PLUS rather than TIMES is sitting at the top of
    % it.
    expTree = treeVar.expandTree(res.tree, totalDiffOrders);

    % Split the tree into derivative part and non-derivative part.
    [newTree, derTree] = treeVar.splitTree(expTree, totalDiffOrders);

    % If newTree is empty, we only have a derivative part in the expression,
    % e.g. diff(u) = 0. We must replace it with a 0, as otherwise, we can't
    % evaluate the resulting odeFun in the ODE solvers.
    if ( isempty(newTree) )
        newTree = 0;
    end

    % Find what argument corresponds to the highest derivative one in the
    % current expression we're looking at. This will also be the order in which
    % we store the outputs from converting individual expressions to first order
    % form -- if the input is of the form @(x,u,v) [diff(v) - u; diff(u) - v],
    % the equations have to be sorted so that they'll be correctly converted.
    maxDerLoc = find(expTree.diffOrder == totalDiffOrders);

    % Convert the derivative part to infix form.
    % Indicate that we are converting a coeffFun
    isCoeffFun = true;
    [infixDer, varArrayDer] = ...
        treeVar.tree2infix(derTree, maxDerLoc, indexStartDer, isCoeffFun);

    % Convert the infix form of the expression that gives us the coefficient
    % multiplying the highest order derivative appearing in the expression to an
    % anonymous function we can evaluate:
    coeffFun = treeVar.toAnon(infixDer, varArrayDer);

    % Reset coeffArg for next evaluation:
    coeffArg = 0*coeffArg;

    % Replace one of the 0s in coeffFun with 1 so that we can evaluate COEFFFUN:
    if ( maxDerLoc == numArgs )
        % The last variable in the system currently appears in the highest order
        % derivate.
        coeffArg(end) = 1;
    else
        % The variable with index maxDerLoc+1 is the next variable we need to
        % start numbering at. So subtract 1 for the index of the highest
        % derivative we're currently interested in.
        coeffArg(indexStartDer(maxDerLoc+1) - 1) = 1;
    end

    % Evaluate the COEFFFUN to the coefficient!
    coeffs{maxDerLoc} = coeffFun(t, coeffArg);

    % Now work with the remaining syntax tree of the current expression of
    % interest. We need to negate the syntax tree as we're moving it to the
    % right-hand side. But if it already starts with a unary minus, we can
    % simply remove it rather than doing a double negation:
    % [TODO: Remove double UMINUS]
    newTree = struct('method', 'minus', 'numArgs', 2, ...
        'left', rhs{wCounter}, 'right', newTree);
    % Convert current expression to infix form:
    isCoeffFun = false;
    [infix, varArray] = ...
        treeVar.tree2infix(newTree, maxDerLoc, indexStart, isCoeffFun);
    % Store the infix form and the variables that appeared in the anonymous
    % function.
    systemInfix{maxDerLoc} = infix;
    varArrays{maxDerLoc} = varArray;
end

% Convert all the infix expressions, coefficients and variables stored to an
% anonymous function we can evaluate and use as the RHS of our ODE system:
funOut = treeVar.toRHS(systemInfix, varArrays, coeffs, ...
    indexStart, totalDiffOrders);

end


%BASE64ENCODE encodes a vector of uint8s as a base64 string
% BASE64ENCODE(BYTES)
%    Encodes every tree BYTES in four printable ASCII characters.
%    If LENGTH(BYTES) is not a multiple of three, it is padded with
%    zeros and unused characters are replaced with '='.

% (c) 2014 Bastian Bechtold
% This code is licensed under the BSD 3-clause license

function base64 = base64encode(bytes)
    % pad the base64 string to a multiple of 3
    if mod(length(bytes), 3) ~= 0
        padding = 3-mod(length(bytes), 3);
        bytes = [bytes; zeros(3-mod(length(bytes), 3), 1, 'uint8')];
    else
        padding = 0;
    end

    % convert every three uint8 bytes into four base64 bytes
    base64 = zeros(length(bytes)/3*4, 1, 'uint8');
    base64(1:4:end) = bitshift(bytes(1:3:end), -2);
    base64(2:4:end) = bitor(bitshift(bitand(bytes(1:3:end),  3),  4), ... % two LSB
                      bitshift(bytes(2:3:end), -4));
    base64(3:4:end) = bitor(bitshift(bitand(bytes(2:3:end),  15),  2), ... % four LSB
                            bitshift(bytes(3:3:end), -6));
    base64(4:4:end) = bitand(bytes(3:3:end), 63); % six LSB

    % convert from base64 bytes to string representation
    table = ['A':'Z' 'a':'z' '0':'9' '+' '/'];
    base64 = table(base64+1);
    base64(end-padding+1:end) = '=';
end


function [v2gMap, sqDist] = mrmMapVerticesToGray(vertexCoords, grayNodes, mmPerVox, grayEdges,distThresh)
%
% [v2gMap sqDist] = mrmMapVerticesToGray(vertices, grayNodes, mmPerVox, [grayEdges]);
%
% Finds a map between the mesh vertices and gray nodes.
% To see the coordinates of the gray matter node (or nodes) nearest to
% mesh vertex I, we can use:
%
%      nearestNodeCoords = grayNodes(1:3, v2gMap(:,I))
%
%
% If the grayEdges are also passed in, then we'll compute the mapping for
% all gray layers. Layer 1 mapping will be in the first row, and layers
% >1 in subsequent columns. As always, vertices with no mapping will be set
% to 0.
%
% The vertexGrayMap now has multiple rows to represent mappings from
% each vertex (the columns) to all gray layers. This mapping is computed in
% two steps:
%
% 1. For each vertex, find the nearest layer 1 gray node, where 'nearest'
% is simply the smallest 3d Euclidian distance, with a threshold to leave
% vertices that are too far from any layer 1 nodes unmapped (zero entry in
% vertexGrayMap). This threshold is currently set to 4mm- edit
% mrmMapVerticesToGray if you want to change this. This layer-1 mapping
% forms the first column of the vertexGrayMap.
%
% 2. For each vertex (row), find all the nodes from layers >1 that should
% map to this vertex. This is a somewhat ill-posed problem, so we had to
% make a choice about which solution we wanted. We decided to use the gray
% layer connections to find all the layer >1 nodes that form a direct
% connection to the nearest layer 1 node that we mapped in step 1. As you
% discovered, this gives us a very redundant sampling of the gray nodes.
% The number of nodes >1 that are most directly connected to a given layer
% 1 node can be very high, especially in regions of high convexity. The
% algorithm for doing this essentially starts at the highest layers and
% maps them down to the most direct (ie. shortest path) layer 1 node. In a
% region of GM at the end of a thick finger of WM, this can map many nodes
% to one layer 1 node (apparently 84 in one case). The vertexGrayMap is an
% array, so the number of columns represents the most densely connected
% case. If you look at it, there are probably only a few vertices with as
% many as 84 connections. Most vertices probably have lots of zeros in
% those higher columns. In fact, in regions of high concavity, you should
% see some with no layers >1 (ie. a row with all zeros except for the first
% column).
%
% We realize that this choice of implementation might not be what everyone
% wants. But it works pretty well for our purposes. Of course, one downside
% to the highly redundant mapping is an effective 'smoothing' of the data,
% especially when you choose to average all layers (in your 3d window
% preferences settings). What we do is look at our data collapsed across
% layers as well as combining all layers, just to make sure we aren't
% missing something.

%
% HISTORY:
%  2003.09.16 RFD (bob@white.stanford.edu)
%  2004.05.21 RFD: now uses Dan Merget's nearpoints to find a proper
%  mapping. No more hacks! Aside from being a bit faster, the result should
%  be substantially more accurate.
%  2005.07.26 RFD: We now return a mapping for all gray layers, if
%  grayEdges is passed in.
%  2005.08.05 RFD: all gray layer mapping is turned off by default, until
%  we figure out how to make it go faster.
%  2005.10.26 GB: Tentative speed improvement in the main loop
%  2006.06.01 RFD: added comments above. These were prompted by an email
%  exchange with David Ress.
%  2007.05.23 ARW : Gray layer mapping seems to be available. Which is
%  nice. Added some minor mods to return sqDist and detect dist thresholds.
verbose = prefsVerboseCheck;

if notDefined('mmPerVox'), error('Voxel size (mm per vox) is required.'); end;
if (notDefined('distThresh'))
    if (ispref('VISTA','defaultSurfaceWMMapDist'))
		if verbose,
	        disp('Setting distThresh to the one in VISTA preferences');
		end
        distThresh = getpref('VISTA','defaultSurfaceWMMapDist');
    else
       if verbose, disp('Setting distThresh to 2'); end
       distThresh = 3;
    end
end

vertexCoords = double(vertexCoords);
grayNodes = double(grayNodes);

if notDefined('grayEdges')
    grayEdges=[];
end

grayEdges = double(grayEdges);

prefs = mrmPreferences;
if(strcmp(prefs.layerMapMode,'all'))
    mapToAllLayers = true;
else
    mapToAllLayers = false;
end

% This is now a real distance threshold, in mm. For each mesh vertex, the
% algorithm will find the nearest gray coord. If the nearest coord is >
% distThresh from the vertex, then that vertex gets no mapping ('0').

% The gray coordinates are in voxels in the vAnatomy file.  This scales
% them into real physical (mm) coordinates.  And transposes them.
grayCoords = grayNodes([1,2,3], :);
grayCoords = [grayCoords(1,:).*mmPerVox(1); ...
        grayCoords(2,:).*mmPerVox(2); ...
        grayCoords(3,:).*mmPerVox(3) ]';

% Transposes these mesh coordinates, which were already built in real
% physical coordinates.
% Major comments needed here.
vertexCoords = vertexCoords' + 1;

% Mask out non-layer 1 nodes so that they are not found
if (~strcmp(prefs.layerMapMode,'any'))
	if verbose,     disp('Masking out layers > 1');   end
    grayCoords(grayNodes(6,:)~=1,:) = -9999;
end

[v2gMap, sqDist] = nearpoints(double(vertexCoords'), double(grayCoords'));

if verbose,
	fprintf('Excluding mesh nodes further than %d away from the boundary \n', ...
			distThresh);
end

v2gMap(sqDist > (distThresh^2)) = 0;

v2gMap = int32(v2gMap);

if(mapToAllLayers && exist('grayEdges','var') && ~isempty(grayEdges))
    layer1Nodes = v2gMap;
    curValid = double(layer1Nodes) > 0;
    numLayers = max(grayNodes(6,:));
    n = length(curValid);
    curLayerNum = 2;

    % GB 2005.10.26
    % We map from higher layers to lower layers,
    % selecting the closest connected node in the lower layer. This way we
    % will avoid multiply-connected

    noNeighborsDown = 0;
    noNeighbor = 0;
    noNeighbor2 = 0;

    v2gMapTemp = zeros(numLayers,size(grayNodes,2));

    h = mrvWaitbar(0, 'Computing between layers connections...');
    progress = 0;
    for iLayer = numLayers:-1:curLayerNum
        midprogress = 0;

        curNodes = find(grayNodes(6,:) == iLayer);
        for iNode = curNodes
            % disp(iNode) % debugging
            offset = grayNodes(5,iNode);
            numConnected = grayNodes(4,iNode);
            if numConnected == 0
                noNeighbor = noNeighbor + 1;
                continue %mrmMapVerticesToGray
            end
            neighbors = grayEdges(offset:offset + numConnected - 1);
            neighbors(grayNodes(6,neighbors) ~= (iLayer - 1)) = [];
            distance = sum(grayNodes(1:3,neighbors).^2,1);
            [value,nearest] = min(distance);
            if ~isempty(nearest)
                v2gMapTemp(iLayer,iNode) = neighbors(nearest);
            elseif length(nearest) > 1
                neighbors = neighbors(nearest);
                distanceIndex = abs(neighbors - iNode);
                [value,nearest] = min(distanceIndex);
                v2gMapTemp(iLayer,iNode) = neighbors(nearest);
            else
                neighbors = grayEdges(offset:offset + numConnected - 1);
                neighbors(grayNodes(6,neighbors) < iLayer - 1) = [];
                nextNeighbors = [];
                neighborsDown = [];
                iter = 0; % debugging
                while isempty(neighborsDown) && ~isequal(neighbors,nextNeighbors)
                    iter = iter+1; %debugging
                    if iter> 1000,
                       disp foo
                       break
                    end
                    neighbors = union(nextNeighbors,neighbors);
                    nextNeighbors = [];
                    for iNeighbor = 1:length(neighbors)
                        offset = grayNodes(5,neighbors(iNeighbor));
                        numConnected = grayNodes(4,neighbors(iNeighbor));
                        nextNeighbors = [nextNeighbors grayEdges(offset:offset+numConnected-1)];
                    end
                    nextNeighbors = unique(nextNeighbors);
                    neighborsDown = nextNeighbors(grayNodes(6,nextNeighbors) == (iLayer - 1));
                end

                if isempty(neighborsDown)
                    noNeighbor2 = noNeighbor2 + 1;
                else
                    distance = sum(grayNodes(1:3,neighborsDown).^2,1);
                    [value,nearest] = min(distance);
                    if length(nearest) == 1
                        v2gMapTemp(iLayer,iNode) = neighborsDown(nearest(1));
                    else
                        neighborsDown = neighborsDown(nearest);
                        distanceIndex = abs(neighborsDown - iNode);
                        [value,nearest] = min(distanceIndex);
                        v2gMapTemp(iLayer,iNode) = neighborsDown(nearest);
                    end
                end
                noNeighborsDown = noNeighborsDown + 1;
            end
        end
        progress = progress + 1/(numLayers - curLayerNum + 1);
        mrvWaitbar(progress/2,h);
    end

    indices = 2*ones(1,size(v2gMap,2));
    indexNodes = cell(1,size(grayNodes,2));
    for curNode = find(curValid)
        indexNodes{v2gMap(1,curNode)} = [indexNodes{v2gMap(1,curNode)} curNode];
    end

    h = mrvWaitbar(1/2, h, 'Creating connections table...');
    progress = 0;
    for iNode = 1:size(grayNodes,2)
        if iNode > (progress + 1/10)*size(grayNodes,2)
            progress = progress + 1/10;
            mrvWaitbar(0.5 + progress/2);
        end

        curLayer = grayNodes(6,iNode);
        curNode = iNode;
        for iLayer = curLayer:-1:2
            if curNode == 0
                break
            end
            curNode = v2gMapTemp(iLayer,curNode);
        end
        if (curNode == 0) || (curNode == iNode)
            continue
        end

        indexNode = indexNodes{curNode};
        if isempty(indexNode)
            continue
        end

        v2gMap(indices(indexNode),indexNode) = iNode;
        indices(indexNode) = indices(indexNode) + 1;

    end
    close(h);

end

return;


function y = vl_nnrelu(x,dzdy)
% VL_NNRELU  CNN rectified linear unit
%   Y = VL_NNRELU(X) applies the rectified linear unit to the data
%   X. X can have arbitrary size.
%
%   DZDX = VL_NNRELU(X, DZDY) computes the network derivative DZDX
%   with respect to the input X given the derivative DZDY with respect
%   to the output Y. DZDX has the same dimension as X.

% Copyright (C) 2014 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

if nargin <= 1 || isempty(dzdy)
  y = max(x, single(0)) ;
else
  y = dzdy .* (x > single(0)) ;
end


function cvx_optpnt = nonnegative( sx ) %#ok

%NONNEGATIVE   The nonnegative orthant.
%   NONNEGATIVE(SX), where SX is a valid size vector, creates an array
%   of size SX and constrains each element to be nonnegative. Therefore,
%   given the declaration
%      variable x(sx)
%   the constraint
%      x == nonnegative(sx);
%   is equivalent to
%      x >= 0;
%   Obviously, the inequality form is simpler and is preferred in most
%   circumstances.
%
%   Disciplined convex programming information:
%       NONNEGATIVE is a cvx set specification. See the user guide for
%       details on how to use sets.

narginchk(1,1);

[ temp, sx ] = cvx_check_dimlist( sx, true );
if ~temp,
    error( 'Argument must be a non-empty dimension vector.' );
end

cvx_begin set
    variables x( sx )
    if all( sx ~= 0 ),
        [ tx, dummy ] = find( cvx_basis( x ) ); %#ok
        newnonl( cvx_problem, 'nonnegative', tx(:) );
    end
cvx_end

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


function F = complements(C1,C2)
%COMPLEMENTS Defines complementary constraints
%
%   F = COMPLEMENTS(C1,C2)

F = complements(lmi(C1),lmi(C2));


function boolean = CalculateTimeForTakingOutBillet(T_new,reference_Temperature,x_intervals,y_intervals)
boolean = 0;
count = 0;

for x_index = 2:1:(x_intervals-1)
    for y_index = 2:1:(y_intervals-1)
        if(abs(T_new(x_index,y_index))-reference_Temperature < 01 )
        count = 1;
        end
    end
    if(count >= ((x_intervals*y_intervals)/2))
        boolean = 1;
        break;
    end
end

end


function [stlStruct] = import_STL_bin(fileName)

% function [stlStruct] = import_STL_bin(fileName)
% ------------------------------------------------------------------------
%
% This function reads an STL file in binary format into stlStruct
%
%
% Based on code originally written by: Doron Harlev, Eric C. Johnson
% (11-Dec-2008), and Francis Esmonde-White (May 2010).
%
%
% Kevin Mattheus Moerman
% gibbon.toolbox@gmail.com
%
% 2016/02/24 Added to GIBBON and altered syntax and behaviour
%------------------------------------------------------------------------

%% Access file

fid=fopen(fileName, 'r'); %Open the file, assumes STL Binary format.
if fid == -1
    error('File could not be opened, check name or path.')
end

%% Read title
solidNameBin=fread(fid,80,'uchar=>schar'); % Read file title
solidName = char(solidNameBin');

%% Get number of faces
numFaces=fread(fid,1,'int32'); % Read number of Faces

%% Read remainder

T = fread(fid,inf,'uint8=>uint8'); % read the remaining values
fclose(fid); %Close file

%% Process import

% Each facet is 50 bytes
%  - Three single precision values specifying the face normal vector
%  - Three single precision values specifying the first vertex (XYZ)
%  - Three single precision values specifying the second vertex (XYZ)
%  - Three single precision values specifying the third vertex (XYZ)
%  - Two color bytes (possibly zeroed)

% 3 dimensions x 4 bytes x 4 vertices = 48 bytes for triangle vertices
% 2 bytes = color (if color is specified)

trilist = 1:48;

ind = reshape(repmat(50*(0:(numFaces-1)),[48,1]),[1,48*numFaces])+repmat(trilist,[1,numFaces]);
coordNormData = reshape(typecast(T(ind),'single'),[3,4,numFaces]);

N=squeeze(coordNormData(:,1,:))';
N=double(N);

V=coordNormData(:,2:4,:);
V=reshape(V,[3,3*numFaces]);
V=double(V)';

F=reshape(1:3*numFaces,[3,numFaces])';

c0 = typecast(T(49:50),'uint16');
if (bitget(c0(1),16)==1)
    trilist = 49:50;
    ind = reshape(repmat(50*(0:(numFaces-1)),[2,1]),[1,2*numFaces])+repmat(trilist,[1,numFaces]);
    c0 = reshape(typecast(T(ind),'uint16'),[1,numFaces]);

    r=bitshift(bitand(2^16-1, c0),-10);
    g=bitshift(bitand(2^11-1, c0),-5);
    b=bitand(2^6-1, c0);
    C=[r; g; b]';
else
    C = zeros(numFaces,3);
end

%% Arrange output in structure array
stlStruct.solidNames{1}=solidName;
stlStruct.solidVertices{1}=V;
stlStruct.solidFaces{1}=F;
stlStruct.solidNormals{1}=N;
stlStruct.solidColors{1}=C;

%%
% _*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 header = dtiReadPDBHeader (fid)

if (~exist('fid','var'))
    header = struct();
    header.xformToAcPc = repmat (0, 4);
    header.numPaths = 0;
else
    offset = fread (fid, 1, 'uint');
    mx = fread (fid, 16, 'double');
    header.xformToAcPc = reshape (mx, 4,4);
    fseek (fid, offset-4, -1);
    header.numPaths = fread (fid, 1, 'uint');
end

% xxx should contain information about statistics too!


function [edgeS, maskDown3D] = getSurface(structNumV, marginV, xyDownsampleIndex, planC)
%"getSurface"
%   Get all the surface points of a a composite structure defined by the
%   structures given in structNumV, with margins epanded in 3D according to
%   marginV.  The iV, jV, kV index vectors give all the surface points with
%   respect to the uniformized CT scan.
%
%JOD, 14 Nov 03.
%JRA, 27 Mar 05.
%
%Usage:
%   [iEdgeV,jEdgeV,kEdgeV] = getSurface(structNumV,marginV, xyDownsampleIndex)
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

if ~exist('planC')
    global planC
end
indexS = planC{end};

global stateS

if any(marginV ~= marginV(1))
  error('Currently only supports the same PB margin around each target.')
end
margin = marginV(1);

scanNum = getStructureAssociatedScan(structNumV(1));
CTUniformInfoS = planC{indexS.scan}(scanNum).uniformScanInfo;

xOffset = CTUniformInfoS.xOffset;
yOffset = CTUniformInfoS.yOffset;

sliceThickness = CTUniformInfoS.sliceThickness;

delta_xy = CTUniformInfoS.grid1Units;

%-----------build composite target volume---------------------%

mask3D = getUniformStr(structNumV(1));

SZ=size(mask3D);

maskDown3D = logical(getDownsample3(mask3D, xyDownsampleIndex, 1));

clear mask3D

S = size(maskDown3D);

len = length(structNumV);

for i = 2 : len

  maskSingle = getUniformStr(structNumV(i));

  mask3D = maskSingle; clear maskSingle;

  tmp3D = logical(getDownsample3(mask3D, xyDownsampleIndex, 1));

  clear mask3D

  maskDown3D = tmp3D | maskDown3D;

end

% II.  Get surface points from target volume

edge = [0 0 0; 0 1 0; 0 0 0];
edge(:,:,2) = [0 1 0; 1 1 1; 0 1 0];
edge(:,:,3) = [0 0 0; 0 1 0; 0 0 0];
edge = edge/7;

surfPoints = getSurfacePoints(maskDown3D);
edge3D = repmat(logical(0), size(maskDown3D));
for i=1:size(surfPoints,1)
   edge3D(surfPoints(i,1),surfPoints(i,2), surfPoints(i,3)) = 1;
end

%Expand margin using convolution
%Create margin ball:

c1 = ceil(margin/delta_xy);
c2 = ceil(margin/delta_xy);
c3 = ceil(margin/sliceThickness);

[uM,vM,wM] = meshgrid(- c1 : c1, -c2 : c2, - c3 : c3);

xM = uM * delta_xy;
yM = vM * delta_xy;
zM = wM * sliceThickness;

rM = (xM.^2 + yM.^2 + zM.^2).^0.5;

ball = [rM <= margin];

[iBallV,jBallV,kBallV] = find3d(ball);

sR = size(rM);

deltaV = (sR - 1)/2 +1;

onesV = repmat(logical(1), [1,length(iBallV)]);

[iV,jV,kV] = find3d(edge3D);

sV = size(maskDown3D);

ind_surfV = sub2ind(sV,iV,jV,kV);

ball_offsetV = (iBallV - deltaV(1)) + sV(1) * (jBallV - deltaV(2)) + sV(1) * sV(2) * (kBallV - deltaV(3));

for i = 1 : length(ind_surfV) %put ones in

  total_indV = ind_surfV(i) + ball_offsetV;

  total_indV = clip(total_indV,1,prod(sV),'limits');

  maskDown3D(total_indV) = onesV;

end

%Find new edge
surfPoints = getSurfacePoints(maskDown3D);

edgeS.rows   = surfPoints(:,1);%iV;
edgeS.cols   = surfPoints(:,2);%jV;
edgeS.slices = surfPoints(:,3);%kV;


function [x,M] = spm_x_nmm(P)
% initialises a state structure for a mean field model
% FORMAT [x,M] = spm_x_nmm(P)
%
% P - parameter structure
% M - model structure
%
% x        - array of states
% x(i,j,k) - k-th state of j-th population on i-th source
%
%   population: 1 - excitatory spiny stellate cells (input cells)
%               2 - inhibitory interneurons
%               3 - excitatory pyramidal cells      (output cells)
%
%        state: 1 V  - voltage
%               2 gE - conductance (excitatory)
%               3 gI - conductance (inhibitory)
%
% M - model structure
%
% see also: spm_x_mfm
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_x_nmm.m 2393 2008-10-23 14:58:50Z karl $

% get initialisation from full mean-field model
%==========================================================================
[x M] = spm_x_mfm(P);

% remove dispersion and fix the covariance of the states (Cx)
%--------------------------------------------------------------------------
M.x   = x{1};
M.Cx  = x{2}(:,:,1,1);
x     = x{1};


%%*****************************************************************
%% linsysolve: solve linear system to get dy, and direction
%%             corresponding to unrestricted variables.
%%
%% [xx,coeff,L,resnrm] = linsysolve(schur,UU,EE,Bmat,rhs);
%%
%% child functions: mybicgstable.m
%%*****************************************************************
%% SDPT3: version 4.0
%% Copyright (c) 1997 by
%% Kim-Chuan Toh, Michael J. Todd, Reha H. Tutuncu
%% Last Modified: 16 Sep 2004
%%*****************************************************************

   function [xx,coeff,L,resnrm] = HSDlinsysolve(par,schur,UU,EE,Bmat,rhs);

    global solve_ok msg
    global nnzmat nnzmatold matfct_options matfct_options_old use_LU

    spdensity  = par.spdensity;
    printlevel = par.printlevel;
    iter       = par.iter;

    m = length(schur);
    if (iter==1); use_LU = 0; matfct_options_old = ''; end
    if isempty(nnzmatold); nnzmatold = 0; end
%%
%% diagonal perturbation
%% old: pertdiag = 1e-15*max(1,diagschur);
%%
    diagschur = abs(full(diag(schur)));
    const = 1e-2/max(1,norm(par.dy2));
    alpha = max(1e-14,min(1e-10,const*norm(par.rp))/(1+norm(diagschur.*par.dy2)));
    pertdiag = alpha*max(1e-8,diagschur); %% Note: alpha is close to 1e-15.
    mexschurfun(schur,pertdiag);
    %%if (printlevel); fprintf(' %3.1e ',alpha); end
    if (par.depconstr) | (min(diagschur) < min([1e-20*max(diagschur), 1e-4]))
       lambda = 0.1*min(1e-14,const*norm(par.rp)/(1+norm(par.diagAAt.*par.dy2)));
       mexschurfun(schur,lambda*par.diagAAt);
       %%if (printlevel); fprintf('*'); end
    end
    if (max(diagschur)/min(diagschur) > 1e14) & (par.blkdim(2) == 0) ...
       & (iter > 10)
       tol = 1e-6;
       idx = find(diagschur < tol); len = length(idx);
       pertdiagschur = zeros(m,1);
       if (len > 0 & len < 5) & (norm(rhs(idx)) < tol)
          pertdiagschur(idx) = 1*ones(length(idx),1);
          mexschurfun(schur,pertdiagschur);
          if (printlevel); fprintf('#'); end
       end
    end
%%
%%
%%
    UU = [UU, Bmat];
    if ~isempty(EE)
       len = max(max(EE(:,1)),max(EE(:,2)));
    else
       len = 0;
    end
    tmp = [len+1,len+3,-1; len+2,len+4,1; len+3,len+1,1; len+4,len+2,-1;
           len+2,len+2,par.addschur];  %% this is the -inverse
    EE = [EE; tmp];
    ncolU = size(UU,2);
%%
%% assemble coefficient matrix
%%
    if isempty(EE)
       coeff.mat22 = [];
    else
       coeff.mat22 = spconvert(EE);
    end
    coeff.mat12 = UU;
    coeff.mat11 = schur; %% important to use perturbed schur matrix
%%
%% pad rhs with zero vector
%% decide which solution methods to use
%%
    rhs = [rhs; zeros(m+ncolU-length(rhs),1)];
    if (ncolU > 300); use_LU = 1; end
%%
%% Cholesky factorization
%%
    L = []; resnrm = []; xx = inf*ones(m,1);
    if (~use_LU)
       nnzmat = mexnnz(coeff.mat11);
       nnzmatdiff = (nnzmat ~= nnzmatold);
       solve_ok = 1;  solvesys = 1;
       if (nnzmat > spdensity*m^2) | (m < 500)
          matfct_options = 'chol';
       else
          matfct_options = 'spchol';
       end
       if (printlevel > 2); fprintf(' %s',matfct_options); end
       L.matdim = length(schur);
       if strcmp(matfct_options,'chol')
          if issparse(schur); schur = full(schur); end;
          if (iter<=5); %%--- to fix strange anonmaly in Matlab
             mexschurfun(schur,1e-20,2);
          end
          L.matfct_options = 'chol';
          [L.R,indef] = chol(schur);
          L.perm = [1:m];
       elseif strcmp(matfct_options,'spchol')
          if ~issparse(schur); schur = sparse(schur); end;
          L.matfct_options = 'spchol';
          [L.R,indef,L.perm] = chol(schur,'vector');
          L.Rt = L.R';
       end
       if (indef)
          solve_ok = -2; solvesys = 0;
          msg = 'HSDlinsysolve: Schur complement matrix not positive definite';
          if (printlevel); fprintf('\n  %s',msg); end
       end
       if (solvesys)
          if (ncolU)
             tmp = coeff.mat12'*linsysolvefun(L,coeff.mat12)-coeff.mat22;
	     if issparse(tmp); tmp = full(tmp); end
             [L.Ml,L.Mu,L.Mp] = lu(tmp);
             tol = 1e-16;
             condest = max(abs(diag(L.Mu)))/min(abs(diag(L.Mu)));
             idx = find(abs(diag(L.Mu)) < tol);
             if ~isempty(idx) | (condest > 1e50*sqrt(norm(par.diagAAt))); %% old: 1e30
                solvesys = 0; solve_ok = -4;
                use_LU = 1;
                msg = 'SMW too ill-conditioned, switch to LU factor';
                if (printlevel); fprintf('\n  %s, %2.1e.',msg,condest); end
             end
          end
          if (solvesys)
             [xx,resnrm,solve_ok] = HSDbicgstab(coeff,rhs,L,[],[],printlevel);
             if (solve_ok<=0) & (printlevel)
                fprintf('\n  warning: HSDbicgstab fails: %3.1f.',solve_ok);
             end
          end
       end
       if (solve_ok < 0)
          if (m < 6000 & strcmp(matfct_options,'chol')) | ...
             (m < 1e5 & strcmp(matfct_options,'spchol'))
             use_LU = 1;
             if (printlevel); fprintf('\n  switch to LU factor'); end
          end
       end
    end
%%
%% LU factorization
%%
    if (use_LU)
       nnzmat = mexnnz(coeff.mat11)+mexnnz(coeff.mat12);
       nnzmatdiff = (nnzmat ~= nnzmatold);
       solve_ok = 1;
       if ~isempty(coeff.mat22)
          raugmat = [coeff.mat11, coeff.mat12; coeff.mat12', coeff.mat22];
       else
          raugmat = coeff.mat11;
       end
       if (nnzmat > spdensity*m^2) | (m+ncolU < 500)
          matfct_options = 'lu';
       else
          matfct_options = 'splu';
       end
       if (printlevel > 2); fprintf(' %s ',matfct_options); end
       L.matdim = length(raugmat);
       if strcmp(matfct_options,'lu')
          if issparse(raugmat); raugmat = full(raugmat); end
          L.matfct_options = 'lu';
          [L.L,L.U,L.p] = lu(raugmat,'vector');
       elseif strcmp(matfct_options,'splu')
          if ~issparse(raugmat); raugmat = sparse(raugmat); end
          L.matfct_options = 'splu';
          [L.L,L.U,L.p,L.q,L.s] = lu(raugmat,'vector');
          L.s = full(diag(L.s));
       elseif strcmp(matfct_options,'ldl')
          if issparse(raugmat); raugmat = full(raugmat); end
          L.matfct_options = 'ldl';
          [L.L,L.D,L.p] = ldl(raugmat,'vector');
          L.D = sparse(L.D);
       elseif strcmp(matfct_options,'spldl')
          if ~issparse(raugmat); raugmat = sparse(raugmat); end
          L.matfct_options = 'spldl';
          [L.L,L.D,L.p,L.s] = ldl(raugmat,'vector');
          L.s  = full(diag(L.s));
          L.Lt = L.L';
       end
       [xx,resnrm,solve_ok] = HSDbicgstab(coeff,rhs,L,[],[],printlevel);
       if (solve_ok<=0) & (printlevel)
          fprintf('\n  warning: HSDbicgstab fails: %3.1f,',solve_ok);
       end
    end
    if (printlevel>=3); fprintf('%2.0f ',length(resnrm)-1); end
%%
    nnzmatold = nnzmat; matfct_options_old = matfct_options;
%%***************************************************************


% LIONSIMBA example script
% Different heat exchange coefficients: this script provides the example simulation shown in the
% paper.

%   This file is part of the LIONSIMBA Toolbox
%
%	Official web-site: 	http://sisdin.unipv.it/labsisdin/lionsimba.php
% 	Official GitHUB: 	https://github.com/lionsimbatoolbox/LIONSIMBA
%
%   LIONSIMBA: A Matlab framework based on a finite volume model suitable for Li-ion battery design, simulation, and control
%   Copyright (C) 2016-2018 :Marcello Torchio, Lalo Magni, Davide Raimondo,
%                            University of Pavia, 27100, Pavia, Italy
%                            Bhushan Gopaluni, Univ. of British Columbia,
%                            Vancouver, BC V6T 1Z3, Canada
%                            Richard D. Braatz,
%                            Massachusetts Institute of Technology,
%                            Cambridge, Massachusetts 02142, USA
%
%   Main code contributors to LIONSIMBA 2.0:
%                           Ian Campbell, Krishnakumar Gopalakrishnan,
%                           Imperial college London, London, UK
%
%   LIONSIMBA is a free Matlab-based software distributed with an MIT
%   license.

% Clear the workspace
clear

% Define the integration times.
t0 = 0;
tf = 10^4;
% Define the parameters structure. By default the hcell parameter is set to
% 1 [W / (m^2 K)]
param{1} = Parameters_init;

% Change the hcell parameter and set it to 0.01 [W / (m^2 K)]
param{1}.hcell = 0.01;

% Start the simulation. Note that the final integration time is 10^4 and
% LIONSIMBA will stop automatically when reached the Cutoff Voltage of
% 2.5V. Note that no Jacobian among one simulation and the other. This is
% due to the fact that the model structure changes for each of the
% simulation (because hcell changes) and consequently also the Jacobian
% matrix changes and cannot be used for all the scenarios.

out1 = startSimulation(t0,tf,[],-30,param);

% Change the hcell parameter and set it to 1 [W / (m^2 K)]
param{1}.hcell = 1;

% Run the simulation
out2 = startSimulation(t0,tf,[],-30,param);

% Change the hcell parameter and set it to 100 [W / (m^2 K)]
param{1}.hcell = 100;

% Run the simulation
out3 = startSimulation(t0,tf,[],-30,param);

%% Plot the results

figure(1)
plot(out1.time{1},out1.Temperature{1}(:,end),'LineWidth',6)
hold on
plot(out2.time{1},out2.Temperature{1}(:,end),'--','LineWidth',6)
plot(out3.time{1},out3.Temperature{1}(:,end),'-.','LineWidth',6)
xlabel('Time [s]')
ylabel('Temperature [K]')
grid on
box on

figure(2)
plot(out1.time{1},out1.Voltage{1},'LineWidth',6)
hold on
plot(out2.time{1},out2.Voltage{1},'--','LineWidth',6)
plot(out3.time{1},out3.Voltage{1},'-.','LineWidth',6)
xlabel('Time [s]')
ylabel('Voltage [V]')
grid on
box on


function [Lmk,Obs] = reparametrizeLmk(Rob,Sen,Lmk,Obs,Opt)

%REPARAMETRIZELMK Reparametrize landmark.
%   [LMK,OBS] = REPARAMETRIZELMK(ROB,SEN,LMK,OBS,OPT) return the
%   reparametrized landmark and Obs structure.
%   The landmark is reparametrized only in the case of an inverse depth
%   point. A linearity test of cartesian point given inverse depth
%   point is performed.

%   Copyright 2009 David Marquez @ LAAS-CNRS.

global Map

switch Lmk.type

    case 'idpPnt'
        % we will convert from inverse-depth to euclidean.

        % Test for linearity:
        Ld = idpLinearTest(Rob,Sen,Lmk);

        if Ld < Opt.correct.linTestIdp

            % ranges
            ir = Lmk.state.r;  % idp
            er = ir(1:3);      % euclidean
            m  = Map.used;     % map

            % point coordinates
            idp     = Map.x(ir);   % idp
            [p,P_i] = idp2euc(idp);  % euclidean

            % map updates
            Map.x(er) = p;     % mean

            Map.P(er,m) = P_i * Map.P(ir,m); % co- and cross-variances
            Map.P(m,er) = Map.P(m,ir) * P_i';

            Map.used(Lmk.state.r(4:6)) = false; % used positions

            % Lmk and Obs updates
            Lmk.state.r = er;    % new range
            Lmk.type  = 'eucPnt'; % new type
            Obs.ltype = 'eucPnt'; % new type
        end

    case 'ahmPnt'
        % we will convert from anchored homogeneous to euclidean.

        % Test for linearity:
        Ld = ahmLinearTest(Rob,Sen,Lmk);

        if Ld < Opt.correct.linTestIdp

            % ranges
            ar  = Lmk.state.r;  % ahmPnt
            er  = ar(1:3);      % euclidean
            m   = Map.used;     % map

            % point coordinates
            ahm     = Map.x(ar);   % idp
            [p,P_a] = ahm2euc(ahm);  % euclidean

            % map updates
            Map.x(er)   = p;     % mean

            Map.P(er,m) = P_a * Map.P(ar,m); % co- and cross-variances
            Map.P(m,er) = Map.P(m,ar) * P_a';

            Map.used(Lmk.state.r(4:7)) = false; % used positions

            % Lmk and Obs updates
            Lmk.state.r = er;    % new range
            Lmk.type  = 'eucPnt'; % new type
            Obs.ltype = 'eucPnt'; % new type
        end

    case {'eucPnt'}
        % do nothing

    case {'hmgPnt','ahmPnt','plkLin','aplLin','idpLin','ahmLin','hmgLin'}
        % do nothing, by now <- probably add here something to do
        % Points should go to euclidean
        % Lines should go to some minimal representation (polar? 'plrLin')

    % case 'myLmk'
        % edit this 'myLmk' name to put your own landmark type
        % do something

    otherwise
        error('??? Unknown landmark type ''%s''.',Lmk.type)

end

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

%   # START GPL LICENSE

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

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

%   # END GPL LICENSE


%Script to ectract heterogenity metrics from MR images
%
%APA, 03/16/2010

global planC
indexS = planC{end};
structNum = 1;
disp('Heterogenity Metrics for MR')
[energy_40base,contrast_40base,Entropy_40base,Homogeneity_40base,standard_dev_40base,Ph_40base,slope_base] = getHaralicParams(structNum);
[jnk,jnk,raw] = xlsread('Cervix_MR_data.xls');
rowIndex = size(raw,1)+1;
dataM = [slope_base,energy_40base,contrast_40base,Entropy_40base,Homogeneity_40base,standard_dev_40base];
PtName = planC{indexS.scan}(1).scanInfo(1).patientName;
[SUCCESS,MESSAGE] = xlswrite('Cervix_MR_data.xls',{PtName},['A',num2str(rowIndex),':A',num2str(rowIndex)]);
if ~SUCCESS
    errordlg(MESSAGE.message,'Error Writing to Excel','modal')
    return
end
[SUCCESS,MESSAGE] = xlswrite('Cervix_MR_data.xls',{datestr(now)},['B',num2str(rowIndex),':B',num2str(rowIndex)]);
if ~SUCCESS
    errordlg(MESSAGE.message,'Error Writing to Excel','modal')
    return
end
acquisitionDate = datestr(datenum(num2str(planC{indexS.scan}(1).scanInfo(1).DICOMHeaders.AcquisitionDate),'yyyymmdd'));
[SUCCESS,MESSAGE] = xlswrite('Cervix_MR_data.xls',{acquisitionDate},['D',num2str(rowIndex),':D',num2str(rowIndex)]);
if ~SUCCESS
    errordlg(MESSAGE.message,'Error Writing to Excel','modal')
    return
end
[SUCCESS,MESSAGE] = xlswrite('Cervix_MR_data.xls',dataM,['E',num2str(rowIndex),':J',num2str(rowIndex)]);
if ~SUCCESS
    errordlg(MESSAGE.message,'Error Writing to Excel','modal')
    return
end


% OCR (Optical Character Recognition).
% PRINCIPAL PROGRAM
warning off %#ok<WNOFF>
% Clear all
clc, close all, clear all
% Read image
imagen=imread('TEST_1.jpg');
% Show image
imshow(imagen);
title('INPUT IMAGE WITH NOISE')
% Convert to gray scale
if size(imagen,3)==3 %RGB image
    imagen=rgb2gray(imagen);
end
% Convert to BW
threshold = graythresh(imagen);
imagen =~im2bw(imagen,threshold);
% Remove all object containing fewer than 30 pixels
imagen = bwareaopen(imagen,30);
%Storage matrix word from image
word=[ ];
re=imagen;
%Opens text.txt as file for write
fid = fopen('text.txt', 'wt');
% Load templates
load templates
global templates
% Compute the number of letters in template file
num_letras=size(templates,2);
while 1
    %Fcn 'lines' separate lines in text
    [fl re]=lines(re);
    imgn=fl;
    %Uncomment line below to see lines one by one
    %imshow(fl);pause(0.5)
    %-----------------------------------------------------------------
    % Label and count connected components
    [L Ne] = bwlabel(imgn);
    for n=1:Ne
        [r,c] = find(L==n);
        % Extract letter
        n1=imgn(min(r):max(r),min(c):max(c));
        % Resize letter (same size of template)
        img_r=imresize(n1,[42 24]);
        %Uncomment line below to see letters one by one
         %imshow(img_r);pause(0.5)
        %-------------------------------------------------------------------
        % Call fcn to convert image to text
        letter=read_letter(img_r,num_letras);
        % Letter concatenation
        word=[word letter];
    end
    %fprintf(fid,'%s\n',lower(word));%Write 'word' in text file (lower)
    fprintf(fid,'%s\n',word);%Write 'word' in text file (upper)
    % Clear 'word' variable
    word=[ ];
    %*When the sentences finish, breaks the loop
    if isempty(re)  %See variable 're' in Fcn 'lines'
        break
    end
end
fclose(fid);
%Open 'text.txt' file
winopen('text.txt')
fprintf('For more information, visit: <a href= "http://www.matpic.com">www.matpic.com </a> \n')
clear all


function [x,paramvec,paramindex,ons] = cond2reg(c,mspec,paramvec,paramindex)
% given a condition structure, returns regressor
%
% x is reg or set of regs to add to model
% paramvec is cell array of onsets (relative to...) for design reconstruction
% paramindex is index of which cell in paramvec to use for reconstruction of which condition
% ons is vector of trial onsets, for updating conditions, if necessary
%
% This function is not used in GA2: it's an extra function that mirrors a subfunction of
% construct_model.m
%
% THIS IS OLD! DOES IT WORK?
%
% Tor Wager

    if isfield(c,'parts')
        if c.parts ~= 1
            % can't build regressor from trial type with parts - return
            x = [];
           return
       end
    end

    % determine onset times
    % -----------------------------------------------------------------------------------
    delta = zeros(mspec.numframes,1);
    if size(c.onsets,1) == 1
        % fixed onsets for condition, but sub-trial may be variable

        if isfield(c,'baseons')     % for sub-parts of trials
            if size(c.onsets,2) == 2    % sub-trial, range is given; get random
                if length(paramvec) < paramindex,
                    paramvec{paramindex} = round(randrange(c.onsets,length(c.baseons)));
                end
                c.onsets = paramvec{paramindex};
                paramindex = paramindex + 1;
            end
            ons = c.onsets + c.baseons;

        else
            ons = c.onsets;

        end
        ons = round(ons);
        delta(1 + (ons)) = 1;

    else
        % variable (random) onsets
        if length(paramvec) < paramindex
            % build new ones if they're not input
            paramvec{paramindex} = onsetbuilder(c.onsets,mspec.numframes);
        end

        if isfield(c,'baseons')     % for sub-parts of trials
            ons = paramvec{paramindex} + c.baseons;
        else
            ons = paramvec{paramindex};
        end
        delta(1 + (paramvec{paramindex})) = 1;
        paramindex = paramindex + 1;
    end

    % convolve or shift
    % -----------------------------------------------------------------------------------

    if isfield(c,'parts')
        if c.parts == 1
            doconv = c.subcond(1).convolve;
            hrfest = c.subcond(1).hrfest;
        else
            error('This should never ever happen.')
        end
    else
        % this c IS a subpart
        doconv = c.convolve;
        hrfest = c.hrfest;
    end

    if doconv,
         x = conv(mspec.hrf,delta);
    elseif ~isempty(hrfest)
         sf{1} = delta;
         [x] = tor_make_deconv_mtx(sf,round(hrfest),1);
    else
         x = delta;
    end

    x = x(1:ceil(mspec.numframes),:);

return

% -----------------------------------------------------------------------------------
% * fill the run with as many trials as possible, given range of random lengths and delays
% -----------------------------------------------------------------------------------

function [onsets] = onsetbuilder(range,numframes)
% builds list of trials with random onset times
% range is range of onset times in condition.onsets, a 2 x 2 matrix

onsets = []; tend = 0;  % 0 is first time point in run
dlen = round(randrange(range(1,:),1));
dnaindex = 2;

while tend + dlen < numframes     % while onset of next trial is < end of run

    tlen = round(randrange(range(2,:),1));  % trial length
    if tend + dlen + tlen > numframes, break,end  % trial will not fit in run

    % add a trial
    onsets(end+1) = tend + dlen;            % specify onset after start delay of dlen
    tend = onsets(end) + tlen;              % specify ending point of trial
    dlen = round(randrange(range(1,:),1));  % re-randomize delay for next trial

end

% -----------------------------------------------------------------------------------
% * get a random number or vector within a specified range
% -----------------------------------------------------------------------------------
function rval = randrange(range,num)
    rval = rand(1,num) * (range(1,2) - range(1,1)) + range(1,1);
return


function confidences = test_boosted_dt_mc(classifier, features)
% confidences = test_boosted_dt_mc(classifier, features)
% returns a log likelihod ratio for each class in the classifier
% confidences(ndata, nclasses)

dt = classifier.wcs(1).dt;
if size(features, 2)~=dt.npred
    error('Incorrect number of attributes')
end

wcs = classifier.wcs;
nclasses = size(wcs, 2);

ntrees = size(wcs, 1);

confidences = zeros(size(features, 1), nclasses);
for c = 1:nclasses
    for t = 1:ntrees
        if ~isempty(wcs(t,c).dt)
            dt = wcs(t,c).dt;
            [var, cut, children, catsplit] = tree_getParameters(dt);
            nodes = treevalc(int32(var), cut, int32(children(:, 1)), ...
                    int32(children(:, 2)), catsplit(:, 1), features');
            %[class_indices, nodes2, classes] = treeval(wcs(t, c).dt, features);
            %         if sum(nodes~=nodes2)>0
            %              disp('error')
            % %              disp(num2str([nodes nodes2]))
            %         end
            confidences(:, c) = confidences(:, c) + wcs(t, c).confidences(nodes);
        end
    end
    confidences(:, c) = confidences(:, c) + classifier.h0(c);
end


%%***************************************************************************
%% steplength: compute xstep such that  X + xstep*dX >= 0.
%%
%% [xstep] = steplength(blk,X,dX,Xchol,invXchol);
%%
%% SDPT3: version 3.1
%% Copyright (c) 1997 by
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
%% Last Modified: 16 Sep 2004
%%***************************************************************************

    function [xstep,invXchol] = steplength(blk,X,dX,Xchol,invXchol);

%%
    for p = 1:size(blk,1)
       pblk = blk(p,:);
       numblk = length(pblk{2});
       pblksize = sum(pblk{2});
       if (any(isnan(dX{p})) | any(isinf(dX{p}))); xstep = 0; break; end;
       if strcmp(pblk{1},'s')
          if (max(pblk{2}) >= 200)
             use_lanczos = 1;
          else
             use_lanczos = 0;
          end
          if (use_lanczos)
             tol = 1e-3;
             maxit = max(min(pblksize,30),round(sqrt(pblksize)));
             [lam,delta,res] = lanczosfun(Xchol{p},-dX{p},maxit,tol);
             %%
             %% Note: lam <= actual largest eigenvalue <= lam + delta.
             %%
	     d = lam+delta;
          else
             if isempty(invXchol{p});
                invXchol{p} = inv(Xchol{p});
             end
	     tmp = Prod2(pblk,dX{p},invXchol{p},0);
             M = Prod2(pblk,invXchol{p}',tmp,1);
             if (exist('mexblkeig')==3)
                d = mexblkeig(pblk,-M);
             else
                d = blkeig(pblk,-M);
             end
          end
          tmp = max(d) + 1e-15*max(abs(d));
          if (tmp > 0);
             xstep(p) = 1/max(tmp);
          else
             xstep(p) = 1e12;
          end
       elseif strcmp(pblk{1},'q')
          aa = qops(pblk,dX{p},dX{p},2);
          bb = qops(pblk,dX{p},X{p},2);
          cc = qops(pblk,X{p},X{p},2);
          dd = bb.*bb - aa.*cc;
          tmp = min(aa,bb);
          idx = find(dd > 0 & tmp < 0);
          steptmp = 1e12*ones(numblk,1);
          if ~isempty(idx)
             steptmp(idx) = -(bb(idx)+sqrt(dd(idx)))./aa(idx);
          end
          idx = find(abs(aa) < eps & bb < 0);
          if ~isempty(idx)
             steptmp(idx) = -cc(idx)./(2*bb(idx));
          end
          %%
          %% also need first component to be non-negative
          %%
          ss = 1 + [0, cumsum(pblk{2})];
          ss = ss(1:length(pblk{2}));
          dX0 = dX{p}(ss);
          X0 = X{p}(ss);
          idx = find(dX0 < 0 & X0 > 0);
          if ~isempty(idx)
             steptmp(idx) = min(steptmp(idx),-X0(idx)./dX0(idx));
          end
          xstep(p) = min(steptmp);
       elseif strcmp(pblk{1},'l')
          idx = find(dX{p} < 0);
          if ~isempty(idx)
             xstep(p) = min(-X{p}(idx)./dX{p}(idx));
          else
             xstep(p) = 1e12;
          end
       elseif strcmp(pblk{1},'u')
          xstep(p) = 1e12;
       end
    end
    xstep = min(xstep);
%%***************************************************************************
%%***************************************************************************
%% lanczos: find the largest eigenvalue of
%%          invXchol'*dX*invXchol via the lanczos iteration.
%%
%% [lam,delta] = lanczosfun(Xchol,dX,maxit,tol,v)
%%
%% lam:  an estimate of the largest eigenvalue.
%% lam2: an estimate of the second largest eigenvalue.
%% res:  residual norm of the largest eigen-pair.
%% res2: residual norm of the second largest eigen-pair.
%%***************************************************************************

   function [lam,delta,res] = lanczosfun(Xchol,dX,maxit,tol,v)

   if (norm(dX,'fro') < 1e-13)
      lam = 0; delta = 0; res = 0;
      return;
   end
   n = length(dX);
   if (nargin < 5);
      state = randn('state');
      randn('state',0);
      v = randn(n,1);
      randn('state',state);
   end
   if (nargin < 4); tol = 1e-3; end
   if (nargin < 3); maxit = 30; end
   V = zeros(n,maxit+1); H = zeros(maxit+1,maxit);
   v = v/norm(v);
   V(:,1) = v;
   if issparse(Xchol); Xcholtransp = Xchol'; end
%%
%% lanczos iteration.
%%
   for k = 1:maxit
      if issparse(Xchol)
         w = dX*mextriangsp(Xcholtransp,v,1);
         w = mextriangsp(Xchol,w,2);
      else
         w = dX*mextriang(Xchol,v,1);
         w = mextriang(Xchol,w,2);
      end
      wold = w;
      if (k > 1);
         w = w - H(k,k-1)*V(:,k-1);
      end;
      alp = w'*V(:,k);
      w   = w - alp*V(:,k);
      H(k,k) = alp;
      %%
      %% one step of iterative refinement if necessary.
      %%
      if (norm(w) <= 0.8*norm(wold));
         s = (w'*V(:,1:k))';
         w = w - V(:,1:k)*s;
         H(1:k,k) = H(1:k,k) + s;
      end;
      nrm = norm(w);
      v = w/nrm;
      V(:,k+1) = v;
      H(k+1,k) = nrm;  H(k,k+1) = nrm;
      %%
      %% compute ritz pairs and test for convergence
      %%
      if (rem(k,5) == 0) | (k == maxit);
         Hk = H(1:k,1:k); Hk = 0.5*(Hk+Hk');
         [Y,D] = eig(Hk);
         eigH  = real(diag(D));
         [dummy,idx] = sort(eigH);
         res_est = abs(H(k+1,k)*Y(k,idx(k)));
         if (res_est <= 0.1*tol) | (k == maxit);
            lam = eigH(idx(k));
            lam2 = eigH(idx(k-1));
            z  = V(:,1:k)*Y(:,idx(k));
            z2 = V(:,1:k)*Y(:,idx(k-1));
            if issparse(Xchol)
               tmp = dX*mextriangsp(Xcholtransp,z,1);
               res = norm(mextriangsp(Xchol,tmp,2) -lam*z);
               tmp = dX*mextriangsp(Xcholtransp,z2,1);
               res2 = norm(mextriangsp(Xchol,tmp,2) -lam*z2);
            else
               tmp = dX*mextriang(Xchol,z,1);
               res = norm(mextriang(Xchol,tmp,2) -lam*z);
               tmp = dX*mextriang(Xchol,z2,1);
               res2 = norm(mextriang(Xchol,tmp,2) -lam*z2);
            end
            tmp = lam-lam2 -res2;
            if (tmp > 0); beta = tmp; else; beta = eps; end;
            delta = min(res,res^2/beta);
            if (delta <= tol); break; end;
         end
      end
   end
%%***************************************************************************


% Copyright (C) Daphne Koller, Stanford Univerity, 2012
%
% Author: Huayan Wang

function VisualizeModels(P, G)
K = length(P.c);

f = figure;
while(1)
    for k=1:K
        subplot(1,K,k);
        if size(G,3) == 1  % same graph structure for all classes

            pose = SamplePose(P,G,k);

        else  % different graph structure for each class

            pose = SamplePose(P,G(:,:,k),k);

        end

        img = ShowPose(pose);
        imshow(img);
        pause(0.3)
        if (~ishandle(f)) return; end; % quit loop when user closes the figure
    end
end


function model=rmInterpolate(view,model,params)
% rmInterpolate - interpolate missing values across the Gray surface
% that were not sampled with the coarse sampling
%
% model = rmInterpolate(view,model,params);
%
% 2007/03 SOD: wrote it.

if notDefined('view'),   error('Need view');   end;
if notDefined('model'),  error('Need model');  end;
if notDefined('params'), error('Need params'); end;

numNeighbors = double(view.nodes(4,:));
myzeros      = zeros(size(numNeighbors));
grayConMat   = [];

roiCoords = rmGet(params,'roiCoords');
if ~isempty(roiCoords),
    % find the index' that cover the roi
    doROI = true;
    inROI = rmGet(params,'roiIndex');
    % coords with data within roi
    coarseIndex     = rmCoarseSamples(roiCoords,params.analysis.coarseSample);
    withData        = logical(myzeros);
    withData(inROI(coarseIndex)) = true;

    % coords without data within roi
    toInterp        = logical(myzeros);
    toInterp(inROI(~coarseIndex)) = true;
else
    doROI    = false;
    coarseIndex     = rmCoarseSamples(viewGet(view,'coords'),params.analysis.coarseSample);
    % coords with data
    withData = coarseIndex;
    % coords without data
    toInterp = ~coarseIndex;
end;

% Sanity check: we only need interpolation if there are points to
% interpolate, e.g. very small ROIs will not be coarsely sampled.
if all(coarseIndex), % if all data points have estimates,
    return;
end;

% now we have to loop over models and parameters
%rp = {'x','y','s','rss','rawrss','x02','y02','s2','rss2','rawrss2', 'exponent','sigmamajor','sigmaminor'};
for n=1:numel(model),
    if strcmp(model{n}.description,'radial oval 2D pRF fit (x,y,sigma_major,sigma_minor)')
        rp = {'x','y','rss','rawrss','x02','y02','rss2','rawrss2', 'exponent','sigmamajor','sigmaminor','theta'};
    else
        rp = {'x','y','s','rss','rawrss','x02','y02','s2','rss2','rawrss2', 'exponent'};
    end

    % reset for different models (should be the same i think)
    fulval = myzeros;
    for p=1:numel(rp),
        val = rmGet(model{n},rp{p});
        if ~isempty(val) && numel(val)==sum(coarseIndex),
            % put data in full datastructure and fill the rest with zeros
            if doROI,
                fulval(inROI(coarseIndex)) = double(val);
            else
                fulval(coarseIndex)        = double(val);
            end;
            % now interpolate the data to some voxels without data
            %newval = myinterp(fulval,withData,toInterp,edges,numNeighbors,edgeOffsets);
            [newval grayConMat] = myinterp(fulval,withData,toInterp,view,grayConMat);
            % if roi we should store the roi voxels only otherwise store
            % the whole thing
            if doROI,
                model{n} = rmSet(model{n},rp{p},newval(inROI));
            else
                model{n} = rmSet(model{n},rp{p},newval);
            end;
        elseif ~isempty(val) && numel(val)==numel(fulval),
            model{n} = rmSet(model{n},rp{p},val);
        end;
    end;
    if isfield(model{n}, 'exponent') && ~isempty(model{n}.exponent) && ~strcmp(model{n}.description,'radial oval 2D pRF fit (x,y,sigma_major,sigma_minor)')
        model{n} = rmSet(model{n}, 's', model{n}.sigma.major .* sqrt(model{n}.exponent));
    end
end;

% separate loop for the betas, because they are saved in a different way
for n=1:numel(model),
    % reset for different models (should be the same i think)
    fulval = myzeros;
    val = double(rmGet(model{n},'b'));
    nBetas  = size(val,3);
    newBeta = zeros(size(val,1),numel(coarseIndex),nBetas);

    for ii=1:nBetas,
        if doROI,
            fulval(inROI(coarseIndex)) = double(val(:,:,ii));
        else
            fulval(coarseIndex) = double(val(:,:,ii));
        end
        newval = myinterp(fulval,withData,toInterp,view,grayConMat);
        % if roi we should store the roi voxels only otherwise store
        % the whole thing
        if doROI,
            newBeta(:,:,ii) = newval(inROI);
        else
            newBeta(:,:,ii) = newval;
        end;
    end;
    model{n} = rmSet(model{n},'b',newBeta);
end;

return;
%---------------------------------------

%---------------------------------------
function [val grayConMat] = myinterp(val,withData,toInterp,view,grayConMat)
% actual interpolation function

lzeros     = false(size(withData));
doTouch    = toInterp;  % keep refining these estimates
oldtoInterp = toInterp;
while (1),
    % 'smooth' data. Points without data are zero and do contribute to this
    % initial estimate:
    [tmp grayConMat] = dhkGraySmooth(view,val,[1 1],grayConMat);

    % Now check which surrounding points had data, 0=no data in
    % neighborhood, 1=all neighbors have data, intermediate is the weight
    % that should have been used to create the new estimate and will be
    % used to remove the contributions of no-data neighbors (0).
    c2               = dhkGraySmooth(view,double(withData),[1 1],grayConMat);

    % All point that we want to interpolate (doTouch) that have neighbors
    % with data and that thus will have a new estimate.
    toInterp          = lzeros;
    toInterp(doTouch) = c2(doTouch)>0.001;

    % Compute new final values taking into account the number of points
    % that had data (c2)
    val(toInterp)     = tmp(toInterp)./c2(toInterp);

    % update toInterp: find voxels that still need interpolating
    toInterp       = (oldtoInterp-toInterp)>0;

    % sanity check: if no changes in toInterp than quit. Ideally
    % toInterp should go to zero but this does not have to be the
    % case if some voxels are not connected to voxels with data.
    if any(oldtoInterp-toInterp) || sum(toInterp)==0,
        break;
    else
        % 'grow' logical matrix that keeps track of which voxels have data
        withData       = toInterp | withData;
        % update
        oldtoInterp = toInterp;
    end;
end;

return;
%---------------------------------------


%  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 St, Fifth Floor, Boston, MA  02110-1301  USA
%function izakt
%IZAKT	Unit test for the function izak.

%	O. Lemoine - February 1996.

N=256;

% Perfect reconstruction
sig=noisecg(N);
DZT=zak(sig);
sigr=izak(DZT);
errors=find(any(abs(sig-sigr)>sqrt(eps)));
if length(errors)~=0,
  error('izak test 1 failed');
end

sig=noisecg(N);
DZT=zak(sig,8,32);
sigr=izak(DZT);
errors=find(any(abs(sig-sigr)>sqrt(eps)));
if length(errors)~=0,
  error('izak test 2 failed');
end

sig=noisecg(N);
DZT=zak(sig,128,2);
sigr=izak(DZT);
errors=find(any(abs(sig-sigr)>sqrt(eps)));
if length(errors)~=0,
  error('izak test 3 failed');
end

N=315;

% Perfect reconstruction
sig=noisecg(N);
DZT=zak(sig);
sigr=izak(DZT);
errors=find(any(abs(sig-sigr)>sqrt(eps)));
if length(errors)~=0,
  error('izak test 4 failed');
end

sig=noisecg(N);
DZT=zak(sig,9,35);
sigr=izak(DZT);
errors=find(any(abs(sig-sigr)>sqrt(eps)));
if length(errors)~=0,
  error('izak test 5 failed');
end

sig=noisecg(N);
DZT=zak(sig,3,105);
sigr=izak(DZT);
errors=find(any(abs(sig-sigr)>sqrt(eps)));
if length(errors)~=0,
  error('izak test 6 failed');
end


% THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION IS RELEASED "AS IS."  THE U.S. GOVERNMENT MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, CONCERNING THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT WILL THE U.S. GOVERNMENT BE LIABLE FOR ANY DAMAGES, INCLUDING ANY LOST PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE, OR INABILITY TO USE, THIS SOFTWARE OR ANY ACCOMPANYING DOCUMENTATION, EVEN IF INFORMED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
%
% integrate_poisspdf.m
% integrates a poisson pdf with respect to lambda from a to b
%
% 022300 tdr created
% 030400 tdr replaced global variable approach to getting x and n to binopdf.
% 030600 tdr added adjustments to a and b to help quad8 converge quickly.
% 			quad8 has trouble with long stretches of near-zero values
% 			so we try to bound the interval to avoid these regions
% 031600 tdr created integrate_poisspdf.m from integrate_binopdf.m
% 012901 tdr changed quad8 to quadl per MatLab 6 recommendation.  Turned off warnings
%   for quadl call because it thinks intervals starting at zero or ending at one
%   involve singularities and generates a warning, although accuracy is okay.
% 031501 tdr changed thres2 from 0.001 to 1.

function y = integrate_poisspdf(x,a,b)

if nargin ~= 3,
    error('Requires three input arguments (x,a,b)');
end

TRACE = 0;
lambda_hat = x;
thres = 1e-6*poisspdf_0ok(x,x); % pdf values less than this are assumed to be negligible.
thres2 = 1; % resolution of adjustments to a and b.
tiny_a = (poisspdf_0ok(x,a) < thres);
tiny_b = (poisspdf_0ok(x,b) < thres);

if tiny_a & tiny_b & (a > lambda_hat | b < lambda_hat),
	%both a and b give results near zero, with no non-zero values between them
   y = 0;
   return
end;

% defaults
new_a = a;
new_b = b;

if tiny_a,
	% a needs to be increased, but not past b or lambda_hat
	ll = a; ul = min(b, lambda_hat);
   while (abs(ll - ul) > thres2),
   	test = (ll + ul)/2;
      if poisspdf_0ok(x,test) < thres,
      	ll = test;
      else
      	ul = test;
      end;
   end;
	new_a = ll;
end;

if tiny_b,
	% b needs to be decreased, but not past a or lambda_hat
	ll = max(a, lambda_hat); ul = b;
   while (abs(ll - ul) > thres2),
   	test = (ll + ul)/2;
      if poisspdf_0ok(x,test) < thres,
      	ul = test;
      else
      	ll = test;
      end;
   end;
	new_b = ul;
end;

% call quad with increased a
%   quadl thinks interval starting at zero or ending at one might involve
%   a singularity and produces a warning, despite being accurate.
warning off;
y=quadl('poisspdf_of_lambda',new_a,new_b,[],TRACE,x);
warning on;


function view=mrv_dilateCurrentROI(view,iterations)
% function d=mrv_dilateCurrentROI(view)
% PURPOSE: Dilates the current ROI in the Gray view.
% HISTORY: 100704: ARW: Wrote it.
% Note: Large numbers of iterations can result in long processing times.
if (~exist('iterations','var'))
    iterations=1;
end
if ~(strcmp(view.viewType,'Gray') | strcmp(view.viewType,'Volume'))
    error('This routine requires you to be in the Gray view');
end

thisROI=view.ROIs(view.selectedROI);
if(~isfield(view,'grayConMat') | isempty(view.grayConMat));
    disp('Computing connection matrix...');
    view.grayConMat = makeGrayConMat(view.nodes,view.edges,0);
end
thisROI.coords=mrv_dilateGrayROI(view,thisROI.coords,iterations);
thisROI.name=[thisROI.name,'_dilated'];
view=addROI(view,thisROI);
return;


function calcRigor( config )
%RIGOR Summary of this function goes here
%   Detailed explanation goes here

rigorconfig = config.rigor;
param = rigorconfig.params.param_set;

%Check if image location exists or not.

if(~exist(config.imageLocation, 'dir'))
	fprintf('Image Location does not exist. Please check path once again \n');
	return;
end

if(~exist(config.outputLocation, 'dir'))
	fprintf('Image Location does not exist. Please check path once again \n');
	return;
end

%Load All images in a particular folder
images = dir(config.imageLocation);
images = regexpi({images.name}, '.*jpg|.*jpeg|.*png|.*bmp', 'match');
images = [images{:}];

for i=1:length(images)
    imname = char(images(i));
    impath = fullfile(config.imageLocation, imname);
    whos impath
    im=imread(impath);
    fprintf('Calculating RIGOR for %s\n', imname);
    proposals =calcrigorForIm(impath,rigorconfig);
    saveFile=[imname '.mat'];
    save([config.outputLocation saveFile], 'proposals');
end
end