%PoseGraph Pose graph

% Copyright (C) 1993-2017, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com
classdef PoseGraph < handle

    properties
        graph

        ngrid
        center
        cellsize
    end

    methods

        function pg = PoseGraph(filename, varargin)
            % parse the file data
            % we assume g2o format
            %    VERTEX* vertex_id X Y THETA
            %    EDGE* startvertex_id endvertex_id X Y THETA IXX IXY IYY IXT IYT ITT
            % vertex numbers start at 0

            opt.laser = false;

            opt = tb_optparse(opt, varargin);

            pg.graph = PGraph(3, 'distance', 'SE2');

            fp = fopen(filename, 'r');
            assert(fp > 0, 'Can''t open file %s', filename);

            toroformat = false;
            nlaser = 0;

            % indices into ROBOTLASER1 record for the 3x3 info matrix in column major
            % order
            g2o =  [6  7  8  7  9  10   8  10  11];
            toro = [6  7 10  7  8  11  10  11   9];

            % we keep an array pgi = vindex(gi) to map g2o vertex index to PGraph vertex index

            tic
            while ~feof(fp)

                line = fgets(fp);

                % is it a comment?
                if line(1) == '#'
                    continue;
                end

                % get keyword
                k = strfind(line, ' ');

                % and deal with it
                switch line(1:k-1)
                    case 'VERTEX_SE2'
                        % g2o format vertex
                        vertex = sscanf(line(k+1:end), '%d %f %f %f')';
                        v = pg.graph.add_node(vertex(2:4));
                        vindex(vertex(1)+1) = v;
                        vd.type = 'vertex';
                        pg.graph.setvdata(v, vd);

                    case 'VERTEX_XY'
                        vertex = sscanf(line(k+1:end), '%d %f %f')';
                        v = pg.graph.add_node(vertex(2:4));
                        vindex(vertex(1)+1) = v;
                        vd.type = 'landmark';
                        pg.graph.setvdata(v, vd);

                    case 'EDGE_SE2'
                        % g2o format edge
                        edge = sscanf(line(k+1:end), '%f')';
                        v1 = vindex(edge(1)+1);
                        v2 = vindex(edge(2)+1);

                        % create the edge
                        e = pg.graph.add_edge(v1, v2);

                        % create the edge data as a structure
                        %  X  Y  T
                        %  3  4  5
                        ed.mean = edge(3:5);

                        % IXX IXY IXT IYY IYT ITT
                        %   6   7   8   9  10  11
                        ed.info = reshape(edge(g2o), [3 3]);

                        % and attach it
                        pg.graph.setedata(e, ed);

                    case 'VERTEX2'
                        toroformat = true;
                        vertex = sscanf(line(k+1:end), '%d %f %f %f')';
                        v = pg.graph.add_node(vertex(2:4));
                        vindex(vertex(1)+1) = v;
                        vd.type = 'vertex';
                        pg.graph.setvdata(v, vd);

                    case 'EDGE2'
                        toroformat = true;
                        edge = sscanf(line(k+1:end), '%f')';
                        v1 = vindex(edge(1)+1);
                        v2 = vindex(edge(2)+1);

                        % create the edge
                        e = pg.graph.add_edge(v1, v2);
                        % create the edge data as a structure
                        %  X  Y  T
                        %  3  4  5
                        ed.mean = edge(3:5);

                        % IXX IXY IYY ITT IXT IYT
                        %   6   7   8   9  10  11
                        ed.info = reshape(edge(toro), [3 3]);
                        % and attach it
                        pg.graph.setedata(e, ed);

                    case 'ROBOTLASER1'
                        if ~opt.laser
                            continue;
                        end

                        % laser records are associated with the immediately preceding VERTEX record
                        [laser,n] = sscanf(line(k+1:end), '%f');
                        nbeams = laser(8);
                        vd.theta = [0:nbeams-1] * laser(4) + laser(2);
                        vd.range = laser(9:8+nbeams)';
                        vd.time = laser(21+nbeams);
                        pg.graph.setvdata(v, vd);
                        nlaser = nlaser + 1;

                    otherwise
                        error('RTB:posegraph:badfile', 'Unexpected line  <%s> in %s', line(1:k-1), filename);
                end
            end
            elapsed = toc;

            fclose(fp);

            if toroformat
                fprintf('loaded TORO/LAGO format file: %d nodes, %d edges in %.2f sec\n', pg.graph.n, pg.graph.ne, elapsed);
            else
                fprintf('loaded g2o format file: %d nodes, %d edges in %.2f sec\n', pg.graph.n, pg.graph.ne, elapsed);
                if nlaser > 0
                    fprintf('  %d laser scans: %d beams, fov %g to %g deg, max range %g\n', ...
                        nlaser, nbeams, [laser(2) sum(laser(2:3))]*180/pi, laser(5) );
                end
            end
        end

        function [r, theta] = scan(pg, n)
            vd = pg.graph.vdata(n);
            r = vd.range;
            theta = vd.theta;
        end

        function [X,Y] = scanxy(pg, n)
            vd = pg.graph.vdata(n);

            [x,y] = pol2cart(vd.theta, vd.range);
            if nargout == 1
                X = [x; y];
            elseif nargout == 2
                X = x; Y = y;
            end
        end

        function plot_scan(pg, n)
            for i=n(:)'
                [x,y] = pg.scanxy(i);
                plot(x, y, '.', 'MarkerSize', 10);
                pause
            end
        end

        function xyt = pose(pg, i)
            xyt = pg.graph.coord(i);
        end

        function t = time(pg, n)
            t = pg.graph.vdata(n).time;
        end

        function plot(pg, varargin)
            pg.graph.plot(varargin{:});
            xlabel('x')
            ylabel('y')
            grid on
        end

        function world = scanmap(pg, varargin)

            opt.center = [75 50];
            opt.ngrid = 3000;
            opt.cellsize = 0.1;

            pg = tb_optparse(opt, varargin, pg);

            h = waitbar(0, 'rendering a map');

            world = zeros(pg.ngrid, pg.ngrid, 'int32');
            for i=1:1:pg.graph.n

                if rem(i, 20) == 0
                    waitbar(i/pg.graph.n, h)
                end

                xy = pg.scanxy(i);
                [r,theta] = pg.scan(i);
                xy(:,r>40) = [];
                xyt = pg.graph.coord(i);

                xy = SE2(xyt) * xy;

                % start of each ray
                [x1,y1] = pg.w2g(xyt(1:2));

                for s=1:numcols(xy)

                    % end of each ray
                    [x2,y2] = pg.w2g(xy(:,s));

                    % all cells along the ray
                    p = bresenham(x1, y1, x2, y2);
                    try
                        k = sub2ind(size(world), p(:,1), p(:,2));

                        k1 = k(1:end-1); k2 = k(end);
                        world(k1) = world(k1) - 1;
                        world(k2) = world(k2) + 1;
                    catch me
                        % come here if any point on the ray is outside the grid
                        % silently ignore it
                    end
                end
            end
            close(h)
            %idisp(world)
        end

        function [gx,gy] = w2g(pg, w)
            dd = 0.10;

            w = w(:) + pg.center(:);
            g = round(w/pg.cellsize);
            gx = g(1); gy = g(2);
        end

        function plot_occgrid(pg, w)

            x = [1:numcols(w)]*pg.cellsize - pg.center(1);
            y = [1:numrows(w)]*pg.cellsize - pg.center(2);
            w(w<0) = -1;
            w(w>0) = 1;
            w=-w;
            idisp(w, 'nogui', 'xydata', {x, y})
            xlabel('x'); ylabel('y');
        end

        %   This source code is part of the graph optimization package
        %   deveoped for the lectures of robotics2 at the University of Freiburg.
        %
        %     Copyright (c) 2007 Giorgio Grisetti, Gian Diego Tipaldi
        %
        %   It is licences under the Common Creative License,
        %   Attribution-NonCommercial-ShareAlike 3.0
        %
        %   You are free:
        %     - to Share - to copy, distribute and transmit the work
        %     - to Remix - to adapt the work
        %
        %   Under the following conditions:
        %
        %     - Attribution. You must attribute the work in the manner specified
        %       by the author or licensor (but not in any way that suggests that
        %       they endorse you or your use of the work).
        %
        %     - Noncommercial. You may not use this work for commercial purposes.
        %
        %     - Share Alike. If you alter, transform, or build upon this work,
        %       you may distribute the resulting work only under the same or
        %       similar license to this one.
        %
        %   Any of the above conditions can be waived if you get permission
        %   from the copyright holder.  Nothing in this license impairs or
        %   restricts the author's moral rights.
        %
        %   This software 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.

        %ls-slam.m
        %this file is released under the creative common license

        %solves a graph-based slam problem via least squares
        %vmeans: matrix containing the column vectors of the poses of the vertices
        %	 the vertices are odrered such that vmeans[i] corresponds to the ith id
        %eids:	 matrix containing the column vectors [idFrom, idTo]' of the ids of the vertices
        %	 eids[k] corresponds to emeans[k] and einfs[k].
        %emeans: matrix containing the column vectors of the poses of the edges
        %einfs:  3d matrix containing the information matrices of the edges
        %	 einfs(:,:,k) refers to the information matrix of the k-th edge.
        %n:	 number of iterations
        %newmeans: matrix containing the column vectors of the updated vertices positions

        function g2 = optimize(pg, varargin)

            opt.iterations = 10;
            opt.animate = false;
            opt.retain = false;

            opt = tb_optparse(opt, varargin);

            g2 = PGraph(pg.graph);  % deep copy

            eprev = Inf;
            for i=1:opt.iterations
                if opt.animate
                    if ~opt.retain
                        clf
                    end
                    g2.plot();
                    pause(0.5)
                end

                [vmeans,energy] = linearize_and_solve(g2);
                g2.setcoord(vmeans);

                if energy >= eprev
                    break;
                end
                eprev = energy;
            end;

            pg.graph = g2;
        end
    end % methods
end % classdef

%computes the taylor expansion of the error function of the k_th edge
%vmeans: vertices positions
%eids:   edge ids
%emeans: edge means
%k:	 edge number
%e:	 e_k(x)
%A:	 d e_k(x) / d(x_i)
%B:	 d e_k(x) / d(x_j)
%function [e, A, B]=linear_factors(vmeans, eids, emeans, k)
function [e, A, B]=linear_factors(g, edge)
    %extract the ids of the vertices connected by the kth edge
    % 	id_i=eids(1,k);
    % 	id_j=eids(2,k);
    %extract the poses of the vertices and the mean of the edge
    %     v_i=vmeans(:,id_i);
    %     v_j=vmeans(:,id_j);
    %     z_ij=emeans(:,k);

    v = g.vertices(edge);
    v_i = g.coord(v(1));
    v_j = g.coord(v(2));
    z_ij = g.edata(edge).mean;

    %compute the homoeneous transforms of the previous solutions
    zt_ij=v2t(z_ij);
    vt_i=v2t(v_i);
    vt_j=v2t(v_j);

    %compute the displacement between x_i and x_j

    f_ij=(inv(vt_i)*vt_j);

    %this below is too long to explain, to understand it derive it by hand
    theta_i=v_i(3);
    ti=v_i(1:2,1);
    tj=v_j(1:2,1);
    dt_ij=tj-ti;

    si=sin(theta_i);
    ci=cos(theta_i);

    A= [-ci, -si, [-si, ci]*dt_ij; si, -ci, [-ci, -si]*dt_ij; 0, 0, -1 ];
    B =[  ci, si, 0           ; -si, ci, 0            ; 0, 0, 1 ];

    ztinv=inv(zt_ij);
    e=t2v(ztinv*f_ij);
    ztinv(1:2,3) = 0;
    A=ztinv*A;
    B=ztinv*B;

    % 	%compute the homogeneous transforms of the previous solutions
    % 	zt_ij=v2t(z_ij);
    % 	vt_i=v2t(v_i);
    % 	vt_j=v2t(v_j);
    % %     zt_ij = SE2(z_ij);
    % % 	vt_i = SE2(v_i);
    % % 	vt_j = SE2(v_j);
    %
    % 	%compute the displacement between x_i and x_j
    % 	%f_ij=(inverse(vt_i)*vt_j);
    % 	f_ij = vt_i.inv * vt_j;
    %
    % 	%this below is too long to explain, to understand it derive it by hand
    %       	theta_i=v_i(3);
    % 	ti=v_i(1:2);
    % 	tj=v_j(1:2);
    %       	dt_ij=tj-ti;
    %
    % 	si=sin(theta_i);
    % 	ci=cos(theta_i);
    %
    % 	A= [-ci, -si, [-si, ci]*dt_ij; si, -ci, [-ci, -si]*dt_ij; 0, 0, -1 ];
    % 	B =[  ci, si, 0           ; -si, ci, 0            ; 0, 0, 1 ];
    %
    % 	ztinv = inv(zt_ij);
    % 	e = xyt(ztinv*f_ij);
    % 	ztinv.t = 0;
    % 	A = ztinv*A;
    % 	B = ztinv*B;
end

%linearizes and solves one time the ls-slam problem specified by the input
%vmeans:   vertices positions at the linearization point
%eids:     edge ids
%emeans:   edge means
%einfs:    edge information matrices
%newmeans: new solution computed from the initial guess in vmeans
function [newmeans,energy] = linearize_and_solve(g)
    tic
    fprintf('solving');

    % H and b are respectively the system matrix and the system vector
    H=zeros(g.n*3,g.n*3);
    b=zeros(g.n*3,1);
    % this loop constructs the global system by accumulating in H and b the contributions
    % of all edges (see lecture)
    %for k=1:size(eids,2)
    fprintf('.');

    etotal = 0;
    for edge = 1:g.ne

        [e, A, B]=linear_factors(g, edge);
        omega = g.edata(edge).info;
        %compute the blocks of H^k

        % not quite sure whey SE3 is being transposed, what does that mean?
        b_i = -A'*omega*e;
        b_j = -B'*omega*e;
        H_ii = A'*omega*A;
        H_ij = A'*omega*B;
        H_jj = B'*omega*B;

        v = g.vertices(edge);
        id_i = v(1); id_j = v(2);
        %accumulate the blocks in H and b
        H((id_i-1)*3+1:id_i*3,(id_i-1)*3+1:id_i*3) = H((id_i-1)*3+1:id_i*3,(id_i-1)*3+1:id_i*3) + H_ii;
        H((id_j-1)*3+1:id_j*3,(id_j-1)*3+1:id_j*3) = H((id_j-1)*3+1:id_j*3,(id_j-1)*3+1:id_j*3) + H_jj;
        H((id_i-1)*3+1:id_i*3,(id_j-1)*3+1:id_j*3) = H((id_i-1)*3+1:id_i*3,(id_j-1)*3+1:id_j*3) + H_ij;
        H((id_j-1)*3+1:id_j*3,(id_i-1)*3+1:id_i*3) = H((id_j-1)*3+1:id_j*3,(id_i-1)*3+1:id_i*3) + H_ij';

        b((id_i-1)*3+1:id_i*3,1) = b((id_i-1)*3+1:id_i*3,1) + b_i;
        b((id_j-1)*3+1:id_j*3,1) = b((id_j-1)*3+1:id_j*3,1) + b_j;

        %NOTE on Matlab compatibility: note that we use the += operator which is octave specific
        %using H=H+.... results in a tremendous overhead since the matrix would be entirely copied every time
        %and the matrix is huge
        etotal = etotal + e'*e;
    end;
    fprintf('.');

    %note that the system (H b) is obtained only from
    %relative constraints. H is not full rank.
    %we solve the problem by anchoring the position of
    %the the first vertex.
    %this can be expressed by adding the equation
    %  deltax(1:3,1)=0;
    %which is equivalent to the following
    H(1:3,1:3) = H(1:3,1:3) + eye(3);

    SH=sparse(H);
    fprintf('.');
    deltax=SH\b;
    fprintf('.');

    %split the increments in nice 3x1 vectors and sum them up to the original matrix
    newmeans = g.coord()+reshape(deltax,3,g.n);

    %normalize the angles between -PI and PI
    for (i=1:size(newmeans,2))
        s=sin(newmeans(3,i));
        c=cos(newmeans(3,i));
        newmeans(3,i)=atan2(s,c);
    end
    dt = toc;
    fprintf('done in %.2g sec.  Total cost %g \n', dt, etotal);
    if nargout > 1
        energy = etotal;
    end
end

%   This source code is part of the graph optimization package
%   deveoped for the lectures of robotics2 at the University of Freiburg.
%
%     Copyright (c) 2007 Giorgio Grisetti, Gian Diego Tipaldi
%
%   It is licences under the Common Creative License,
%   Attribution-NonCommercial-ShareAlike 3.0
%
%   You are free:
%     - to Share - to copy, distribute and transmit the work
%     - to Remix - to adapt the work
%
%   Under the following conditions:
%
%     - Attribution. You must attribute the work in the manner specified
%       by the author or licensor (but not in any way that suggests that
%       they endorse you or your use of the work).
%
%     - Noncommercial. You may not use this work for commercial purposes.
%
%     - Share Alike. If you alter, transform, or build upon this work,
%       you may distribute the resulting work only under the same or
%       similar license to this one.
%
%   Any of the above conditions can be waived if you get permission
%   from the copyright holder.  Nothing in this license impairs or
%   restricts the author's moral rights.
%
%   This software 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.

%computes the homogeneous transform matrix A of the pose vector v
function A=v2t(v)
    c=cos(v(3));
    s=sin(v(3));
    A=[c, -s, v(1) ;
        s,  c, v(2) ;
        0   0  1  ];
end

%computes the pose vector v from an homogeneous transform A
function v=t2v(A)
    v(1:2, 1)=A(1:2,3);
    v(3,1)=atan2(A(2,1),A(1,1));
end


function test01 ( prefix )

%*****************************************************************************80
%
%% TEST01 tests XY_TO_DIST_TABLE.
%
%  Discussion:
%
%    Get the XY coordinates of a set of cities, and compute
%    the city-to-city distance table.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 September 009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string PREFIX, the common file prefix.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST01'
  fprintf ( 1, '  POINT_TO_DIST_TABLE computes a distance table from a'
  fprintf ( 1, '  list of point locations.'

  main_filename = sprintf ( '%s_main.txt', prefix );
  point_filename = sprintf ( '%s_points.txt', prefix );
  dist_table_filename = sprintf ( '%s_dist_table.txt', prefix );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The main filename is "%s".\n', main_filename );
  fprintf ( 1, '  The point filename is "%s".\n', point_filename );
  fprintf ( 1, '  The distance table filename will be "%s".\n', dist_table_filename );

  [ dim_num, point_num ] = r8mat_header_read ( point_filename );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The spatial dimension is ', dim_num
  fprintf ( 1, '  The number of points is  ', point_num

  point = r8mat_data_read ( point_file, dim_num, point_num );

  r8mat_transpose_print ( dim_num, point_num, point, '  The points:' );

  dist_table = point_to_dist_table ( dim_num, point_num, point );

  dist_table(1:n,1:n) = round ( dist_table(1:n,1:n) );

  r8mat_print_some ( point_num, point_num, dist_table, 1, 1, 5, 5, ...
    '  Initial 5x5 distance subtable:' );

  r8mat_write ( dist_table_filename, point_num, point_num, dist_table );

  return
end


clear all; close all; clc;

DATADIR = 'WHERE\IS\DATA';
SAVEDIR = 'WHERE\TO\SAVE';
%% SSVEP
SSVEPDATA = 'EEG_SSVEP.mat';
STRUCTINFO = {'EEG_SSVEP_train', 'EEG_SSVEP_test'};
SESSIONS = {'session1', 'session2'};
TOTAL_SUBJECTS = 54;
%% INITIALIZATION
FS = 100;
FREQBAND = [.5 40];
SEGTIME = [0 4000];

params = {
    'Channels', {'Oz'};
    'Class', {'up'; 'left'; 'right'; 'down'};
    'FFTPlot', 'on';
    };
%%
dataLength = (TOTAL_SUBJECTS * 2 * length(STRUCTINFO));
conSMT = cell(1, dataLength);
idx = 1;
%%
fprintf('Visualization tutorial\n')
for sessNum = 1:length(SESSIONS)
    session = SESSIONS{sessNum};
    for subNum = 1:TOTAL_SUBJECTS
        subject = sprintf('s%d',subNum);
        data = importdata(fullfile(DATADIR,session,subject,SSVEPDATA));
        for info = 1:length(STRUCTINFO)
            CNT = data.(STRUCTINFO{info});
            CNT = rmfield(CNT, 'smt');
            CNT = prep_resample(CNT, FS, {'Nr', 0});
            CNT = prep_filter(CNT, {'frequency', FREQBAND});
            SMT = prep_segmentation(CNT, {'interval', SEGTIME});
            SMT = prep_average(SMT);

            conSMT{idx} = SMT;

            fprintf('%06.2f%%...', idx/dataLength*100);
            if mod(idx, 20) == 0
                fprintf('\n');
            end
            idx = idx + 1;
        end
    end
end
fprintf('\n');

avSMT = grandAverage_prototye(conSMT);

vis_plotController(avSMT, [], params);
mkdir(SAVEDIR);
saveas(gcf, fullfile(SAVEDIR, 'SSVEP_GA'), 'fig');


%=========================================================================
% Sparse Representation-based Classification for Fusion (SRCF) , v1.0
%
% M. Nejati, S. Samavi, S. Shirani, "Multi-focus Image Fusion Using
% Dictionary-Based Sparse Representation", Information Fusion, vol. 25,
% Sept. 2015, pp. 72-84.
%
% Please refer to the above paper if you use this software.
%=========================================================================
clc,clear all,close all;
addpath('Utils','Utils\ompbox10','Utils\Metrics','Utils\GCO\bin','Utils\GCO\');

%====< Test Dataset >====%
dataPath = 'Data\GrayscaleDataset';
% dataPath = 'Data\LytroDataset';
[dataset,Dict] = loadData(dataPath);

%====< Fusion of Mutifocus Image Pairs >====%
res = struct([]);
for i = 1:dataset.numImage

    fprintf('>> start of fusion for image (%d)...\n',i);

    %----< load source image pairs >----%
    imgA0 = imread(fullfile(dataset.dataPath, dataset.imagesA{i}));
    imgB0 = imread(fullfile(dataset.dataPath, dataset.imagesB{i}));
    if strcmp(dataset.imgSet,'Grayscale')
    if (size(imgA0,3)>1), imgA0 = rgb2gray(imgA0); end
    if (size(imgB0,3)>1), imgB0 = rgb2gray(imgB0); end
    end

    %---< Fusion >---%
    imgF0 = SRCF(imgA0, imgB0, Dict);

    if (size(imgA0,3)>1), imgA = rgb2gray(imgA0); else imgA = imgA0; end
    if (size(imgB0,3)>1), imgB = rgb2gray(imgB0); else imgB = imgB0; end
    if (size(imgF0,3)>1), imgF = rgb2gray(imgF0); else imgF = imgF0; end

    %=======================
    % Objective Evaluation
    %=======================
    MI = fusionMI(imgA,imgB,imgF); % no matter double or uint8
    NMI = fusionECC(imgA,imgB,imgF); % no matter double or uint8
    QABF = Qabf_eval(imgA,imgB,imgF); % no matter double or uint8
    VIFF = VIFF_Public(imgA,imgB,imgF); % no matter double or uint8
    fprintf('-------------------------------------------------------\n')
    fprintf(' %s: QABF = %.4f , VIFF = %.4f , NMI = %.4f\n',dataset.imagesA{i}(1:end-4),QABF,VIFF,NMI);
    fprintf('-------------------------------------------------------\n')
    res(i).MI = MI;
    res(i).NMI = NMI;
    res(i).QABF = QABF;
    res(i).VIFF = VIFF;

    %---< Display >---%
%     figure,imshow(imgA0,[]),title('Source Image 1')
%     figure,imshow(imgB0,[]),title('Source Image 2')
    figure,imshow(imgF0,[]),title('Fused Image')
    pause(2);
    close all;

end


function [obj, objGrad] = pathObjective(u)
% [obj, objGrad] = pathObjective(u)
%
% Computes the objective function (and gradients) for the simple pendulum
%

obj = u.^2;

if nargout == 2  % Analytic gradients
    nTime = length(u);

    objGrad = zeros(4,nTime); %4 = [time + angle + rate + torque];

    objGrad(4,:) = 2*u;  %gradient obj wrt u

end

end


function [faces,idx,facemap]=uniqfaces(elem)
%
% [faces,idx,facemap]=uniqfaces(elem)
%
% return the unique face list from a or tetrahedral mesh
%
% author: Qianqian Fang, <q.fang at neu.edu>
%
% input:
%     elem: a list of elements, each row is a list of nodes for an element.
%           elem can have 2, 3 or 4 columns
%
% output:
%     face: unique faces in the mesh, denoted by a triplet of node indices
%     idx:  index of the output in the raw face list (returned by meshface)
%     facemap: index of the raw faces in the output list (for triangular mesh)
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

if(size(elem)==3)
   faces=elem;
elseif(size(elem)>=4)
   faces=meshface(elem);
else
   error('invalid input');
end

[ufaces,idx,jdx]=unique(sort(faces,2),'rows');
faces=faces(idx,:);
if(nargout>2)
    facemap=reshape(jdx,[size(elem,1) nchoosek(size(elem,2),3)]);
end


function varargout = transpose(varargin)
%.'   DISKFUN transpose.
%   F.' is the non-conjugate transpose of the underlying quasimatrix for
%   the DISKFUN object F. Given F in polar coordinates, F(theta, r),
%   F.' = F(r, theta). To transpose a DISKFUN with respect to Cartesian
%   coordinates, use the command FLIPXY.
%
% See also DISKFUN/CTRANSPOSE and DISKFUN/FLIPXY.

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

[varargout{1:nargout}] = transpose@separableApprox(varargin{:});

end


function prior = logisticNormalPriorParamInit(prior)

% LOGISTICNORMALPRIORPARAMINIT Logistic-normal prior model's parameter initialisation.
% FORMAT
% DESC initialises the parameters of the 4 parameter logistic-normal
% prior with some default parameters.
% ARG prior : prior structure to be initialised.
% RETURN prior : prior structure with initial values in place.
%
% Reference: Johnson, Systems of Frequency Curves Generated by
% Methods of Translation, Biometrika 36(1/2):149-176, 1949.
%
% SEEALSO : priorCreate
%
% COPYRIGHT : Antti Honkela, 2011

% PRIOR

prior.mu = 0;
prior.sd = sqrt(2);
prior.a = 0;
prior.b = 1;

prior.transforms.index = [2];
prior.transforms.type = optimiDefaultConstraint('positive');
prior.nParams = 2;
prior.isBounded = 1;


function lambda = symm_random_eigenvalues ( n, d, key )

%*****************************************************************************80
%
%% SYMM_RANDOM_EIGENVALUES returns the eigenvalues of the SYMM_RANDOM matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 March 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Input, real D(N), the desired eigenvalues for the matrix.
%
%    Input, integer KEY, a positive integer that selects the data.
%
%    Output, real LAMBDA(N), the eigenvalues.
%
  d = d(:);

  lambda = d;

  return
end


function [ cum_ret, cumprod_ret, daily_ret, daily_portfolio] = template( fid, data, varargins, opts )
% This is a template for writing a portfolio selection algorithm
%
% [ cum_ret, cumprod_ret, daily_ret, daily_portfolio] = template( fid, data, varargins, opts )
%
% Please put the description of your algorithm here
% Name of Strategy:
% Author:
% Description:
% The sections labelled as "Static" of the file need not be changed

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of OLPS: http://OLPS.stevenhoi.org/
% Original authors:
% Contributors:
% Change log:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %% Make changes to this section to construct your algorithm

    %% Read Parameters
    p1 = varargins{1};

    %% Initialize variables
    [r c] = size(data);
    b = ones(c,1)/c;
    returns = zeros(r,1);
    portfolio = ones(r,c)/c;

    %% Static
    progress = waitbar(0,'Executing Algorithm...');

    %% The looping over the entire dataset for backtesting
    % The algorithm looping over r time periods
    for t = 1:1:r

        %% Static
        % compute x ofthe optimization problem i.e. todaysRelative
        todaysRelative = data(t,:)';
        % Compute the returns of algorithm
        portfolio(t, :) = b;
        returns(t) = b'*(todaysRelative-1);

        %% Change this section to describe your strategy portfolio selection method

        % Use solver/algorithm to find new portfolio vector at end of time
        % period t

        %%  Static
        % Update Progress
        if mod(t, 50) == 0
            waitbar((t/r));
        end

    end

    %% Static

    % Compute additional statistics (for quick individual run without GUI)
    % Can be deleted
    stats.finalValue = prod(returns+1);
    Y =r/252;
    stats.sharpe = ((stats.finalValue)^(1/Y) - 1.04)  / (std(returns)*sqrt(252));
    stats.averageInTopStock = mean(max(portfolio') );
    stats.averageInTop2Stocks = flipud(sort(portfolio'));
    stats.averageInTop2Stocks = mean(sum(stats.averageInTop2Stocks(1:2, :)));
    stats.variance = (std(returns)*sqrt(252));

    % Conversion of results to algorithm format
    % cum_ret, cumprod_ret, daily_ret, daily_portfolio
    daily_portfolio = portfolio;
    daily_ret = returns+ 1;
    cumprod_ret = cumprod(daily_ret);
    cum_ret = cumprod_ret(end);

    close(progress);
end


% pop_expica() - export ICA weights or inverse matrix
%
% Usage:
%   >> pop_expica( EEG, whichica);             % a window pops up
%   >> pop_expica( EEG, whichica, filename );
%
% Inputs:
%   EEG         - EEGLAB dataset
%   whichica    - ['weights'|'inv'] export ica 'weights' or ica inverse
%                 matrix ('inv'). Note: for 'weights', the function
%                 export the product of the sphere and weights matrix.
%   filename    - text file name
%
% Author: Arnaud Delorme, CNL / Salk Institute, Mai 14, 2003
%
% See also: pop_export()

% Copyright (C) Mai 14, 2003, Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function com = pop_expica(EEG, whichica, filename);

com = '';
if nargin < 1
    help pop_expica;
    return;
end;

if nargin < 2
    whichica = 'weights';
end;
switch lower(whichica)
 case {'weights' 'inv'}, ;
 otherwise error('Unrecognized option for ''whichica'' parameter');
end;

if nargin < 3
	% ask user
	[filename, filepath] = uiputfile('*.*', [ 'File name for ' ...
                        fastif(strcmpi(whichica, 'inv'), 'inverse', 'weight') ' matrix -- pop_expica()']);
    drawnow;
	if filename == 0 return; end;
	filename = [filepath filename];
end;

% save datas
% ----------
if strcmpi(whichica, 'inv')
    tmpmat = double(EEG.icawinv);
else
    tmpmat = double(EEG.icaweights*EEG.icasphere);
end;
save(filename, '-ascii', 'tmpmat');

com = sprintf('pop_expica(%s, ''%s'', ''%s'');', inputname(1), whichica, filename);

return;


function [y, pst] = tapas_ceode_gen_erp(P, M, U)
% [y, pst] = tapas_ceode_gen_erp(P, M, U)
%
% Compute predicted data based on a specified DCM, with variable integrator
% specification.
%
% Adapted from spm_gen_erp.m (original function lincense below).
%
%
% INPUT
%   P           struct          parameter structure
%   M           struct          model specification
%   U           struct          design specification
%
% OUTPUT
%   y           mat             Integrated activity in sensor space
%
% -------------------------------------------------------------------------
%
% Author: Dario Schöbi
% Created: 2020-08-10
% Copyright (C) 2020 TNU, Institute for Biomedical Engineering, University of Zurich and ETH Zurich.
%
% This file is part of the TAPAS ceode Toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------
%
% ORIGINAL FUNCTION LICENSE
%
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
%
% Karl Friston
% $Id: spm_gen_erp.m 5758 2013-11-20 21:04:01Z karl $
%--------------------------------------------------------------------------

% default inputs - one trial (no between-trial effects)
%--------------------------------------------------------------------------
if nargin < 3, U.X = sparse(1,0); end

% peristimulus time
%--------------------------------------------------------------------------
if nargout > 1
    pst = (1:M.ns)*U.dt - M.ons/1000;
end

% within-trial (exogenous) inputs
%==========================================================================
if ~isfield(U,'u')

    % peri-stimulus time inputs
    %----------------------------------------------------------------------
    U.u = feval(M.fu,(1:M.ns)*U.dt,P,M);

end

if isfield(M,'u')

    % remove M.u to preclude endogenous input
    %----------------------------------------------------------------------
    M = rmfield(M,'u');

end

% between-trial (experimental) inputs
%==========================================================================
if isfield(U,'X')
    X = U.X;
else
    X = sparse(1,0);
end

if ~size(X,1)
    X = sparse(1,0);
end

% cycle over trials
%==========================================================================
y      = cell(size(X,1),1);
for  c = 1:size(X,1)

    % condition-specific parameters
    %----------------------------------------------------------------------
    Q = spm_gen_Q(P, X(c, :));

    % solve for steady-state - for each condition
    %----------------------------------------------------------------------
    M.x  = spm_dcm_neural_x(Q,M);

    % integrate DCM - for this condition
    %----------------------------------------------------------------------
    y{c} = feval(M.int, Q, M, U);

end


% This script estimates the vowel space ratio of a speaker with respect to
% his/her reference population.
%
%
% Description
% Based on the tracked formants F1 and F2 for the voiced regions of speech
% we compute the vowel space for each recorded subject individually [1].
% We define the vowel space as the frequency region covered by the triangle
% in the two dimensional frequency space spanned by F1 and F2 for the vowels
% /i/ (as in heed), /a/ (as in hod), and /u/ (as in who'd) following [2].
% These three vowels represent the vowels with the most extreme positions
% of the tongue and are therefore located in the extremes of this triangularly
% shaped two-dimensional frequency space [3]. The method is developed
% following the recommendations in [4]. Reference frequencies of american
% english vowels are found in [5].
%
%
% [ratio, centroids] = getVowelSpace(formant_data, gender, mode, scaling, plot_formants)
%
% Inputs
%  formant_dat      : [samples] [Nx2] input formant observations F1 and F2
%  gender           : [nominal] [1x1] female = 0; male = 1; child = 2
%  mode             : [code]    [string] 'triangle' (default); 'polygon'
%                               (add /ae/ (as in had) to the vowel space)
%  scaling          : [boolean] [1x1] bark scaling on/off (default);
%                               mel_scaling optional in code.
%  plot_formants    : [boolean] [1x1] visualize vowel space on/off
%                               (default)
%
% Outputs
%  ratio            : [1x1] vowel space ratio
%  centroids        : [1x12] vector containing prototype vowel locations
%
% References
% [1] Scherer, S., Morency, L.-P., Gratch, J., and Pestian, J., EDUCED VOWEL SPACE
% IS A ROBUST INDICATOR OF PSYCHOLOGICAL DISTRESS: A CROSS-CORPUS ANALYSIS,
% Proceedings of ICASSP 2015.
% [2] H.-M. Liu, F.-M. Tsao, and P. K. Kuhl, ?The effect of reduced vowel
% working space on speech intelligibility in mandarin-speaking young
% adults with cerebral palsy,? Journal of the Acoustical Society of America,
% vol. 117, no. 6, pp. 3879?3889, 2005.
% [3] B. Lindblom, ?Explaining phonetic variation: A sketch of the h&h
% theory,? Speech Production and Speech Modeling, pp. 403?439, 1990.
% [4] S. Sandoval, V. Berisha, R. L. Utianski, J. M. Liss, and A. Spanias,
% ?Automatic assessment of vowel space area,? Journal of the Acoustical
% Society of America, vol. 134, no. 5, pp. 477?483, 2013.
% [5] J. Hillenbrand, L. A. Getty, M. J. Clark, and K. Wheeler, ?Acoustic
% characteristics of american english vowels,? Journal of the Acoustical
% Society of America, vol. 97, no. 5, pp. 3099?3111, 1995.
%
% Copyright (c) 2014 University of Southern California, Institute for
% Creative Technologies
%
% License
%  This file is under the LGPL license,  you can
%  redistribute it and/or modify it under the terms of the GNU Lesser General
%  Public License as published by the Free Software Foundation, either version 3
%  of the License, or (at your option) any later version. This file is
%  distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
%  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
%  PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
%  details.
%
% 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.
%
% This function is part of the Covarep project: http://covarep.github.io/covarep
%
% Author
%  Stefan Scherer scherer@ict.usc.edu
%
function [ratio, centroids] = getVowelSpace(formant_data, gender, mode, scaling, plot_formants)

%% initialization
mel_scaling = @(x)(2595.*log10(ones(size(x))+x./700));
bark_scaling = @(x)(13.*atan(0.00076.*x)+3.5.*atan((x./7500).^2));
min_observations = 1000;

switch nargin
    case 1
        gender = 1;
        warning('getVowelSpace.m : no gender specified. assumes male gender.');
        plot_formants = 0;
        scaling = false;
        mode = 'triangle';
    case 2
        if(~ismember(gender, [0,1,2]))
            error('getVowelSpace.m : wrong use of gender variable; permitted values: 1 .. male; 0 .. female; 2 .. child');
        end
        plot_formants = 0;
        scaling = false;
        mode = 'triangle';
    case 3
        if(~ismember(gender, [0,1,2]))
            error('getVowelSpace.m : wrong use of gender variable; permitted values: 1 .. male; 0 .. female; 2 .. child');
        end
        if(~ismember(mode, {'triangle','polygon'}))
            error('getVowelSpace.m : wrong use of gender variable; permitted values: 1 .. male; 0 .. female; 2 .. child');
        end
        scaling = false;
        plot_formants = 0;
    case 4
        if(~ismember(gender, [0,1,2]))
            error('getVowelSpace.m : wrong use of gender variable; permitted values: 1 .. male; 0 .. female; 2 .. child');
        end
        plot_formants = 0;
    case 5
        if(~ismember(gender, [0,1,2]))
            error('getVowelSpace.m : wrong use of gender variable; permitted values: 1 .. male; 0 .. female; 2 .. child');
        end
    otherwise
        error('getVowelSpace.m : wrong use of getVowelSpace.');
end

if(size(formant_data,2) < 2)
    error('getVowelSpace.m : wrong use of getVowelSpace. you must provide at least the first two formants!');
end

%% Formants for vowels
% list of formants; based on [4]
% this list is quite flexible.. you can adjust that to your dialect/language if you like!
men_f1 = [342, 427, 476, 580, 588, 768, 652, 497, 469, 378, 623, 474];
men_f2 = [2322, 2034, 2089, 1799, 1952, 1333, 997, 910, 1122, 997, 1200, 1379];

fem_f1 = [437, 483, 536, 731, 669, 936, 781, 555, 519, 459, 753, 523];
fem_f2 = [2761, 2365, 2530, 2058, 2349, 1551, 1136, 1035, 1225, 1105, 1426, 1588];

child_f1 = [452, 511, 564, 749, 717, 1002, 803, 597, 568, 494, 794, 586];
child_f2 = [3081, 2552, 2656, 2267, 2501, 1688, 1210, 1137, 1490, 1345, 1546, 1719];

if strcmp(mode, 'polygon')
    target_vowels = [1, 5, 6, 10];
else
    target_vowels = [1, 6, 10];
end

%% initialize data for processing
if(gender == 1)
    init_formants = [men_f1; men_f2]';
    formant_data = formant_data(formant_data(:,1) < 900 & formant_data(:,2) > 800 & formant_data(:,1) > 250 & formant_data(:,2) < 2450, :); % remove some outliers of formants
elseif(gender == 0)
    init_formants = [fem_f1; fem_f2]';
    formant_data = formant_data(formant_data(:,1) < 1000 & formant_data(:,2) > 1000 & formant_data(:,1) > 350 & formant_data(:,2) < 2800, :); % remove some outliers of formants
elseif(gender == 2)
    init_formants = [child_f1; child_f2]';
    formant_data = formant_data(formant_data(:,1) < 1000 & formant_data(:,2) > 1000 & formant_data(:,1) > 350 & formant_data(:,2) < 2800, :); % remove some outliers of formants
end

if(size(formant_data,1) < min_observations)
    warning('getVowelSpace.m : More formant observations are required for this method to work robustly.');
    ratio = 0;
    centroids = [];
    return
end

%% bark scaling
if scaling
    formant_data = bark_scaling(formant_data);
    init_formants = bark_scaling(init_formants);
    % optional:
    % formant_data = mel_scaling(formant_data);
    % init_formants = mel_scaling(init_formants);
end

%% vector quantization
warning off;
[~,centroids] = kmeans(formant_data(:,1:2),[],'start',init_formants, 'emptyaction', 'singleton');
warning on;

%% temp data for clustering
% distance measure can be changed!
pairwise_distances = pdist2(init_formants, centroids, 'seuclidean');
[~, idx] = min(pairwise_distances(target_vowels, :), [], 2);

%% triangle ratio
convHullPoints=centroids(idx,:);
vowelSpacePoints = init_formants(target_vowels,:);
[convOrder , cur_space] = convhull(convHullPoints);
[spaceOrder , vowel_space] = convhull(vowelSpacePoints);
ratio = cur_space./vowel_space;

%% plot vowel space
if(plot_formants)
    figure
    scatter(formant_data(:,1),formant_data(:,2), '.', 'LineWidth', 0.05);
    hold on;
    plot(centroids(:,1), centroids(:,2), 'ro')
    plot(centroids(idx,1), centroids(idx,2), 'go')
    xlabel('Formant 1');
    ylabel('Formant 2');
    plot(init_formants(:,1), init_formants(:,2), 'kx')
    plot(init_formants(target_vowels,1), init_formants(target_vowels,2), 'mx')
    plot(convHullPoints(convOrder,1),convHullPoints(convOrder,2),'g-')
    plot(vowelSpacePoints(spaceOrder,1),vowelSpacePoints(spaceOrder,2),'m-')
    set(gca,'XDir','reverse');
    set(gca,'YDir','reverse');
    set(gca,'XAxisLocation','top','YAxisLocation','right');
    title(sprintf('vowel space ratio %2.3f (#obs = %d)', ratio, size(formant_data, 1)));
    drawnow;
    hold off;
end


classdef RegularizedPerimeterComputer < handle

    properties (Access = public)
        perimeters
        perimetersGradient
        regularizedDensity
        perimeterShapeFunctions
        epsilons
    end

    properties (Access = private)
        inputFile
        backgroundMesh
        designVariable
        scale
        nEpsilon
        epsilon
        printing
        plotting
        capturingImage
        perimeterShapeFunction
        outputFigureName
        perimeterType
        isRobinTermAdded
    end

    methods (Access = public)

        function obj = RegularizedPerimeterComputer(cParams)
            obj.init(cParams);
        end

        function compute(obj)
            obj.createEpsilonValues();
            obj.computePerimeters();
        end

    end

    methods (Access = private)

        function init(obj,cParams)
            obj.inputFile        = cParams.inputFile;
            obj.backgroundMesh   = cParams.backgroundMesh;
            obj.scale            = cParams.scale;
            obj.designVariable   = cParams.designVariable;
            obj.outputFigureName = cParams.outputFigureName;
            obj.plotting         = cParams.plotting;
            obj.printing         = cParams.printing;
            obj.capturingImage   = cParams.capturingImage;
            obj.perimeterType    = cParams.perimeterType;
            obj.isRobinTermAdded = cParams.isRobinTermAdded;
        end

        function createEpsilonValues(obj)
            epsmin = obj.backgroundMesh.computeMeanCellSize;
            epsmax = obj.backgroundMesh.computeCharacteristicLength();
            obj.nEpsilon = min(6,ceil(log2(epsmax/epsmin)));
            obj.epsilons = epsmin*(2.^((1:obj.nEpsilon) - 1));
        end

        function computePerimeters(obj)
            obj.perimeters = zeros(obj.nEpsilon,1);
            for iepsilon = 1:obj.nEpsilon
                obj.epsilon = obj.epsilons(iepsilon);
                obj.computeRegularizedPerimeter(iepsilon);
                obj.plotDensity();
                obj.printDensity(iepsilon);
                obj.captureImage(iepsilon);
            end
        end

        function computeRegularizedPerimeter(obj,iepsilon)
            obj.createPerimeterShapeFunction();
            obj.perimeterShapeFunction.computeFunctionAndGradient();
            per    = obj.perimeterShapeFunction.value;
            dPer   = obj.perimeterShapeFunction.gradient;
            rhoReg = obj.perimeterShapeFunction.regularizedDensity;
            obj.perimeters(iepsilon) = per*obj.perimeterShapeFunction.value0;
            obj.perimetersGradient(:,iepsilon) = dPer;
            obj.regularizedDensity(:,iepsilon) = rhoReg;
            obj.perimeterShapeFunctions{iepsilon} = obj.perimeterShapeFunction;
        end

        function createPerimeterShapeFunction(obj)
            s = obj.createPerimeterParams();
            shFunc = ShFunc_Perimeter(s);
            obj.perimeterShapeFunction = shFunc;
        end

        function s = createPerimeterParams(obj)
            sC.inputFile        = obj.inputFile;
            sC.mesh             = obj.backgroundMesh;
          %  sC.designVariable.value      = obj.designVariable;
          %  sC.designVariable.nVariables = 1;
            sC.designVariable   = obj.createDesignVariable();
            sC.epsilon          = obj.epsilon;
            sC.scale            = obj.scale;
            sC.type             = obj.perimeterType;
            sC.isRobinTermAdded = obj.isRobinTermAdded;
            fCreator = PerimeterParamsCreator(sC);
            s = fCreator.perimeterParams;
        end

        function dV = createDesignVariable(obj)
          %  s.scalarProductSettings.femSettings = [];
          %  s.epsilon = [];
          %  ss.type = 'full';
          %  sLs = SettingsLevelSetCreator;
          %  s = sLs.create(ss);
            s.mesh      = obj.backgroundMesh;
            s.inputFile = obj.inputFile;
            s.scale     = obj.scale;
            s.type      = 'LevelSet';
            d = DesignVariableCreatorSettings(s);
            s = d.create();
            dV = DesignVariable.create(s);
            dV.update(obj.designVariable);
        end

        function plotDensity(obj)
            s.mesh      = obj.backgroundMesh;
            s.inputFile = obj.inputFile;
            s.scale     = obj.scale;
            s.density   = obj.perimeterShapeFunction.regularizedDensity;
            plotter = DensityPlotterForPerimeter(s);
            if obj.plotting
                plotter.plot();
            end
        end

        function printDensity(obj,iepsilon)
            s.inputFile = obj.inputFile;
            s.iter      = iepsilon;
            s.mesh      = obj.backgroundMesh;
            s.perimeter   = obj.perimeterShapeFunction;
            printer = DensityPrinterForPerimeter(s);
            printer.print();
        end

        function captureImage(obj,iepsilon)
            if obj.capturingImage
                i = iepsilon;
                f = obj.inputFile;
                outPutNameWithIter = [obj.outputFigureName,'Epsilon',num2str(i)];
                inputFileName = fullfile('Output',f,[f,num2str(i),'.flavia.res']);
                s.fileName = f;
                s.outPutImageName = outPutNameWithIter;
                s.inputFileName = inputFileName;
                imageCapturer = GiDImageCapturer(s);
                imageCapturer.capture();
            end
        end

    end

end


function [g1L, g2L, g3L, g4L] = sdlfmvXsdlfmKernGradientICBlock(lfmKern1, ...
    lfmKern2, tInit1, tInit2, kyy, kyv, kvy, kvv, i, j, generalConst, ...
    generalConstGrad, gkyy1, gkyy2, gkyy3, gkyy4, gkyv1, gkyv2, ...
    gkyv3, gkyv4, gkvy1, gkvy2, gkvy3, gkvy4, gkvv1, gkvv2, gkvv3, gkvv4)

% SDLFMVXSDLFMKERNGRADIENTICBLOCK Partial derivatives initial conditions
%
% COPYRIGHT : Mauricio A. Alvarez, 2010

% KERN

g1L = cell(2);
g2L = cell(2);
g3L = cell(2);
g4L = cell(2);

typeParam = {'sdlfmv', 'sdlfm'};

% Compute for tInit1(1) and tInit2(2)

[g1L{1,2}, g2L{1,2}, g3L{1,2}] = sdlfmvXsdlfmKernGradientBlock(lfmKern1, lfmKern2, tInit1(1), ...
    tInit2(2), kyy, kyv, kvy, kvv, i, j, generalConst, generalConstGrad, 1);

g1Plus = sdlfmaXsdlfmKernComputeBlock(lfmKern1, lfmKern2, tInit1(1), ...
    tInit2(2), kyy, kyv, kvy, kvv, i, j, generalConst);

g2Plus = sdlfmvXsdlfmvKernComputeBlock(lfmKern1, lfmKern2, tInit1(1), ...
    tInit2(2), kyy, kyv, kvy, kvv, i, j, generalConst);

if (i==1 && j==1) || (i==1) && (j~=1)

    if i~=1 || j~=1
        [gkyy1IC, gkyy2IC, gkyy3IC, gkyy4IC] = sdlfmXsdlfmKernGradientIC(lfmKern1, lfmKern2, ...
            tInit1(1), tInit2(2), gkyy1{i,j}, gkyy2{i,j}, gkyy3{i,j}, gkyy4{i,j}, gkyv1{i,j}, gkyv2{i,j}, ...
            gkyv3{i,j}, gkyv4{i,j}, gkvy1{i,j}, gkvy2{i,j}, gkvy3{i,j}, gkvy4{i,j}, gkvv1{i,j}, gkvv2{i,j}, ...
            gkvv3{i,j}, gkvv4{i,j}, 1, typeParam);
        for k=1:3
            g1L{1,2}{k} = g1L{1,2}{k} + gkyy1IC{k};
            g2L{1,2}{k} = g2L{1,2}{k} + gkyy2IC{k};
        end
        cLength = length(gkyy3IC);
        g3L{1,2}(1:cLength) = g3L{1,2}(1:cLength) + gkyy3IC;
        g3L{1,2}(i)   = g3L{1,2}(i) + g1Plus;
        g3L{1,2}(j+1) = g2Plus;
        g4L{1,2} = gkyy4IC;
    else
        g3L{1,2}(i)   = g3L{1,2}(i) + g1Plus;
        g3L{1,2}(j+1) = g2Plus;
        g4L{1,2} = sdlfmKernMeanCovPartial(lfmKern1(1), lfmKern2(1), tInit1(1), ...
            tInit2(2), 1, typeParam);
    end
end

% Compute for tInit1(2) and tInit2(1)

[g1L{2,1}, g2L{2,1}, g3L{2,1}] = sdlfmvXsdlfmKernGradientBlock(lfmKern1, lfmKern2, tInit1(2), ...
    tInit2(1), kyy, kyv, kvy, kvv, i, j, generalConst, generalConstGrad, 1);

g1Plus = sdlfmaXsdlfmKernComputeBlock(lfmKern1, lfmKern2, tInit1(2), ...
    tInit2(1), kyy, kyv, kvy, kvv, i, j, generalConst);

g2Plus = sdlfmvXsdlfmvKernComputeBlock(lfmKern1, lfmKern2, tInit1(2), ...
    tInit2(1), kyy, kyv, kvy, kvv, i, j, generalConst);

if (i==1 && j==1) || (i~=1) && (j==1)
    if i~=1 || j~=1
        [gkyy1IC, gkyy2IC, gkyy3IC, gkyy4IC] = sdlfmXsdlfmKernGradientIC(lfmKern1, lfmKern2, ...
            tInit1(2), tInit2(1), gkyy1{i,j}, gkyy2{i,j}, gkyy3{i,j}, gkyy4{i,j}, gkyv1{i,j}, gkyv2{i,j}, ...
            gkyv3{i,j}, gkyv4{i,j}, gkvy1{i,j}, gkvy2{i,j}, gkvy3{i,j}, gkvy4{i,j}, gkvv1{i,j}, gkvv2{i,j}, ...
            gkvv3{i,j}, gkvv4{i,j}, 1, typeParam);
        for k=1:3
            g1L{2,1}{k} = g1L{2,1}{k} + gkyy1IC{k};
            g2L{2,1}{k} = g2L{2,1}{k} + gkyy2IC{k};
        end
        cLength = length(gkyy3IC);
        g3L{2,1}(1:cLength) = g3L{2,1}(1:cLength) + gkyy3IC;
        g3L{2,1}(j)   =  g3L{2,1}(j) + g2Plus;
        g3L{2,1}(i+1) =  g1Plus;
        g4L{2,1} = gkyy4IC;
    else
        g3L{2,1}(j)   =  g3L{2,1}(j) + g2Plus;
        g3L{2,1}(i+1) =  g1Plus;
        g4L{2,1} = sdlfmKernMeanCovPartial(lfmKern1(1), lfmKern2(1), tInit1(2), ...
            tInit2(1), 1, typeParam);
    end
end

% Compute for tInit1(2) and tInit2(2)

[g1L{2,2}, g2L{2,2}, g3Local] = sdlfmvXsdlfmKernGradientBlock(lfmKern1, lfmKern2, tInit1(2), ...
    tInit2(2), kyy, kyv, kvy, kvv, i, j, generalConst, generalConstGrad, 1);

g1Plus = sdlfmaXsdlfmKernComputeBlock(lfmKern1, lfmKern2, tInit1(2), ...
    tInit2(2), kyy, kyv, kvy, kvv, i, j, generalConst);

g2Plus = sdlfmvXsdlfmvKernComputeBlock(lfmKern1, lfmKern2, tInit1(2), ...
    tInit2(2), kyy, kyv, kvy, kvv, i, j, generalConst);

if i~=1 || j~=1
    [gkyy1IC, gkyy2IC, gkyy3IC, gkyy4IC] = sdlfmXsdlfmKernGradientIC(lfmKern1, lfmKern2, ...
        tInit1(2), tInit2(2), gkyy1{i,j}, gkyy2{i,j}, gkyy3{i,j}, gkyy4{i,j}, gkyv1{i,j}, gkyv2{i,j}, ...
        gkyv3{i,j}, gkyv4{i,j}, gkvy1{i,j}, gkvy2{i,j}, gkvy3{i,j}, gkvy4{i,j}, gkvv1{i,j}, gkvv2{i,j}, ...
        gkvv3{i,j}, gkvv4{i,j}, 1, typeParam);
    if i>=2 && j>=2
        g1L{2,2}{1} = g1L{2,2}{1} + gkyy1IC{1};
        g2L{2,2}{1} = g2L{2,2}{1} + gkyy2IC{1};
        g1L{2,2}{2} = [gkyy1IC{2} g1L{2,2}{2}];
        g2L{2,2}{2} = [gkyy2IC{2} g2L{2,2}{2}];
        g1L{2,2}{3} = [gkyy1IC{3} g1L{2,2}{3}];
        g2L{2,2}{3} = [gkyy2IC{3} g2L{2,2}{3}];
    else
        for k=1:3
            g1L{2,2}{k} = g1L{2,2}{k} + gkyy1IC{k};
            g2L{2,2}{k} = g2L{2,2}{k} + gkyy2IC{k};
        end
    end
    cLength = length(g3Local);
    g3L{2,2} = zeros(1, cLength+1);
    g3L{2,2}(1:cLength) = g3L{2,2}(1:cLength) + g3Local;
    cLength = length(gkyy3IC);
    g3L{2,2}(1:cLength) = g3L{2,2}(1:cLength) + gkyy3IC;
    g3L{2,2}(i+1) = g3L{2,2}(i+1) + g1Plus;
    g3L{2,2}(j+1) = g3L{2,2}(j+1) + g2Plus;
    g4L{2,2} = gkyy4IC;
else
    g3L{2,2} = g3Local;
    g3L{2,2}(i+1) = g1Plus;
    g3L{2,2}(j+1) = g3L{2,2}(j+1) + g2Plus;
    g4L{2,2} = sdlfmKernMeanCovPartial(lfmKern1(1), lfmKern2(1), tInit1(2), ...
        tInit2(2), 1, typeParam);
end


function [Population,Groups,K] = spiltVariables(Problem,BU,BD,s)
% Decision variable grouping with RDG2 in SACCEAMII

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    %% Initialize
    D = length(BU);
    Groups     = zeros(1,D);
    Population = [];
    Separable  = [];
    NonSeparable = [];

    %% Recursive Decomposition Grouping Methods
    xLL  = BD;
    xNew = Problem.Evaluation(xLL);
    yLL  = xNew.objs;
    Population = [Population,xNew];
    X1   = 1;
    X2   = 2:D;
    % Process
    while ~isempty(X2)
        % Interaction detection
        [sub1,Population] = INTERACT(Problem,Population,X1,X2,xLL,yLL,BU,BD);
        if numel(sub1) == numel(X1) % isequal(sub1,X1)
            if numel(X1) == 1
                Separable = [Separable,X1];
            else
                NonSeparable = [NonSeparable,X1];
            end
			X1 = X2(1);
			X2 = X2(2:end);
        else
            X1 = sub1;
            X2 = X2(~ismember(X2,X1));
        end

        if isempty(X2)
            if numel(X1) > 1
                NonSeparable = [NonSeparable,X1];
            else
                Separable = [Separable,X1];
            end
        end
    end

    %% Split the separable decision varables
     if ~isempty(Separable)
         num = floor(numel(Separable)/s);
         if num <= 1
             K   = 1;
             Groups(Separable) = K;
         else
             K = num;
             idx = 1:1:numel(Separable);
             for i = 1 : num-1
                 select = randperm(numel(idx),s);
                 Groups(Separable(idx(select))) = i;
                 idx(select) = [];
             end
             Groups(Separable(idx)) = num;
         end
         if ~isempty(NonSeparable)
             K = K + 1;
             Groups(NonSeparable) = K;
         end
     else
         K = 1;
         Groups(NonSeparable) = K;
     end
end

function [X1,Population] = INTERACT(Problem,Population,X1,X2,xLL,yLL,BU,BD)
    % Determine gamma
    muM   = eps/2;
    gamma = @(n)(n.*muM)./(1-n.*muM);

    xUL     = xLL;
    xUL(X1) = BU(X1);

    % Calculate delta1
    tNew       = Problem.Evaluation(xUL);
    delta1     = yLL - tNew.objs;
    Population = [Population,tNew];

    % Calculate delta2
    xLM     = xLL;
    xLM(X2) = (BU(X2)+BD(X2))/2;
    xUM     = xUL;
    xUM(X2) = (BU(X2)+BD(X2))/2;
    tNew1   = Problem.Evaluation(xLM);
    tNew2   = Problem.Evaluation(xUM);
    delta2  = tNew1.objs - tNew2.objs;
    Population = [Population,tNew1,tNew2];
    % Update
    F4 = [yLL,tNew.objs,tNew1.objs,tNew2.objs];
    threshold = gamma(numel(BU).^0.5+2)*sum(abs(F4));
    if abs(delta1-delta2) > threshold
        if numel(X2) == 1
            X1 = union(X1,X2);
        else
            % Divide X2 into equally-sized groups G1, G2
            mid = floor(length(X2)/2);
            G1  = X2(1:mid);
            G2  = X2(mid+1:end);
            [subX1,Population] = INTERACT(Problem,Population,X1,G1,xLL,yLL,BU,BD);
            [subX2,Population] = INTERACT(Problem,Population,X1,G2,xLL,yLL,BU,BD);
            X1  = union(subX1,subX2);
        end
    end
end


function [Jul1,Jul2]=Cal2UTC(year,month,day,hour,minute,second)
%%CAL2UTC Convert dates in terms of the Gregorian calendar in years,
%         months, days, hours, minutes and seconds with the time in
%         universal coordinated time (UTC) to a two-part pseudo-Julian
%         date in UTC.
%
%INPUTS: year A matrix of integer  years in the Gregorian calendar under
%             UTC time.
%       month A matrix of integer months in the Gregorian calendar under
%             UTC time. 1<=month<=12
%         day A matrix of integer days in the Gregorian calendar under UTC
%             time. Days count from 1.
%        hour A matrix of integer hours under the Gregorian calendar. UTC
%             time 0<=hour<=23
%      minute A matrix of integer minutes in the Gregorian calendar under
%             UTC time. 0<=minute<=59.
%      second A matrix of double floating point seconds in the Gregorian
%             calendar under UTC time. This is >=0 and normally less than
%             60, but can be a value less than 61 or 59 at the right hour
%             on a day with a leap second.
%
%Since the default format of numbers in Matlab is double-precision
%floating point numbers and one must go to lengths to use values that are
%differently formatted, it is assumed that all inputs, including the
%integer values, are double-precision floats.
%
%OUTPUTS: Jul1, Jul2 Matrices of the time as pseudo-Julian dates in UTC
%                    where each row/column corresponds to the values in
%                    the same row/column of the input matrices. Jul1
%                    corresponds to an integer number of days starting at
%                    midnight, which means that it ends in 0.5, since
%                    Julian days start at noon. Jul2 is the fraction of a
%                    day (midnight-to-midnight) after that.
%
%This is a mex wrapper for the function iauDtf2d in the International
%Astronomical Union's (IAU) Standard's of Fundamental Astronomy library.
%The UTC date is only pseudo-Julian, because there is not a fixed number
%of seconds in a Julian day. The convention used in the IAU standard is
%that the Julian day matches the UTC day regardless of whether the UTC day
%is 86399, 86400 or 86401 SI seconds (depending on the presence of leap
%seconds).
%
%The algorithm can be compiled for use in Matlab  using the
%CompileCLibraries function.
%
%The algorithm is run in Matlab using the command format
%[Jul1,Jul2]=Cal2UTC(year,month,day,hour,minute,second);
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

error('This function is only implemented as a mexed C or C++ function. Please run CompileCLibraries.m to compile the function for use.')

end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function [bdNode,bdFacet,isBdNode] = findpolyboundary(varargin)
%% FINDPOLYBOUNDARY finds the boundary facet(s) of a polytopal mesh (dim=2 or 3)
%  2D: facet is given as an NEx2 edge array.
%  3D: facet is given as an NFx4 face array.
%  allFacet contains all facets retrieved from elem{:} or elem
%  If the input is elem, elem has be a cell array
%  Current restriction: face has to be triangular or quadrilateral
%  when f-th face is triangular, the face(f,4) = 0.
%
%  Examples:
%
%  totalEdge = uint32([elem(:,[1 2]); elem(:,[2 3]); ...
%                    elem(:,[3 4]); elem(:,[4 1])]);
%  [bdNode,bdFacet,isBdNode] = findpolyboundary(allEdge)
%
%  allFace = [elem(:,[2, 3, 4]);elem(:,[1, 4,3]);elem(:,[1,2,4]);elem(:,[1,3,2])];
%  allFace(:,4) = 0;
%  [bdNode,bdFacet,isBdNode] = findpolyboundary(allFace)
%
%  the following example only works in 2D elem is a cell array:
%  elem = {[10,9,11,14,15];[15,14,16,17];[3,1,6,5];[5,6,7,12,11];...
%          [4,3,5,11,9];[2,4,9,10];[12,7,8,13];[14,11,12,13,16]};
%  node = [1 0; 0 0; 0.63591 0; 0.36409 0; 0.68734 0.31329;...
%          1  0.36233; 1 0.63767; 1 1; 0.31266 0.31329;...
%          0 0.36233; 0.49815 0.5; 0.68734 0.68671; 0.63591 1;...
%          0.31266 0.68671;  0 0.63767; 0.36409 1; 0 1];
%  [bdNode,bdFacet,isBdNode] = findpolyboundary(elem);
%  showmeshpoly(node,elem);
%  findnode(node,bdNode);
%
%  To-do: add bdFlag for more streamlined workflow

%%
if iscell(varargin{1})
    elem = varargin{1};
    elemVertexNumber = cellfun('length',elem);
    maxNv = max(elemVertexNumber);
    minNv = min(elemVertexNumber);
    allFacet = cell(maxNv,1);
    for Nv = minNv:maxNv
        idx = (elemVertexNumber == Nv);
        elemNv = cell2mat(elem(idx));
        NT = sum(idx);
        % # of edge = # of vertices in 2D
        locEdge = [1:Nv; circshift(1:Nv,-1)]';
        allFacet{Nv} = zeros(NT*Nv,2);
        for j = 1:Nv
           allFacet{Nv}((j-1)*NT+1:j*NT,:) = elemNv(:,locEdge(j,:));
        end
    end
    if isrow(allFacet); allFacet = allFacet'; end
    allFacet = cell2mat(allFacet);
elseif ismatrix(varargin{1})
    allFacet = varargin{1};
end

[NF, dim] = size(allFacet);
allFacet = sort(allFacet, 2);
[uface, i2, j] = myunique(allFacet); %#ok<*ASGLU>
i1(j(NF:-1:1)) = NF:-1:1;
i1 = i1';
bdFacet = allFacet(i1(i1 == i2), :);
switch dim
    case 2
        isBdNode(bdFacet(:)) = true;
    case 4
        isTriFace = bdFacet(:, 4) == 0;
        isBdNode(bdFacet(isTriFace,1:3)) = true;
        isBdNode(bdFacet(~isTriFace, :)) = true;
end

bdNode = find(isBdNode);


function msh = meshFV2msh(fv,mmPerVox,windowID, actor)
% Convert Matlab faces/vertices to vistasoft mesh
%
% Example:  See t_meshSimpleShapes, t_meshCurvature
%
% BW (c) VISTASOFT Team, Stanford, 2013

%% Check and initialize parameters
if notDefined('mmPerVox'), mmPerVox = [1 1 1]; end
if notDefined('windowID'), windowID = 1000; end
if notDefined('actor'), actor = 33; end

% Create a vista mesh structure
msh = meshCreate;
msh = meshSet(msh,'window id',windowID);
msh = meshSet(msh,'actor',actor);

%% Copy the Matlab vertices faces and vertices into msh
msh = meshSet(msh,'vertices',double(fv.vertices'));

%% Set the scene origin
vertices = meshGet(msh,'vertices');
msh = meshSet(msh,'origin',-mean(vertices,2)');

% Set the scale
msh = meshSet(msh,'mmPerVox',mmPerVox);

%% Triangles and normals

% Permute the triangle order, for some reason.  Otherwise we have apparent
% holes in the meshes - one side is transparent and the other side opaque.
% We haven't understood this yet.
msh = meshSet(msh,'triangles',double(fv.faces(:,[3 2 1])' - 1));

% Compute and set vertex normals
msh = meshSet(msh,'normals',patchnormals(fv)');

%% Calculate mean curvature

% try
%     % [Umin,Umax,Cmin,Cmax,Cmean,Cgauss,Normal]
%     % Cmax is no good
%     % Cmin is possible
%     % Cmean is good
%     % Cgauss is not so good
%     % n is useless
%     [~,~,~,~,Cmean,~,~] = compute_curvature(fv.vertices,fv.faces);
%     msh = meshSet(msh,'curvature',Cmean);
% catch err
% Different calculation, slower, but it seems to run.
fprintf('Using tricurv_v01\n');
curvatures = tricurv_v01(fv.faces,fv.vertices);
msh = meshSet(msh,'curvature',curvatures.km);
% end

%% Build  color values from curvature

% This should become a separate routine

% Negative curvature is brighter because we multiply by -1.
% We compress because we are mostly interested in the curvature near 0.
% s = 0.1;
% c = ((2*c > 0) - 1) * .25 * 128 + 127.5;  % Formula from meshColor

% If curvature is negative, make the color index bigger
curvatureSaturation = 0.1;
curvatureContrast = 0.45;
curvatureCutpoint = -0.15;
c = -1 * (msh.curvature(:)) ./ (abs(msh.curvature(:)) + curvatureSaturation);
c = (c > curvatureCutpoint) * curvatureContrast * 128 + 96;  % Formula from meshColor

% Place the color map in a 4xN
c = c*ones(1,3);
c(:,4) = 255;  % Make opaque (not working well)
c = round(c);
msh = meshSet(msh,'colors',c');

%% meshVisualize(msh)
end


%DIPIM Fixed mapping running any DIPimage command with one input image
%
%	B = DIPIM(A,COMMAND,PAR1,PAR2, ...)
%	B = A*DIPIM([],COMMAND,PAR1,PAR2, ...)
%	B = A*DIPIM(COMMAND,PAR1,PAR2, ...)
%
% INPUT
%   A        Dataset or datafiles with object images
%   COMMAND  String with name of a DIPimage command
%   PAR1     Additional parameters needed for COMMAND
%
% OUTPUT
%   B        Datasetor datafile with results
%
% DESCRIPTION
% This is a general routine to run DIPimage commands on the images stored
% in a dataset or datafile. It is thereby appropriate for grey value
% operations. For logical and morphological operations DIPBIN should be
% used. See DIPIMAGE for a list of all possible commands. A few suggections:
%     stretch              - Grey-value stretching
%     hist_equalize        - Histogram equalization
%     lut                  - Look-up Table (with interpolation)
%     convolve             - General convolution filter
%     gaussf               - Gaussian filter
%     unif                 - Uniform filter
%     maxf                 - Maximum filter
%     minf                 - Minimum filter
%     medif                - Median filter
%     percf                - Percentile filter
%     varif                - Variance filter
%     gabor                - Gabor filter
%     derivative           - Derivative filters
%     dx                   - First derivative in the X-direction
%     dy                   - First derivative in the Y-direction
%     dz                   - First derivative in the Z-direction
%     laplace              - Laplace operator
%     laplace_plus_dgg     - Laplace + Dgg
%     laplace_min_dgg      - Laplace - Dgg
%     hessian              - Hessian matrix of an image
%     prewittf             - Prewitt derivative filter
%     sobelf               - Sobel derivative filter
%     threshold            - Thresholding
%     hist2image           - Backmaps a 2D histogram ROI to the images
%     minima               - Detect local minima
%     maxima               - Detect local maxima
%     watershed            - Watershed
%
% SEE ALSO (PRTools Guide)
% DATASETS, DATAFILES, DIP_IMAGE, DIPBIN

% Copyright: R.P.W. Duin, r.p.w.duin@37steps.com
% Faculty EWI, Delft University of Technology
% P.O. Box 5031, 2600 GA Delft, The Netherlands

function b = dipim(varargin)

  checktoolbox('diplib');
	argin = shiftargin(varargin,'char');
  argin = setdefaults(argin,[],'');
  varargin = cell(1,numel(argin)-2);
  [a,command,varargin{:}] = deal(argin{:});
	if isempty(command)
    error('No DIPimage command supplied')
  end
  if mapping_task(argin,'definition')
    b = define_mapping(argin,'fixed');
    b = setname(b,'DIPimage');
  elseif isa(a,'prdataset') % allows datafiles too
		isobjim(a);
    b = filtim(a,mfilename,{command varargin{:}});
  elseif isa(a,'double') % here we have a single image
		a = dip_image(a);
    b = runcommand(command,a,varargin{:});
  elseif isa(a,'dip_image') % here we have a single DIP image
    b = runcommand(command,a,varargin{:});
  else
    error('Illegal call')
  end

 return

  function b = runcommand(command,a,varargin)

  try
    b = feval(command,a,varargin{:});
  catch ME
    if strcmp(ME.message, 'Argument # 1: image data type not supported')
      error('Wrong routine for this DIPimage command. Try DIPBIN.')
    end
    rethrow(ME);
  end

return


function t = subsasgn(t,s,rhs)
%SUBSASGN Subscripted assignment for sparse tensor.
%
%   We can assign elements to a sptensor in three ways.
%
%   Case 1: X(R1,R2,...,RN) = Y, in which case we replace the
%   rectangular subtensor (or single element) specified by the ranges
%   R1,...,RN with Y. The right-hand-side can be a scalar or an
%   sptensor.
%
%   Case 2: X(S) = V, where S is a p x n array of subscripts and V is
%   a scalar value or a vector containing p values.
%
%   Linear indexing is not supported for sparse tensors.
%
%   Examples
%   X = sptensor([30 40 20]) %<-- Create an emtpy 30 x 40 x 20 sptensor
%   X(30,40,20) = 7 %<-- Assign a single element to be 7
%   X([1,1,1;2,2,2]) = 1 %<-- Assign a list of elements to the same value
%   X(11:20,11:20,11:20) = sptenrand([10,10,10],10) %<-- subtensor!
%   X(31,41,21) = 7 %<-- grows the size of the tensor
%   X(111:120,111:120,111:120) = sptenrand([10,10,10],10) %<-- grows
%   X(1,1,1,1) = 4 %<-- increases the number of dimensions from 3 to 4
%
%   X = sptensor([30]) %<-- empty one-dimensional tensor
%   X([4:6]) = 1 %<-- set subtensor to ones (does not increase dimension)
%   X([10;12;14]) = (4:6)'  %<-- set three elements
%   X(31) = 7 %<-- grow the first dimension
%   X(1,1) = 0 %<-- add a dimension, but no nonzeros
%
%   Note regarding singleton dimensions: It is not possible to do, for
%   instance, X(1,1:10,1:10) = sptenrand([1 10 10],5). However, it is okay
%   to do X(1,1:10,1:10) = squeeze(sptenrand([1 10 10],5)).
%
%   See also SPTENSOR, TENSOR/SUBSASGN.
%
%MATLAB Tensor Toolbox.
%Copyright 2012, Sandia Corporation.

% This is the MATLAB Tensor Toolbox by T. Kolda, B. Bader, and others.
% http://www.sandia.gov/~tgkolda/TensorToolbox.
% Copyright (2012) Sandia Corporation. Under the terms of Contract
% DE-AC04-94AL85000, there is a non-exclusive license for use of this
% work by or on behalf of the U.S. Government. Export of this data may
% require a license from the United States Government.
% The full license terms can be found in the file LICENSE.txt

switch s.type

    case '.'
        error(['Cannot change field ', s.subs, ' directly.']);

    case '()'

        % Do nothing if both subscripts and RHS are empty
        if isempty(s.subs{1}) && isempty(t.vals)
            return;
        end

        % Figure out if we are doing a subtensor or a list of subscripts...
        type = tt_assignment_type(t,s.subs,rhs);

        %% Case I: Replace a sub-tensor
        if isequal(type,'subtensor')

            %% Case I(a): RHS is another sparse tensor
            if isa(rhs,'sptensor')

                %% First, Resize the tensor and check the size match with
                %% the tensor that's being inserted.
                m = 1;
                for n = 1:numel(s.subs)
                    if ischar(s.subs{n}) && (s.subs{n} == ':')
                        if ndims(t) < n
                            newsz(1,n) = rhs.size(m);
                        else
                            newsz(1,n) = max([t.size(n), rhs.size(m)]);
                        end
                        m = m + 1;
                    elseif numel(s.subs{n}) == 1
                        if ndims(t) < n
                            newsz(1,n) = s.subs{n};
                        else
                            newsz(1,n) = max([t.size(n) s.subs{n}]);
                        end
                    else
                        if numel(s.subs{n}) ~= rhs.size(m)
                            error('RHS does not match range size');
                        end
                        if ndims(t) < n
                            newsz(1,n) = max(s.subs{n});
                        else
                            newsz(1,n) = max([t.size(n) s.subs{n}]);
                        end
                        m = m + 1;
                    end
                end
                t.size = newsz;

                % Expand subs array if there are new modes, i.e., if the order
                % has increased.
                if ~isempty(t.subs) && (size(t.size,2) > size(t.subs,2))
                    t.subs(:,end+1:size(t.size,2)) = 1;
                end

                % Delete what currently occupies the specified range
                rmloc = subdims(s.subs,t);
                kploc = setdiff(1:nnz(t),rmloc);
                newsubs = t.subs(kploc,:);
                newvals = t.vals(kploc);

                % Renumber the subscripts
                addsubs = irenumber(rhs, t.size, s.subs);
                t.subs = [newsubs; addsubs];
                t.vals = [newvals; rhs.vals];

                return;
            end

            %% Case I(b): RHS is zero or scalar

            % First, Resize the tensor.
            % Determine new size of existing modes
            for n = 1:ndims(t)
                if ischar(s.subs{n}) && (s.subs{n} == ':')
                    newsz(1,n) = t.size(n);
                else
                    newsz(1,n) = max([t.size(n) s.subs{n}]);
                end
            end
            % Determine size of new modes, if any
            for n = ndims(t)+1:numel(s.subs)
                newsz(1,n) = max(s.subs{n});
            end
            t.size = newsz;

            % Expand subs array if there are new modes, i.e., if the order
            % has increased.
            if ~isempty(t.subs) && (size(t.size,2) > size(t.subs,2))
                t.subs(:,end+1:size(t.size,2)) = 1;
            end

            % Case I(b)i: Zero right-hand-side
            if numel(rhs) == 1 && rhs == 0

                % Delete what currently occupies the specified range
                rmloc = subdims(s.subs,t);
                kploc = setdiff(1:nnz(t),rmloc);
                t.subs = t.subs(kploc,:);
                t.vals = t.vals(kploc);
                return;
            end

            % Case I(b)ii: Scalar right-hand-side
            if numel(rhs) == 1

                % Determine number of dimensions (may be larger than
                % current number)
                N = numel(s.subs);

                % Figure out how many indices are in each dimension
                nssubs = zeros(N,1);
                for n = 1:N
                    if ischar(s.subs{n}) && s.subs{n} == ':'
                        s.subs{n} = 1:size(t,n);
                    end
                    nssubs(n) = numel(s.subs{n});
                end

                % Preallocate (discover any memory issues here!)
                addsubs = zeros(prod(nssubs),N);

                % Generate appropriately sized ones vectors.
                o = cell(N,1);
                for n = 1:N
                    o{n} = ones(nssubs(n),1);
                end

                % Generate each column of the subscripts in turn
                for n = 1:N
                    i = o;
                    i{n} = s.subs{n}';
                    addsubs(:,n) = khatrirao(i);
                end

                if ~isempty(t.subs)
                    % replace existing values
                    [junk,loc] = intersect(t.subs,addsubs,'rows');
                    t.vals(loc) = rhs;
                    % pare down list of subscripts to add
                    addsubs = setdiff(addsubs,t.subs,'rows');
                end
                t.subs = [t.subs; addsubs];
                t.vals = [t.vals; rhs*ones(size(addsubs,1),1)];
                return;
            end

            error('Invalid RHS')

        end

        % Case II: Subscripts
        if isequal(type,'subscripts')

            % Case II: Replacing values at specified indices

            newsubs = [s.subs{1}];
            tt_subscheck(newsubs);

            % Error check on subscripts
            if size(newsubs,2) < ndims(t)
                error('Invalid subscripts');
            end

            % Check for expanding the order
            if size(newsubs,2) > ndims(t)
                t.size(end+1:size(newsubs,2)) = 1;
                if ~isempty(t.subs)
                    t.subs(:,end+1:size(newsubs,2)) = 1;
                end
            end

            % Copy rhs to newvals
            newvals = rhs;

            % Error check the RHS is a column vector. We do not bother to
            % handle any other type of RHS with the sparse tensor.
            tt_valscheck(newvals);

            % Determine number of nonzeros being inserted. (This is
            % determined by the number of subscripts. Later we will check
            % to see that it matches the size of the RHS.)
            newnnz = size(newsubs,1);

            % Error check on size of newvals
            if numel(newvals) == 1

                % Special case where newvals is a single element to be
                % assigned to multiple RHS. Fix to be correct size.
                newvals = newvals * ones(newnnz,1);

            elseif size(newvals,1) ~= newnnz

                % Sizes don't match!
                error('Number of subscripts and number of values do not match!');

            end

            % Remove duplicates & print warning if any duplicates were
            % removed.
            [newsubs,idx] = unique(newsubs,'rows');
            if size(newsubs,1) ~= newnnz
                warning('Duplicate assignments discarded.');
            end
            newvals = newvals(idx);

            % Find which subscripts already exist and their locations
            [tf,loc] = ismember(newsubs,t.subs,'rows');

            % Split into three groups for processing:
            %
            % Group A: Elements that already exist and need to be changed
            % Group B: Elements that already exist and need to be removed
            % Group C: Elements that do not exist and need to be added
            %
            % Note that we are ignoring any new zero elements, because
            % those obviously do not need to be added. Also, it's
            % important to process Group A before Group B because the
            % processing of Group B may change the locations of the
            % remaining elements.

            idxa = find((tf .* newvals) ~= 0);
            idxb = find((tf .* ~abs(newvals)) ~= 0);
            idxc = find((~tf .* newvals) ~= 0);

            % Process Group A: Changing values
            if ~isempty(idxa)
                t.vals(loc(idxa)) = newvals(idxa);
            end

            % Process Group B: Removing values
            if ~isempty(idxb)
                removesubs = loc(idxb);
                keepsubs = setdiff(1:nnz(t),removesubs);
                t.subs = t.subs(keepsubs,:);
                t.vals = t.vals(keepsubs);
            end

            % Process Group C: Adding new, nonzero values
            if ~isempty(idxc)
                t.subs = [t.subs; newsubs(idxc,:)];
                t.vals = [t.vals; newvals(idxc)];
            end

            % Resize the tensor!
            for n = 1:length(t.size)
                smax = max(newsubs(:,n));
                t.size(n) = max(t.size(n), smax);
            end

            return;

        end

        error('Invalid call to sptensor/subsasgn');

    case '{}'
        error('Subscript cell reference not supported for sptensor.');

    otherwise
        error('Incorrect indexing into sptensor.')

end


%% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy 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 software 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 software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defop  Method   @@sym mtimes {(@var{x}, @var{y})}
%% @defopx Operator @@sym {@var{x} * @var{y}} {}
%% Multiply symbolic matrices.
%%
%% Example:
%% @example
%% @group
%% syms x y
%% A = sym([1 2; 3 4])
%%   @result{} A = (sym 2×2 matrix)
%%       ⎡1  2⎤
%%       ⎢    ⎥
%%       ⎣3  4⎦
%% B = [x; y]
%%   @result{} B = (sym 2×1 matrix)
%%       ⎡x⎤
%%       ⎢ ⎥
%%       ⎣y⎦
%% A * B
%%   @result{} (sym 2×1 matrix)
%%       ⎡ x + 2⋅y ⎤
%%       ⎢         ⎥
%%       ⎣3⋅x + 4⋅y⎦
%% @end group
%% @end example
%% @end defop

function z = mtimes(x, y)

  cmd = { '(x,y) = _ins'
          'return x*y,' };

  z = pycall_sympy__ (cmd, sym(x), sym(y));

end

%!test
%! % scalar
%! syms x
%! assert (isa (x*2, 'sym'))
%! assert (isequal (2*sym(3), sym(6)))
%! assert (isequal (sym(2)*3, sym(6)))

%!test
%! % matrix-scalar
%! D = [0 1; 2 3];
%! A = sym(D);
%! assert (isa (2*A, 'sym'))
%! assert (isequal ( 2*A , 2*D  ))
%! assert (isequal ( A*2 , 2*D  ))

%!test
%! % matrix-matrix
%! D = [0 1; 2 3];
%! A = sym(D);
%! assert (isa (A*A, 'sym'))
%! assert (isequal ( A*A , D*D  ))


function b = cgbsl ( abd, lda, n, ml, mu, ipvt, b, job )

%*****************************************************************************80
%
%% CGBSL solves a complex band system factored by CGBCO or CGBFA.
%
%  Discussion:
%
%    CGBSL can solve A * X = B or hermitan ( A ) * X = B.
%
%    A division by zero will occur if the input factor contains a
%    zero on the diagonal.  Technically this indicates singularity
%    but it is often caused by improper arguments or improper
%    setting of LDA.  It will not occur if the subroutines are
%    called correctly and if CGBCO has set 0.0 < RCOND
%    or CGBFA has set INFO = 0.
%
%    To compute inverse ( A ) * C where C is a matrix with P columns:
%
%      call cgbco(abd,lda,n,ml,mu,ipvt,rcond,z)
%
%      if ( rcond is not too small ) then
%        do j = 1, p
%          call cgbsl(abd,lda,n,ml,mu,ipvt,c(1,j),0)
%        end do
%      end if
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 April 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, (Society for Industrial and Applied Mathematics),
%    3600 University City Science Center,
%    Philadelphia, PA, 19104-2688.
%
%  Parameters:
%
%    Input, complex ABD(LDA,N), the output from CGBCO or CGBFA.
%
%    Input, integer LDA, the leading dimension of ABD.
%
%    Input, integer N, the order of the matrix.
%
%    Input, integer ML, the number of diagonals below the main diagonal.
%
%    Input, integer MU, the number of diagonals above the main diagonal.
%
%    Input, integer IPVT(N), the pivot vector from CGBCO or CGBFA.
%
%    Input, complex B(N), the right hand side.
%
%    Input, integer JOB.
%    0, to solve A*x = b,
%    nonzero, to solve hermitian(A)*x = b, where hermitian(A) is the
%    conjugate transpose.
%
%    Output, complex B(N), the solution.
%
  m = mu + ml + 1;

  if ( job == 0 )
%
%  JOB = 0, solve A * X = B.
%
%  First solve L * Y = B.
%
    if ( ml ~= 0 )

      for k = 1 : n - 1

        lm = min ( ml, n - k );
        l = ipvt(k);
        t = b(l);

        if ( l ~= k )
          b(l) = b(k);
          b(k) = t;
        end

        b(k+1:k+lm) = b(k+1:k+lm) + t * abd(m+1:m+lm,k);

      end

    end
%
%  Now solve U * X = Y.
%
    for k = n : -1 : 1
      b(k) = b(k) / abd(m,k);
      lm = min ( k, m ) - 1;
      la = m - lm;
      lb = k - lm;
      t = -b(k);
      b(lb:lb+lm-1) = b(lb:lb+lm-1) + t * transpose ( abd(la:la+lm-1,k) );
    end

  else
%
%  JOB = nonzero, solve hermitian(A) * X = B.
%
%  First solve hermitian ( U ) * Y = B.
%
    for k = 1 : n
      lm = min ( k, m ) - 1;
      la = m - lm;
      lb = k - lm;
      t = cdotc ( lm, abd(la,k), 1, b(lb), 1 );
      b(k) = ( b(k) - t ) / conj ( abd(m,k) );
    end
%
%  Now solve hermitian ( L ) * X = Y.
%
    if ( ml ~= 0 )

      for k = n-1 : -1 : 1

        lm = min ( ml, n - k );
        b(k) = b(k) + cdotc ( lm, abd(m+1,k), 1, b(k+1), 1 );
        l = ipvt(k);

        if ( l ~= k )
          t    = b(l);
          b(l) = b(k);
          b(k) = t;
        end

      end

    end

  end

  return
end


function varargout = fillSphericalPolygon(sphere, poly, germ)
%FILLSPHERICALPOLYGON  Fill a spherical polygon
%
%   fillSphericalPolygon(SPHERE, POLY, GERM)
%
%
%   Example
%   fillSphericalPolygon
%
%   See also
%   drawSphericalPolygon, fillSphericalTriangle, drawSphere
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2012-02-09,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2012 INRA - Cepia Software Platform.

nv = size(poly, 1);

h = zeros(nv, 1);
for i = 1:nv
    v1 = poly(i, :);
    v2 = poly(mod(i, nv) + 1, :);

    h(i) = fillSphericalTriangle(sphere, germ, v1, v2);
end

if nargout > 0
    varargout = {h};
end


function f = ivmKernelObjective(params, model)

% IVMKERNELOBJECTIVE Compute the negative of the IVM log likelihood approximation.
% FORMAT

% DESC computes the IVM negative log likelihood approximation at a
% given set of kernel parameters. Adiditonally if there is any
% regularisation present on the kernel parameter it computes the prior
% probability and adds it in.
% ARG params : the parameter values where the obective is to be
% evaluated.
% ARG model : the model structure for which the objective is to be
% evaluated.
%
% SEEALSO : ivmKernelGradient, ivmOptimiseKernel, kernExpandParam,
% ivmApproxLogLikelihood, kernPriorLogProb
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005

% IVM

%/~
if any(isnan(params))
  warning('Parameter is NaN')
end
%~/

model.kern = kernExpandParam(model.kern, params);
f = ivmApproxLogLikelihood(model);
f = f + kernPriorLogProb(model.kern);
f = -f;


function [xRot,rotMat]=GCRS2MOD(xVec,TT1,TT2)
%%GCRS2MOD Rotate a vector from the geocentric celestial reference system
%          (GCRS) to the mean of date (MOD) coordinate system, which is
%          the coordinate system using the mean equinox and
%          ecliptic of date, IAU 2006/2000A model. The transformation is
%          performed by adding the precession and frame bias.
%
%INPUTS: xVec The 3XN matrix of N 3X1 Cartesian vectors that are to be
%             rotated from the GCRS coordinate system into the MOD
%             coordinate system.
% TT1, TT2 Jul1,Jul2 Two parts of a Julian date given in TT. The units
%             of the date are days. The full date is the sum of both
%             terms. The date is broken into two parts to provide more
%             bits of precision. It does not matter how the date is
%             split.
%
%OUTPUTS: xRot The 3XN matrix of the N 3X1 input vector rotated into the
%              MOD coordinate system.
%       rotMat The 3X3 rotation matrix such that
%              xRot(:,i)=rotMat*xVec(:,i).
%
%This uses functions in the International Astronomical Union's (IAU)
%Standard's of Fundamental Astronomy (SOFA) library to obtain the product
%of the precession rotation matrix and the frame rotation bias matrix. One
%goes from GCRS to mean of date by applying a frame bias and then
%precession. Thus this function removes those rotations. The rotations are
%discussed in the documentation for the SOFA library as well as in [1]
%among other sources.
%
%The algorithm can be compiled for use in Matlab  using the
%CompileCLibraries function.
%
%The algorithm is run in Matlab using the command format
%[xRot,rotMat]=GCRS2MOD(xVec,TT1,TT2);
%
%Different celestial coordinate systems are compared in [2].
%
%REFERENCES:
%[1] G. Petit and B. Luzum, IERS Conventions (2010), International Earth
%    Rotation and Reference Systems Service Std. 36, 2010.
%[2] D. F. Crouse, "An Overview of Major Terrestrial, Celestial, and
%    Temporal Coordinate Systems for Target Tracking," Formal Report,
%    Naval Research Laboratory, no. NRL/FR/5344--16-10,279, 10 Aug. 2016,
%    173 pages.
%
%March 2014 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

error('This function is only implemented as a mexed C or C++ function. Please run CompileCLibraries.m to compile the function for use.')

end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function Population = SubcomponentOptimizer(Problem,Population,Neighbour,indices)
% Subcomponent optimizer

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    for i = 1 : length(Population)
        if rand < 0.9
            P = Neighbour(i,randperm(size(Neighbour,2),2));
        else
            P = randperm(length(Population),2);
        end
        OffDec          = Population(i).dec;
        NewDec          = OperatorDE(Problem,OffDec,Population(P(1)).dec,Population(P(2)).dec,{1,0.5,length(OffDec)/length(indices)/2,20});
        OffDec(indices) = NewDec(indices);
        Offspring       = Problem.Evaluation(OffDec);
        if sum(Offspring.obj) < sum(Population(i).obj)
            Population(i) = Offspring;
        end
    end
end