function z = times( x, y, oper )

%   Disciplined convex programming information for TIMES:
%      In general, disciplined convex programs must obey the "no-product
%      rule" which states that two non-constant expressions cannot be
%      multiplied together. Under this rule, the following combinations
%      are allowed:
%         {constant} .* {non-constant}  {non-constant} .* {constant}
%      Furthermore, if the non-constant expression is nonlinear, then
%      the constant term must be real.
%
%      A lone exception to the no-product rule is made for quadratic
%      forms: two affine expressions may be multiplied together if the
%      result is convex or concave. For example, the construction
%         variable x(n)
%         x.*x  <= 1;
%      would be permitted because each element of x.*x is convex.
%
%   Disciplined geometric programming information for TIMES:
%      Both terms in a multiplication must have the same log-curvature,
%      so the following products are permitted:
%         {log-convex} .* {log-convex}  {log-concave} .* {log-concave}
%         {log-affine} .* {log-affine}
%      Note that log-affine expressions are both log-convex and
%      log-concave.
%
%   For vectors, matrices, and arrays, these rules are verified
%   indepdently for each element.

error( nargchk( 2, 3, nargin ) );
if nargin < 3, oper = '.*'; end

%
% Check sizes
%

sx = size( x );
sy = size( y );
xs = all( sx == 1 );
ys = all( sy == 1 );
if xs,
    sz = sy;
elseif ys,
    sz = sx;
elseif ~isequal( sx, sy ),
    error( 'Matrix dimensions must agree.' );
else
    sz = sx;
end
nn = prod( sz );
if nn == 0,
    z = zeros( sz );
    return
end

%
% Determine the computation methods
%

persistent remap_m remap_l remap_r
if isempty( remap_r ),
    % zero .* valid, valid .* zero, constant .* constant
    temp_1    = cvx_remap( 'constant' );
    temp_2    = cvx_remap( 'zero' );
    temp_3    = temp_2' * cvx_remap( 'valid' );
    remap_1   = ( temp_1' * temp_1 ) | temp_3 | temp_3';
    remap_1n  = ~remap_1;
    % constant / nonzero, zero / log-concave, zero / log-convex
    temp_4    = temp_1 & ~temp_2;
    remap_1r  = ( temp_1' * temp_4 ) | ( temp_2' * cvx_remap( 'log-valid' ) );
    remap_1rn = ~remap_1r;

    % constant * affine, real * convex/concave/log-convex, positive * log-concave
    temp_5   = cvx_remap( 'real' );
    temp_6   = cvx_remap( 'positive' );
    temp_7   = cvx_remap( 'affine' );
    temp_1n   = ~temp_1;
    temp_8   = cvx_remap( 'log-concave' ) & temp_1n;
    remap_2  = ( temp_1' * temp_7 ) | ...
               ( temp_5' * cvx_remap( 'convex', 'concave', 'log-convex' ) ) | ...
               ( temp_6' * temp_8 );
    remap_2  = remap_2 & remap_1n;
    % real / log-concave, positive / log-convex
    temp_9   = cvx_remap( 'log-convex' ) & temp_1n;
    remap_2r = ( temp_5' * temp_8 ) | ...
               ( temp_6' * temp_9 );
    remap_2r = remap_2r & remap_1rn;

    % Affine * constant, convex/concave/log-convex * real, log-concave * positive
    remap_3  = remap_2';
    % Affine / nonzero, convex/concave/log-convex / nzreal, log-concave / positive
    remap_3r = remap_3;
    remap_3r(:,2) = 0;

    % Affine * affine
    remap_4  = temp_7 & ~temp_1;
    remap_4  = remap_4' * +remap_4;

    % log-concave * log-concave, log-convex * log-convex
    remap_5  = ( temp_8' * +temp_8 ) | ( temp_9' * +temp_9 );
    % log-concave / log-convex, log-convex / log-concave
    remap_5r = temp_8' * +temp_9;
    remap_5r = remap_5r | remap_5r';

    remap_m = remap_1 + 2 * remap_2  + 3 * remap_3 + 4 * remap_4 + 5 * remap_5;
    remap_r = remap_1r + 2 * remap_2r + 3 * remap_3r + 5 * remap_5r;
    remap_r(:,2) = 0;
    remap_l = remap_r';
end
switch oper,
    case '.*',
        remap = remap_m;
        r_recip = 0;
        l_recip = 0;
    case './',
        remap = remap_r;
        r_recip = 1;
        l_recip = 0;
    case '.\',
        remap = remap_l;
        r_recip = 0;
        l_recip = 1;
end
vx = cvx_classify( x );
vy = cvx_classify( y );
vr = remap( vx + size( remap, 1 ) * ( vy - 1 ) );
vu = sort( vr(:) );
vu = vu([true;diff(vu)~=0]);
nv = length( vu );
if vu(1) == 1 && nv > 1,
    vr(vr==1) == vu(2);
    nv = nv - 1;
    vu(1) = [];
end

%
% Process each computation type separately
%

x   = cvx( x );
y   = cvx( y );
xt  = x;
yt  = y;
if nv ~= 1,
    z = cvx( sz, [] );
end
for k = 1 : nv,

    %
    % Select the category of expression to compute
    %

    if nv ~= 1,
        t = vr == vu( k );
        if ~xs,
            xt = cvx_subsref( x, t );
            sz = size( xt );
        end
        if ~ys,
            yt = cvx_subsref( y, t );
            sz = size( yt );
        end
    end

    %
    % Apply the appropriate computation
    %

    switch vu( k ),
    case 0,

        % Invalid
        error( 'Disciplined convex programming error:\n    Cannot perform the operation: {%s} %s {%s}', cvx_class( xt, true, true, true ), oper, cvx_class( yt, true, true, true ) );

    case 1,

        % constant .* constant
        xb = cvx_constant( xt );
        yb = cvx_constant( yt );
        if l_recip,
            cvx_optval = xb .\ yb;
        elseif r_recip,
            cvx_optval = xb ./ yb;
        else
            cvx_optval = xb .* yb;
        end
        if nnz( isnan( cvx_optval ) ),
            error( 'Disciplined convex programming error:\n    This expression produced one or more invalid numeric values (NaNs).', 1 ); %#ok
        end
        cvx_optval = cvx( cvx_optval );

    case 2,

        % constant .* something
        xb = cvx_constant( xt );
        if l_recip, xb = 1.0 ./ xb; end
        yb = yt;
        if r_recip && nnz( xb ), yb = exp( - log( yb ) ); end
        yb = yb.basis_;
        if ~xs,
            nn = numel(  xb  );
            if ys,
                xb = cvx_reshape( xb, [ 1, nn ] );
                if issparse( yb ) && ~issparse( xb ),
                    xb = sparse( xb );
                end
            else
                n1 = 1 : nn;
                xb = sparse( n1, n1, xb( : ), nn, nn );
            end
        end
        cvx_optval = cvx( sz, yb * xb );

    case 3,

        % something .* constant
        yb = cvx_constant( yt );
        if r_recip, yb = 1.0 ./ yb; end
        xb = xt;
        if l_recip && any( xb ), xb = exp( - log( xb ) ); end
        xb = xb.basis_;
        if ~ys,
            nn = numel(  yb  );
            if xs,
                yb = cvx_reshape( yb, [ 1, nn ] );
                if issparse( xb ) && ~issparse( yb ),
                    yb = sparse( yb );
                end
            else
                n1 = 1 : nn;
                yb = sparse( n1, n1, yb( : ), nn, nn );
            end
        end
        cvx_optval = cvx( sz, xb * yb );

    case 4,

        % affine .* affine
        nn = prod( sz );
        xA = xt.basis_; yA = yt.basis_;
        if xs && ~ys, xA = xA( :, ones( 1, nn ) ); end
        if ys && ~xs, yA = yA( :, ones( 1, nn ) ); end
        mm = max( size( xA, 1 ), size( yA, 1 ) );
        if size( xA, 1 ) < mm, xA( mm, end ) = 0; end
        if size( yA, 1 ) < mm, yA( mm, end ) = 0; end
        xB = xA( 1, : ); xA( 1, : ) = 0;
        yB = yA( 1, : ); yA( 1, : ) = 0;
        cyA   = conj( yA );
        alpha = sum( real( xA .* yA ), 1 ) ./ max( sum( cyA .* yA, 1 ), realmin );
        adiag = sparse( 1 : nn, 1 : nn, alpha, nn, nn );
        if all( sum( abs( xA - cyA * adiag ), 2 ) <= 2 * eps * sum( abs( xA ), 2 ) ),
            beta  = xB - alpha .* conj( yB );
            alpha = reshape( alpha, sz );
            if isreal( y ),
                cvx_optval = alpha .* square( y ) + reshape( beta, sz ) .* y;
            elseif all( abs( beta ) <= 2 * eps * abs( xB ) ),
                cvx_optval = alpha .* square_abs( y );
            else
                error( 'Disciplined convex programming error:\n    Invalid quadratic form(s): product is not real.\n', 1 ); %#ok
            end
        else
            error( 'Disciplined convex programming error:\n    Invalid quadratic form(s): not a square.\n', 1 ); %#ok
        end

    case 5,

        % posynomial .* posynomial
        xb = log( xt );
        if l_recip, xb = - xb; end
        yb = log( yt );
        if r_recip, yb = - yb; end
        cvx_optval = exp( xb + yb );

    otherwise,

        error( 'Shouldn''t be here.' );

    end

    %
    % Store the results
    %

    if nv == 1,
        z = cvx_optval;
    else
        z = cvx_subsasgn( z, t, cvx_optval );
    end

end

% Copyright 2010 Michael C. Grant and Stephen P. Boyd.
% See the file COPYING.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function [TorF, vstr, rdate] = have_feature_gurobi()
%HAVE_FEATURE_GUROBI  Detect availability/version info for Gurobi
%
%   Feature detection function implementing 'gurobi' tag for HAVE_FEATURE
%   to detect availability/version of Gurobi optimizer
%   (https://www.gurobi.com).
%
%   See also HAVE_FEATURE, QPS_MASTER, MIQPS_MASTER, GUROBI.

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

TorF = exist('gurobi', 'file') == 3;
vstr = '';
rdate = '';
if TorF
    try
        model = struct( ...
            'A', sparse(1), ...
            'rhs', 1, ...
            'sense', '=', ...
            'vtype', 'C', ...
            'obj', 1, ...
            'modelsense', 'min' ...
        );
        params = struct( ...
            'outputflag', 0 ...
        );
        result = gurobi(model, params);
        vstr = sprintf('%d.%d.%d', result.versioninfo.major, result.versioninfo.minor, result.versioninfo.technical);
    catch % gurobiError
        TorF = 0;
        fprintf('Gurobi Error!\n');
%         disp(gurobiError.message);
    end
end


function calcAllFusedTextures_HNissam(pathWORK,nPatient,roiNumb,CTinv_cell,CTweight_mat,R_mat,scale_cell,algo_cell,Ng_mat,fusWeights)
% -------------------------------------------------------------------------
% function calcAllFusedTextures_HNissam(pathWORK,nPatient,roiNumb,CTinv_cell,CTweight_mat,R_mat,scale_cell,algo_cell,Ng_mat)
% -------------------------------------------------------------------------
% DESCRIPTION:
% This function computes FUSED texture features for all patients, for all
% different combinations of the following texture extraction parameters:
% - CT Inv.: Inversion of CT intensities in the PET/CT fusion process.
% - CT weight: Weight given to MRI wavelet low-pass sub-bands in the
%               PET/CT fusion process.
% - WPBF ratio 'R': Ratio specifying the ratio of weight given to band-pass
%                   coefficients to the weigth given to the rest of
%                   coefficients (HHH and LLL) in the wavelet band-pass
%                   filtering process.
% - Scale: Resolution at which the ROI is isotropically resampled.
% - Quant. Algo.: Quantization algorithm used on analyzed ROI.
% - Ng: Number of gray-levels in the quantization process.
%
% Different extraction parameters are passed as arrays or cells in the
% function in order to test all possible combinations. This function is
% used for FUSED scans specifically. See Ref. [1,2] and 'prepareVolume.m'
% for more details.
%
% Texture features are computed for all head and neck (HN) DICOM  imaging
% data downloaded from The Cancer Imaging Archive (TCIA) website at:
% <http://dx.doi.org/10.7937/K9/xxxxxxxxxxxxxxxxxxx, and first organized
% in a 'DATA' directory using the function readAllDICOM_HN.m.  Results are
% then saved in a folder 'TEXTURES' in the HN WORKSPACE.
% -------------------------------------------------------------------------
% REFERENCE:
% [1] Vallieres, M. et al. (2015). FDG-PET/CT radiomics models for the
%     early prediction of different tumour outcomes in head and neck cancer.
%     The Journal of Nuclear Medicine, aa(bb), xxx-yyy.
%     doi:
% [2] Vallieres, M. et al. (2015). A radiomics model from joint FDG-PET and
%     MRI texture features for the prediction of lung metastases in soft-tissue
%     sarcomas of the extremities. Physics in Medicine and Biology, 60(14),
%     5471-5496. doi:10.1088/0031-9155/60/14/5471
% -------------------------------------------------------------------------
% INPUTS:
% - pathWORK: Full path to the HN WORKSPACE directory.
% - nPatient: Number of patients to read.
% - roiNumb: Array of size [N X 2] specifying the contour number
%            corresponding to the GTV in sData{2}.scan.contour for all
%            patients. First column is for the PET data, second column for
%            CT data.
% - CTinv_cell: Cell vector specifying the different 'CT Inv.' values to test.
% - CTweight_mat: Array vector specifying the different 'CT weight' values to test.
% - R_mat: Array vector specifying the different 'R' ratio values to test.
% - scale_cell: Cell vector specifying the different 'Scale' values to test.
% - algo_cell: Cell vector specifying the different 'Quant. Algo.' values to test.
% - Ng_mat: Array vector specifying the different 'Ng' values to test.
% -------------------------------------------------------------------------
% EXAMPLE:
% CTinv_cell = {'NoInv','Inv'};
% CTweight_mat = [1/4,1/3,1/2,2/3,3/4];
% R_mat = [1/2,2/3,1,3/2,2];
% scale_cell = {'pixelW',1,2,3,4,5};
% algo_cell = {'Uniform','Equal','Lloyd'};
% Ng_mat = [8,16,32,64];
% -------------------------------------------------------------------------
% AUTHOR(S): Martin Vallieres <mart.vallieres@gmail.com>
% -------------------------------------------------------------------------
% HISTORY:
% - Creation: July 2015
%--------------------------------------------------------------------------
% STATEMENT:
% This file is part of <https://github.com/mvallieres/radiomics/>,
% a package providing MATLAB programming tools for radiomics analysis.
% --> Copyright (C) 2015  Martin Vallieres
%
%    This package 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 package 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 package.  If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------

startpath=pwd;
cd(pathWORK), cd('TEXTURES'), pathTEXT = pwd;
cd .., cd('DATA'), pathDATA = pwd;

% INITIALIZATION
scans = {'CT'};
nScans = numel(scans);
suffix = ['_TEXT'];

% COMPUTATION
fprintf('\n')
for i = 1:nPatient
    load(['Patient',num2str(i),'_PET']), sDataPET = sData;
    for j = 1:nScans
        nameLoad = ['Patient',num2str(i),'_CT'];
        load(nameLoad), sDataCT = sData;
        tStart = tic;
        fprintf(['\n*********************** COMPUTING TEXTURES: PATIENT %u, FUSED PET/',scans{j},' SCAN ***********************'],i)
        [textures] = calcPatientFusText_HNissam(sDataPET,sDataCT,roiNumb(i,:),CTinv_cell,CTweight_mat,R_mat,scale_cell,algo_cell,Ng_mat,fusWeights);
        cd(pathTEXT), save(['Patient',num2str(i),'_PET_',scans{j},suffix],'textures')
        cd(pathDATA)
        time = toc(tStart);
        fprintf('TOTAL TIME: %.2f seconds\n',time)
    end
end

cd(startpath)
end


function [LRatio IsolDist ID] = plx_getClusterQuality(varargin)
% USAGE
%
% [LRatio IsolDist ID] = getClusterQuality(plxfile)
%
% INPUTS
%
%  plx - filename of a *.plx file in the current working directory (should
%        already be manually cluster cut)
%
% OUTPUTS
%
%  LRatio - L_Ratio.m
%  IsolDist - IsolationDistance.m
%  ID -
%
%
% pulls the spike waveforms out of a .plx file and returns cluster quality
% metrics

if nargin < 1
    plx = dir('*plx');
    for i=1:length(plx)
        if ~isempty(findstr(lower(plx(i).name),'cut'))
            plx = plx(i).name;
        end
    end
else
    plx = varargin{1};
end

if isempty(plx)
    LRatio=nan;
    IsolDist=nan;
    ID=nan;
    return
end
try
    [OpenedFileName, Version, Freq, Comment, Trodalness, NPW, PreTresh, ...
        SpikePeakV, SpikeADResBits, SlowPeakV, SlowADResBits, Duration, ...
        DateTime] = plx_information(plx);

    for i=1:Trodalness:48
        for j=1:50  % ..if you're recording > 50 units per *trode, you may want to do some merging...
        [n, npw, ts, wave{i,j}] = plx_waves_v(plx,i,j-1); % -1 includes 'unsorted spikes'
        [n, npw, ts, wave{i+1,j}] = plx_waves_v(plx,i+1,j-1);
        end
    end

    c=1;
    for j=1:Trodalness:48
        w=[];id=[];
        for i=1:50
            if wave{j,i}~=-1
                if size(wave{j,i},1) == size(wave{j+1,i},1)
                w =[w; wave{j,i}, wave{j+1,i}];
                id = [id;i*ones(size(wave{j,i},1),1)];
                end
            end
        end
        for i=1:50
            if ~isempty(find(id==i))
           IsolDist(c) = IsolationDistance(w, find(id==i));
           [L, LRatio(c), df]  = L_Ratio(w, find(id==i));
           if i == 1
               ID(c) = 0;
           else
               ID(c) = 1;
           end
           c=1+c;
            end
        end
        clear w id
    end
end


function [obX,obY,obSize,obSizeOrig,sagPts,sagSlice,lp,obPts,obSlice] = ...
              mrReloadParams(lp,curInplane,obXM,obYM,sagSize,numSlices,volume,cTheta,aTheta,curSag,reflections,scaleFac)

% PURPOSE: Implements the reloading of variables from AlignParams
% AUTHOR: SPG
% DATE: 11.21.97
% NOTES:

if ~isempty(obXM)
    obX = obXM(curInplane,:);
    obY = obYM(curInplane,:);
    lp = mrRefreshInplanes(lp,obXM,obYM,curInplane,0);
else
    obX = [0,0];
    obY = [0,0];
end

[obSize,obSizeOrig] = mrFindObSize(obX,obY,sagSize,numSlices,curInplane);

[sagSlice,sagPts,obSlice,obPts]=mrRotSagVol(volume,obXM,obYM,obSize,sagSize,cTheta,aTheta,curSag,reflections,1,1/scaleFac(1,3));


function [Nv, VX, K, EToV] = MeshReader1DGambit(FileName)

% function [Nv, VX, K, EToV] = MeshReader1DGambit(FileName)
% Purpose  : Read in basic grid information to build grid
%
% NOTE     : gambit(Fluent, Inc) *.neu format is assumed

% Open file and read intro
Fid = fopen(FileName, 'rt');
for i=1:6; line = fgetl(Fid); end

% Find number of nodes and number of elements
dims = fscanf(Fid, '%d');
Nv = dims(1); K = dims(2);
for i=1:2; line = fgetl(Fid); end

% read node coordinates
VX = (1:Nv);
for i = 1:Nv
  line = fgetl(Fid);
  tmpx = sscanf(line, '%lf');
  VX(i) = tmpx(2);
end
for i=1:2; line = fgetl(Fid); end

% read element to node connectivity
EToV = zeros(K, 2);
for k = 1:K
  line   = fgetl(Fid);
  tmpcon = sscanf(line, '%lf');
  EToV(k,1) = tmpcon(4); EToV(k,2) = tmpcon(5);
end

% Close file
st = fclose(Fid);
return


function r = or(p,q)
% this function compares the x, y, and z values of the structures that I use in
% the FVtool.
%
% SYNOPSIS:
%
%
% PARAMETERS:
%
%
% RETURNS:
%
%
% EXAMPLE:
%
% SEE ALSO:
%

% Copyright (c) 2012-2016 Ali Akbar Eftekhari
% See the license file

if (isa(p, 'FaceVariable')&&isa(q, 'FaceVariable'))
    r=p;
    r.xvalue = p.xvalue|q.xvalue;
    r.yvalue = p.yvalue|q.yvalue;
    r.zvalue = p.zvalue|q.zvalue;
elseif isa(p, 'FaceVariable')
    r=p;
    r.xvalue = p.xvalue|q;
    r.yvalue = p.yvalue|q;
    r.zvalue = p.zvalue|q;
else
    r=q;
    r.xvalue = p|q.xvalue;
    r.yvalue = p|q.yvalue;
    r.zvalue = p|q.zvalue;
end


% Copyright 2011 Zdenek Kalal
%
% This file is part of TLD.
%
% TLD 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.
%
% TLD 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 TLD.  If not, see <http://www.gnu.org/licenses/>.

function d = bb_distance(bb1,bb2)
% Info

switch nargin
    case 1
        d = 1 - bb_overlap(bb1);
    case 2
        d = 1 - bb_overlap(bb1,bb2);
end


function selectp(in_or_out)
    %  This .m file selects the earthquakes within a polygon
    %  and plots them. Sets "primeCatalog" equal to the catalogue produced after the
    %  general parameter selection. Operates on "storedcat", replaces "primeCatalog"
    %  with new data and makes "primeCatalog" equal to ZG.newcat
    %
    %   operates on main map window
    % plot tags:
    %  'poly_selected_events' : earthquakes in/out of polygon
    %  'mouse_points_overlay' : polygon outline

    ZG=ZmapGlobal.Data;
    echo on
    % ___________________________________________________________
    %  Please use the left mouse button or the cursor to select
    %  the polygon vertexes.
    %
    %  Use the right mouse button to select the final point.
    %_____________________________________________________________
    echo off
    report_this_filefun();
    %zoom off
    ZG.newt2 = [ ];           % reset catalogue variables
    %a=storedcat;              % uses the catalogue with the pre-selected main
    % general parameters
    ZG.newcat = copy(ZG.primeCatalog);

    delete(findobj('Tag','mouse_points_overlay'));
    delete(findobj('Tag','poly_selected_events'));

    % pick polygon points,
    ax=findobj(gcf,'Tag','mainmap_ax');
    [x,y, mouse_points_overlay] = select_polygon(ax);

    if ~exist('in_or_out','var')
        in_or_out = 'inside';
    end
    if isnumeric(ZG.primeCatalog)
        error('old catalog');
    else
        mask = polygon_filter(x,y, ZG.primeCatalog.Longitude, ZG.primeCatalog.Latitude, in_or_out);
        ZG.newt2 = ZG.primeCatalog.subset(mask);

        % Plot of new catalog
        washeld=ishold(ax); ax.NextPlot='add';
        hMap=mainmap();
        hMap.plotOtherEvents(ZG.newt2,0,...
            'Marker','.',...
            'LineStyle','none',...
            'MarkerEdgeColor','g',...
            'MarkerFaceColor','none',...
            ...'Linewidth',1.5,...
            'DisplayName','Selected Events');

        %change the polygon characteristics
        set(mouse_points_overlay,'LineStyle','--','LineWidth',2,'Color',[.5 .5 .5],'Marker','none');
        if ~washeld; ax.NextPlot='replace';end
    end
    % ask for a name for this new catalog
    %ploc = get(0,'PointerLocation');
    prompt = 'Please provide a catalog name:';
    dlgname = 'CatalogSelection';
    numlines = 1;
    defaultans = {'new_catalog'};
    sel_nm = inputdlg('Please provide a catalog name:','Name of Selected Catalog',1, defaultans);
    if ~isempty(sel_nm)
        ZG.newt2.Name = sel_nm{1};
    end
    xy = [x y];

    %save polcor.dat xy -ascii
    [file1,path1] = uiputfile(fullfile(ZmapGlobal.Data.Directories.data, '*.txt'),'Save Polygon ? (yes/cancel)');
    if length(file1) > 1
        if length(file1)>3
            if strcmp(file1(length(file1)-3:length(file1)),'.txt')==0
                file1=[file1 '.txt']
            end
        end
        save([path1 file1],'xy', '-ascii');
    end

    %++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    %
    %   The new catalog (ZG.newcat) with points only within the
    %   selected Polygon is created and resets the original
    %   "primeCatalog" .
    %
    %++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    ZG.newcat = ZG.newt2;                   % resets ZG.newcat and ZG.newt2

    ctp=CumTimePlot(ZG.newt2);
    ctp.plot();
end


function [parcel] = ft_sourceparcellate(cfg, source, parcellation)

% FT_SOURCEPARCELLATE combines the source-reconstruction parameters over the parcels, for
% example by averaging all the values in the anatomically or functionally labeled parcel.
%
% Use as
%    output = ft_sourceparcellate(cfg, source, parcellation)
% where the input source is a 2D surface-based or 3-D voxel-based source grid that was for
% example obtained from FT_SOURCEANALYSIS or FT_COMPUTE_LEADFIELD. The input parcellation is
% described in detail in FT_DATATYPE_PARCELLATION (2-D) or FT_DATATYPE_SEGMENTATION (3-D) and
% can be obtained from FT_READ_ATLAS or from a custom parcellation/segmentation for your
% individual subject. The output is a channel-based representation with the combined (e.g.
% averaged) representation of the source parameters per parcel.
%
% The configuration "cfg" is a structure that can contain the following fields
%   cfg.method       = string, method to combine the values, see below (default = 'mean')
%   cfg.parcellation = string, fieldname that contains the desired parcellation
%   cfg.parameter    = cell-array with strings, fields that should be parcellated (default = 'all')
%
% The values within a parcel or parcel-combination can be combined with different methods:
%   'mean'      compute the mean
%   'median'    compute the median (unsupported for fields that are represented in a cell-array)
%   'eig'       compute the largest eigenvector
%   'min'       take the minimal value
%   'max'       take the maximal value
%   'maxabs'    take the signed maxabs value
%   'std'       take the standard deviation
%
% See also FT_SOURCEANALYSIS, FT_DATATYPE_PARCELLATION, FT_DATATYPE_SEGMENTATION

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

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

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

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

% get the defaults
cfg.parcellation = ft_getopt(cfg, 'parcellation');
cfg.parameter    = ft_getopt(cfg, 'parameter', 'all');
cfg.method       = ft_getopt(cfg, 'method', 'mean'); % can be mean, min, max, svd
cfg.feedback     = ft_getopt(cfg, 'feedback', 'text');

% the data can be passed as input argument or can be read from disk
hasparcellation = exist('parcellation', 'var');

if ischar(cfg.parameter)
  cfg.parameter = {cfg.parameter};
end

if hasparcellation
  % the parcellation is specified as separate structure
else
  % the parcellation is represented in the source structure itself
  parcellation = source;
end

% keep the transformation matrix
if isfield(parcellation, 'transform')
  transform = parcellation.transform;
else
  transform = [];
end

% ensure it is a parcellation, not a segmentation
parcellation = ft_checkdata(parcellation, 'datatype', 'parcellation', 'parcellationstyle', 'indexed', 'hasunit', 'yes');

% keep the transformation matrix
if ~isempty(transform)
  parcellation.transform = transform;
end

% ensure it is a source, not a volume
source = ft_checkdata(source, 'datatype', 'source', 'insidestyle', 'logical', 'hasunit', 'yes');

% ensure that the source and the parcellation are anatomically consistent
if ~strcmp(source.unit, parcellation.unit)
  ft_error('the units of the source and parcellation structure are not consistent, please use FT_SOURCEINTERPOLATE');
end

% ensure that the source and the parcellation are anatomically consistent
tolerance = 0.1 * ft_scalingfactor('mm', source.unit);
if ~isalmostequal(source.pos, parcellation.pos, 'abstol', tolerance)
  ft_error('the positions of the source and parcellation structure are not consistent, please use FT_SOURCEINTERPOLATE');
end

if isempty(cfg.parcellation)
  % determine the first field that can be used for the parcellation
  fn = fieldnames(parcellation);
  for i=1:numel(fn)
    if isfield(parcellation, [fn{i} 'label'])
      ft_warning('using "%s" for the parcellation', fn{i});
      cfg.parcellation = fn{i};
      break
    end
  end
end

if isempty(cfg.parcellation)
  ft_error('you should specify the field containing the parcellation');
end

% determine the fields and corresponding dimords to work on
fn = fieldnames(source);
fn = setdiff(fn, {'pos', 'tri', 'inside', 'outside', 'time', 'freq', 'dim', 'transform', 'unit', 'coordsys', 'cfg', 'hdr'}); % remove fields that do not represent the data
fn = fn(cellfun(@isempty, regexp(fn, 'dimord'))); % remove dimord fields
fn = fn(cellfun(@isempty, regexp(fn, 'label'))); % remove label fields
dimord = cell(size(fn));
for i=1:numel(fn)
  dimord{i} = getdimord(source, fn{i});
end

if any(strcmp(cfg.parameter, 'all'))
  cfg.parameter = fn;
else
  [inside, i1, i2] = intersect(cfg.parameter, fn);
  [outside       ] = setdiff(cfg.parameter, fn);
  if ~isempty(outside)
    ft_warning('\nparameter "%s" cannot be parcellated', outside{:});
  end
  cfg.parameter = fn(i2);
  fn     = fn(i2);
  dimord = dimord(i2);
end

% although it is technically feasible, don't parcellate the parcellation itself
sel    = ~strcmp(cfg.parcellation, fn);
fn     = fn(sel);
dimord = dimord(sel);

if numel(fn)==0
  ft_error('there are no source parameters that can be parcellated');
end

% get the parcellation and the labels that go with it
tissue      = parcellation.(cfg.parcellation);
tissuelabel = parcellation.([cfg.parcellation 'label']);
ntissue     = length(tissuelabel);

if isfield(source, 'inside')
  % determine the conjunction of the parcellation and the inside source points
  n0 = numel(source.inside);
  n1 = sum(source.inside(:));
  n2 = sum(tissue(:)~=0);
  fprintf('there are in total %d positions, %d positions are inside the brain, %d positions have a label\n', n0, n1, n2);
  fprintf('%d of the positions inside the brain have a label\n',        sum(tissue(source.inside)~=0));
  fprintf('%d of the labeled positions are inside the brain\n',         sum(source.inside(tissue(:)~=0)));
  fprintf('%d of the positions inside the brain do not have a label\n', sum(tissue(source.inside)==0));
  % discard the positions outside the brain and the positions in the brain that do not have a label
  tissue(~source.inside) = 0;
end

% start preparing the output data structure
parcel       = keepfields(source, {'freq','time','cumtapcnt'});
parcel.label = tissuelabel;

for i=1:numel(fn)
  % parcellate each of the desired parameters
  dat = source.(fn{i});
  siz = getdimsiz(source, fn{i});
  siz(contains(tokenize(dimord{i},'_'),'pos')) = ntissue;

  if startsWith(dimord{i}, '{pos_pos}')
    fprintf('creating %d*%d parcel combinations for parameter %s by taking the %s\n', numel(tissuelabel), numel(tissuelabel), fn{i}, cfg.method);
    tmp = zeros(siz);
    ft_progress('init', cfg.feedback, 'computing parcellation');
    k = 0;
    K = numel(tissuelabel)^2;
    for j1=1:numel(tissuelabel)
      for j2=1:numel(tissuelabel)
        k = k + 1;
        ft_progress(k/K, 'computing parcellation for %s combined with %s', tissuelabel{j1}, tissuelabel{j2});
        switch cfg.method
          case 'mean'
            tmp(j1,j2,:,:) = cellmean(dat(tissue==j1,tissue==j2));
          case 'median'
            tmp(j1,j2,:,:) = cellmedian(dat(tissue==j1,tissue==j2));
          case 'min'
            tmp(j1,j2,:,:) = cellmin(dat(tissue==j1,tissue==j2));
          case 'max'
            tmp(j1,j2,:,:) = cellmax(dat(tissue==j1,tissue==j2));
          case 'eig'
            tmp(j1,j2,:,:) = celleig(dat(tissue==j1,tissue==j2));
          case 'std'
            tmp(j1,j2,:,:) = cellstd(dat(tissue==j1,tissue==j2));
          otherwise
            ft_error('method %s not implemented for %s', cfg.method, dimord{i});
        end % switch
      end % for j2
    end % for j1
    ft_progress('close');

  elseif startsWith(dimord{i}, '{pos}')
    fprintf('creating %d parcels for parameter %s by taking the %s\n', numel(tissuelabel), fn{i}, cfg.method);
    tmp = zeros(siz);
    ft_progress('init', cfg.feedback, 'computing parcellation');
    for j=1:numel(tissuelabel)
      ft_progress(j/numel(tissuelabel), 'computing parcellation for %s', tissuelabel{j});
      switch cfg.method
        case 'mean'
          tmp(j,:,:) = cellmean(dat(tissue==j));
        case 'median'
          tmp(j,:,:) = cellmedian(dat(tissue==j));
        case 'min'
          tmp(j,:,:) = cellmin(dat(tissue==j));
        case 'max'
          tmp(j,:,:) = cellmax(dat(tissue==j));
        case 'eig'
          tmp(j,:,:) = celleig(dat(tissue==j));
        case 'std'
          tmp(j,:,:) = cellstd(dat(tissue==j));
        otherwise
          ft_error('method %s not implemented for %s', cfg.method, dimord{i});
      end % switch
    end % for
    ft_progress('close');

  elseif startsWith(dimord{i}, 'pos_pos')
    fprintf('creating %d*%d parcel combinations for parameter %s by taking the %s\n', numel(tissuelabel), numel(tissuelabel), fn{i}, cfg.method);
    siz     = size(dat);
    siz(1)  = ntissue;
    siz(2)  = ntissue;
    tmp     = nan(siz);
    ft_progress('init', cfg.feedback, 'computing parcellation');
    k = 0;
    K = numel(tissuelabel)^2;
    for j1=1:numel(tissuelabel)
      for j2=1:numel(tissuelabel)
        k = k + 1;
        ft_progress(k/K, 'computing parcellation for %s combined with %s', tissuelabel{j1}, tissuelabel{j2});
        switch cfg.method
          case 'mean'
            tmp(j1,j2,:) = arraymean2(dat(tissue==j1,tissue==j2,:));
          case 'median'
            tmp(j1,j2,:) = arraymedian2(dat(tissue==j1,tissue==j2,:));
          case 'min'
            tmp(j1,j2,:) = arraymin2(dat(tissue==j1,tissue==j2,:));
          case 'max'
            tmp(j1,j2,:) = arraymax2(dat(tissue==j1,tissue==j2,:));
          case 'eig'
            tmp(j1,j2,:) = arrayeig2(dat(tissue==j1,tissue==j2,:));
          case 'maxabs'
            tmp(j1,j2,:) = arraymaxabs2(dat(tissue==j1,tissue==j2,:));
          case 'std'
            tmp(j1,j2,:) = arraystd2(dat(tissue==j1,tissue==j2,:));
          otherwise
            ft_error('method %s not implemented for %s', cfg.method, dimord{i});
        end % switch
      end % for j2
    end % for j1
    ft_progress('close');

  elseif startsWith(dimord{i}, 'pos')
    fprintf('creating %d parcels for %s by taking the %s\n', numel(tissuelabel), fn{i}, cfg.method);
    siz     = size(dat);
    siz(1)  = ntissue;
    tmp     = nan(siz);
    ft_progress('init', cfg.feedback, 'computing parcellation');
    for j=1:numel(tissuelabel)
      ft_progress(j/numel(tissuelabel), 'computing parcellation for %s', tissuelabel{j});
      switch cfg.method
        case 'mean'
          tmp(j,:) = arraymean1(dat(tissue==j,:));
        case 'mean_thresholded'
          cfg.mean = ft_getopt(cfg, 'mean', struct('threshold', []));
          if isempty(cfg.mean.threshold)
            ft_error('when cfg.method = ''mean_thresholded'', you should specify a cfg.mean.threshold');
          end
          if numel(cfg.mean.threshold)==size(dat,1)
            % assume one threshold per vertex
            threshold = cfg.mean.threshold(tissue==j,:);
          else
            threshold = cfg.mean.threshold;
          end
          tmp(j,:) = arraymean1(dat(tissue==j,:), threshold);
        case 'median'
          tmp(j,:) = arraymedian1(dat(tissue==j,:));
        case 'min'
          tmp(j,:) = arraymin1(dat(tissue==j,:));
        case 'max'
          tmp(j,:) = arraymax1(dat(tissue==j,:));
        case 'maxabs'
          tmp(j,:) = arraymaxabs1(dat(tissue==j,:));
        case 'eig'
          tmp(j,:) = arrayeig1(dat(tissue==j,:));
        case 'std'
          tmp(j,:)  = arraystd1(dat(tissue==j,:));
        otherwise
          ft_error('method %s not implemented for %s', cfg.method, dimord{i});
      end % switch
    end % for
    ft_progress('close');

  else
    ft_error('unsupported dimord %s', dimord{i})

  end % if pos, pos_pos, {pos}, etc.

  % update the dimord, use chan rather than pos
  % this makes it look just like timelock or freq data
  tok = tokenize(dimord{i}, '_');
  tok(strcmp(tok,  'pos' )) = {'chan'}; % replace pos by chan
  tok(strcmp(tok, '{pos}')) = {'chan'}; % replace pos by chan
  tok(strcmp(tok, '{pos'))  = {'chan'}; % replace pos by chan
  tok(strcmp(tok, 'pos}'))  = {'chan'}; % replace pos by chan

  % squeeze out any singleton oris
  siz  = [size(tmp) 1]; % add trailing singleton to be sure
  oris = contains(tok, 'ori') & siz(1:numel(tok))==1;
  siz(oris) = [];
  tmp = reshape(tmp, siz);
  tok(oris) = [];

  tmpdimord = sprintf('%s_', tok{:});
  tmpdimord = tmpdimord(1:end-1);         % exclude the last _

  % store the results in the output structure
  parcel.(fn{i})            = tmp;
  parcel.([fn{i} 'dimord']) = tmpdimord;

  % to avoid confusion
  clear dat tmp tmpdimord j j1 j2
end % for each of the fields that should be parcellated

% a brainordinate is a brain location that is specified by either a surface vertex (node) or a volume voxel
parcel.brainordinate = keepfields(parcellation, {'pos', 'tri', 'dim', 'transform'}); % keep the information about the geometry
fn = fieldnames(parcellation);
for i=1:numel(fn)
  if isfield(parcellation, [fn{i} 'label'])
    % keep each of the labeled fields from the parcellation
    parcel.brainordinate.( fn{i}         ) = parcellation.( fn{i}         );
    parcel.brainordinate.([fn{i} 'label']) = parcellation.([fn{i} 'label']);
  end
end

% do the general cleanup and bookkeeping at the end of the function
ft_postamble debug
ft_postamble previous   source parcellation
ft_postamble provenance parcel
ft_postamble history    parcel
ft_postamble savevar    parcel

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTIONS to compute something over the first dimension
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = arraymean1(x, threshold)

if nargin==1
  y = mean(x,1);
else
  if numel(threshold)==1
    % scalar comparison is possible
  elseif size(threshold,1) == size(x,1)
    % assume threshold to be column vector
    threshold = repmat(threshold, [1, size(x,2)]);
  end
  sel = sum(x>threshold,2);
  if ~isempty(sel)
    y = mean(x(sel>0,:),1);
  else
    y = nan+zeros(1,size(x,2));
  end
end

function y = arraymedian1(x)
if ~isempty(x)
  y = median(x,1);
else
  y = nan(1,size(x,2));
end

function y = arraymin1(x)
if ~isempty(x)
  y = min(x,[], 1);
else
  y = nan(1,size(x,2));
end

function y = arraymax1(x)
if ~isempty(x)
  y = max(x,[], 1);
else
  y = nan(1,size(x,2));
end

function y = arrayeig1(x)
if ~isempty(x)
  siz = size(x);
  x = reshape(x, siz(1), prod(siz(2:end)));
  [u, s, v] = svds(x, 1);         % x = u * s * v'
  y = s(1,1) * v(:,1);            % retain the largest eigenvector with appropriate scaling
  y = reshape(y, [siz(2:end) 1]); % size should have at least two elements
else
  siz = size(x);
  y   = nan([siz(2:end) 1]);
end

function y = arraymaxabs1(x)
if ~isempty(x)
  % take the value that is at max(abs(x))
  [dum,ix] = max(abs(x), [], 1);
  y        = x(ix);
else
  y = nan(1,size(x,2));
end

function y = arraystd1(x)
if ~isempty(x)
  y = std(x,0, 1);
else
  y = nan(1,size(x, 2));
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTIONS to compute something over the first two dimensions
% all of these functions should be implemented the same
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = arraymean2(x)
siz = size(x);
x = reshape(x, [siz(1)*siz(2) siz(3:end) 1]); % simplify it into a single dimension
y = arraymean1(x);

function y = arraymedian2(x)
siz = size(x);
x = reshape(x, [siz(1)*siz(2) siz(3:end) 1]); % simplify it into a single dimension
y = arraymedian1(x);

function y = arraymin2(x)
siz = size(x);
x = reshape(x, [siz(1)*siz(2) siz(3:end) 1]); % simplify it into a single dimension
y = arraymin1(x);

function y = arraymax2(x)
siz = size(x);
x = reshape(x, [siz(1)*siz(2) siz(3:end) 1]); % simplify it into a single dimension
y = arraymax1(x);

function y = arrayeig2(x)
siz = size(x);
x = reshape(x, [siz(1)*siz(2) siz(3:end) 1]); % simplify it into a single dimension
y = arrayeig1(x);

function y = arraymaxabs2(x)
siz = size(x);
x = reshape(x, [siz(1)*siz(2) siz(3:end) 1]); % simplify it into a single dimension
y = arraymaxabs1(x);

function y = arraystd2(x)
siz = size(x);
x = reshape(x, [siz(1)*siz(2) siz(3:end) 1]); % simplify it into a single dimension
y = arraystd1(x);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTIONS for doing something over all elements of a cell-array
% add a singleton dimension, concatenate into an array, and do the computatioon
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = cellmean(x)
siz = size(x{1});
for i=1:numel(x)
  x{i} = reshape(x{i}, [1 siz]);
end
x = cat(1, x{:});
y = arraymean1(x);

function y = cellmedian(x)
siz = size(x{1});
for i=1:numel(x)
  x{i} = reshape(x{i}, [1 siz]);
end
x = cat(1, x{:});
y = arraymedian1(x);

function y = cellmin(x)
siz = size(x{1});
for i=1:numel(x)
  x{i} = reshape(x{i}, [1 siz]);
end
x = cat(1, x{:});
y = arraymin1(x);

function y = cellmax(x)
siz = size(x{1});
for i=1:numel(x)
  x{i} = reshape(x{i}, [1 siz]);
end
x = cat(1, x{:});
y = arraymax1(x);

function y = celleig(x)
siz = size(x{1});
for i=1:numel(x)
  x{i} = reshape(x{i}, [1 siz]);
end
x = cat(1, x{:});
y = arrayeig1(x);

function y = cellstd(x)
siz = size(x{1});
for i=1:numel(x)
  x{i} = reshape(x{i}, [1 siz]);
end
x = cat(1, x{:});
y = arraystd1(x);


% This script assumes that the variables under interest of analysis are:
%
% 1) SAVED FROM SIMULINK as STRUCTURE WITH TIME format;
%
% 2) contains the suffix "_DATA" in the name.
%
% Then, the script reads the workspace (or loads a .mat file), looks for
% these variables and allows the user to choose which variable to plot.
%
%

%% DATA TO LOAD (comment if data are in the workspace)
% load('EXAMPLE.mat')

%% SETUP VISUALIZER
close all
clc

addpath('./src_plot')

%%utility variables

% labels and font size
xAxisLabel  = 'Time [s]';
lineSize    = 2;

% print figures to .png
printFigure = false;

% dock all figures together
dockFigures = true;

% desired init and end time in the figures [s]
timeInit    = 0;
timeLimit   = 120;

if dockFigures

    set(0,'DefaultFigureWindowStyle','docked')
else
    set(0,'DefaultFigureWindowStyle','normal')
end

%% Get dataset from workspace
dataVariables = whos('*DATA');
plotList      = {};

for k = 1:length(dataVariables)

    plotList{k} = dataVariables(k).name; %#ok<SAGROW>
end

[plotNumber, ~] = listdlg('PromptString',  'Choose the variables to plot:', ...
                          'ListString',     plotList, ...
                          'SelectionMode', 'multiple', ...
                          'ListSize',       [250 150]);

% regenerate the plot list with the data selected by user
plotList = plotList(plotNumber);

%% Select which time to use for the plot (if Yarp time is available)
timeList = {'simulink time'};

if exist('time_Yarp','var')

    timeList{2} = 'yarp time';
end

if length(timeList) > 1

   [timeNumber, ~] = listdlg('PromptString',  'Choose the time vector to use:', ...
                             'ListString',     timeList, ...
                             'SelectionMode', 'single', ...
                             'ListSize',       [250 150]);
else
    timeNumber = 1;
end

%% Process data to plot
figNumber = 0;

for k = 1:length(plotList)

    currentData = eval(plotList{k});

    if timeNumber == 1

        time = currentData.time;

    elseif timeNumber == 2

        time = time_Yarp.signals.values;
    end

    % get the user defined time length
    timeLimitIndex = sum(time <= timeLimit);
    timeInitIndex  = sum(time <= timeInit);
    tVector        = time(timeInitIndex:timeLimitIndex);

    dataStructure  = currentData.signals;
    figNumber      = figNumber + 1;

    for kk = 1:length(currentData.signals)

        valuesToPlot = squeeze(currentData.signals(kk).values);

        % twist data dimensions if necessary
        if size(valuesToPlot,1) < length(time)

            valuesToPlot = valuesToPlot';
        end

        valuesToPlot = valuesToPlot(timeInitIndex:timeLimitIndex,:);
        yAxisLabel   = currentData.signals(kk).label;

        if kk == 1

            titleLabel = plotList{k}(1:end-5);
        else
            titleLabel = '';
        end

        figure(figNumber)
        subplot(length(currentData.signals),1,kk)
        custom_plot(tVector, valuesToPlot, xAxisLabel, yAxisLabel, titleLabel, ...
                    lineSize, '', figNumber, printFigure, 0);
    end
end

rmpath('./src_plot')


function D = driving_function_mono_wfs_vss(x0,xv,srcv,Dv,f,conf)
%DRIVING_FUNCTION_MONO_WFS_VSS driving signal for a given set of virtual
%secondary sources and their driving signals
%
%   Usage: D = driving_function_mono_wfs_vss(x0,xv,srcv,Dv,f,conf)
%
%   Input parameters:
%       x0          - position, direction, and weights of the real secondary
%                     sources / m [nx7]
%       xv          - position, direction, and weights of the virtual secondary
%                     sources / m [mx7]
%       srcv        - type of virtual secondary sources [mx7]
%                         'pw' - plane wave (xv(:,1:3) defines the direction of
%                                the plane waves in this case)
%                         'fs' - focused source (xv(:,1:6) defines the position
%                                and orientation of the focused sources in this
%                                case)
%       Dv          - driving functions of virtual secondary sources [mx1]
%       f           - frequency / Hz
%       conf        - optional configuration struct (see SFS_config)
%
%   Output parameters:
%       D           - driving function [nx1]
%
%   See also: driving_function_mono_wfs, driving_function_mono_wfs_fs
%
%   References:
%       Spors and Ahrens (2010) - "Local Sound Field Synthesis by Virtual
%       Secondary Sources", in 40th Conference of the Audio Engineering Society,
%       Paper 6-3, http://www.aes.org/e-lib/browse.cfm?elib=15561

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Checking of input  parameters ==================================
nargmin = 6;
nargmax = 6;
narginchk(nargmin,nargmax);
isargvector(Dv);
isargpositivescalar(f);
isargchar(srcv);
isargsecondarysource(x0,xv);
isargstruct(conf);

%% ===== Configuration ==================================================
dimension = conf.dimension;

%% ===== Computation ====================================================
% Secondary source selection and driving function to synthesise a single virtual
% secondary source
switch srcv
case 'fs'
    ssd_select = @(X0,XS) secondary_source_selection(X0,XS(1:6),'fs');
    driv = @(X0,XS) driving_function_mono_wfs_fs(X0(:,1:3),X0(:,4:6),XS,f,conf);

    if strcmp('2.5D',dimension) || strcmp('3D',dimension)
        % === Focussed Point Sink ===
        conf.driving_functions = 'default';
    elseif strcmp('2D',dimension)
        % === Focussed Line Sink ===
        % We have to use the driving function setting directly, because in
        % opposite to the case of a non-focused source where 'ps' and 'ls' are
        % available as source types, for a focused source only 'fs' is
        % available. Have a look at driving_function_mono_wfs_fs() for details
        % on the implemented focused source types.
        conf.driving_functions = 'line_sink';
    else
        error('%s: %s is not a known source type.',upper(mfilename),dimension);
    end
case 'pw'
    ssd_select = @(X0,XS) secondary_source_selection(X0,XS(1:3),'pw');
    driv = @(X0,XS) driving_function_mono_wfs_pw(X0(:,1:3),X0(:,4:6),XS,f,conf);
end

% Get driving signals
Nv = size(xv,1);
N0 = size(x0,1);
Dmatrix = zeros(N0,Nv);

% it's ok to have zero secondary sources selected for pwd
warning('off','SFS:x0');
for idx=1:Nv
    [x0s, xdx] = ssd_select(x0,xv(idx,:));
    if (~isempty(x0s))
        % Virtual secondary source position
        xs = repmat(xv(idx,1:3),[size(x0s,1) 1]);
        % Optional tapering
        wtap = tapering_window(x0s,conf);
        Dmatrix(xdx,idx) = driv(x0s,xs) .* wtap;
    end
end
warning('on','SFS:x0');

D = Dmatrix*(Dv(:).*xv(:,7));


function view_stressmap(bvg) % autogenerated function wrapper
    % Script: view_stressmap.m
    % Author: S. Wiemer
    % last update: 19.05.2005, j.woessner@sed.ethz.ch
    % turned into function by Celso G Reyes 2017

    ZG=ZmapGlobal.Data; % used by get_zmap_globals
    report_this_filefun(mfilename('fullpath'));

    SA = 1;
    SA2 = 3;
    % Matrix bvg contains:
    % bvg : [S1Trend S1Plunge S2Trend S2Plunge S3Trend S3Plunge Variance Radius b-value]
    % ste : [S1Plunge S1Trend+180 S2Plunge S2Trend+180 S3Plunge S3Trend+180 Variance];
    ste = [bvg(:,2) bvg(:,1)+180  bvg(:,4) bvg(:,3)+180 bvg(:,6) bvg(:,5)+180 bvg(:,7) ];
    sor = ste;
    ste2 = s;
    % sor : [S1Plunge S1Trend+270 S2Plunge S2Trend+180 S3Plunge S3Trend+180 Variance];
    sor(:,SA*2) = sor(:,SA*2)+90;

    % Create matrices
    normlap2=NaN(length(tmpgri(:,1)),1);

    re3=reshape(normlap2,length(yvect),length(xvect));
    s11 = re3;

    normlap2(ll)= bvg(:,8);
    rama=reshape(normlap2,length(yvect),length(xvect));

    normlap2(ll)= bvg(:,7);
    r=reshape(normlap2,length(yvect),length(xvect));

    normlap2(ll)= bvg(:,1);
    s11=reshape(normlap2,length(yvect),length(xvect));

    normlap2(ll)= bvg(:,4);
    s31=reshape(normlap2,length(yvect),length(xvect));

    normlap2(ll)= bvg(:,2);
    s12=reshape(normlap2,length(yvect),length(xvect));

    %old1 = re3;

    % Create figure
    figure_w_normalized_uicontrolunits('visible','off')
    l_normal =  ste(:,1) > 52 &   ste(:,5) < 35 ;
    l_notnormal = l_normal < 1;

    plq = quiver(newgri(l_notnormal,1),newgri(l_notnormal,2),-cos(sor(l_notnormal,SA*2)*pi/180),sin(sor(l_notnormal,SA*2)*pi/180),0.6,'.');
    set(plq,'LineWidth',0.5,'Color','k')
    px = get(plq,'Xdata');
    py = get(plq,'Ydata');

    close

    figure_w_normalized_uicontrolunits('visible','off')

    plq_n = quiver(newgri(l_normal,1),newgri(l_normal,2),-cos(sor(l_normal,SA2*2)*pi/180),sin(sor(l_normal,SA2*2)*pi/180),0.6,'.');
    set(plq_n,'LineWidth',0.5,'Color','r')

    drawnow
    px_n = get(plq_n,'Xdata');
    py_n = get(plq_n,'Ydata');
    close

    figure_w_normalized_uicontrolunits('Name','Faulting style map','pos',[100 100 860 600])
    watchon;
    %whitebg(gcf);
    set(gcf,'color','w');
    axes('pos',[0.12 0.12 0.8 0.8]);
    hold on
    n = 0;
    l0 = []; l1 = []; l2 = []; l3 = []; l4 = []; l5 = [];

    ste = sor(l_notnormal,:);
    for i = 1:3:length(px)-1
        n = n+1;j = jet;
        col = floor(ste(n,SA*2-1)/60*62)+1;
        if col > 64 ; col = 64; end
        pl = plot(px(i:i+1),py(i:i+1),'k','Linewidth',1.,'Markersize',1,'color',[ 0 0 0  ] );
        hold on

        dx = px(i)-px(i+1);
        dy = py(i) - py(i+1);
        pl2 = plot(px(i),py(i),'ko','Markersize',0.1,'Linewidth',0.5,'color',[0 0 0] );
        l0 = pl2;
        pl3 = plot([px(i) px(i)+dx],[py(i) py(i)+dy],'k','Linewidth',1.,'color',[0 0 0] );
        % Select faulting style according to Zoback(1992)
        if ste(n,1) < 40  && ste(n,3) > 45  && ste(n,5) < 20 ; set([pl pl3],'color',[0.2 0.8 0.2]); set(pl2,'color',[0.2 0.8 0.2]); l3 = pl; end
        if ste(n,1) < 20  && ste(n,3) > 45  && ste(n,5) < 40 ;  set([pl pl3],'color',[0.2 0.8 0.2]); set(pl2,'color',[0.2 0.8 0.2]);l3 = pl; end
        if ste(n,1) > 40  &&                 ste(n,1) < 52  && ste(n,5) < 20 ;  set([pl pl3],'color','m'); set(pl2,'color','m'); l2 = pl; end
        if ste(n,1) < 20  &&                 ste(n,5) > 40  &&  ste(n,5) <  52 ; set([pl pl3],'color','c'); set(pl2,'color','c');l4 = pl; end
        if ste(n,1) < 37  && ste(n,5) > 47  ; set([pl pl3],'color','b'); set(pl2,'color','b');l5 = pl;  end

    end
    %drawnow
    ste = sor(l_normal,:);
    n = 0;

    for i = 1:3:length(px_n)-1
        n = n+1;j = jet;
        col = floor(ste(n,SA*2-1)/60*62)+1;
        if col > 64 ; col = 64; end
        dx_n = px_n(i)-px_n(i+1);
        dy_n= py_n(i) - py_n(i+1);
        pl_n = plot(px_n(i:i+1),py_n(i:i+1),'k','Linewidth',1.,'Markersize',1,'color',[ 0 0 0  ] );
        hold on
        dx = px_n(i)- px_n(i+1);
        dy = py_n(i) - py_n(i+1);
        pl2_n = plot(px_n(i),py_n(i),'ko','Markersize',0.1,'Linewidth',0.5,'color',[0 0 0] );
        l0 = pl2;
        pl3_n = plot([px_n(i) px_n(i)+dx_n],[py_n(i) py_n(i)+dy_n],'k','Linewidth',1.,'color',[0 0 0] );

        if ste(n,1) > 52  &&                 ste(n,5) < 35 ;                 set([pl_n pl3_n],'color','r'); set(pl2_n,'color','r'); l1 = pl_n;
        end
    end

    if isempty(l1); pl2 = plot(px,py,'kx','Linewidth',1.,'color','r'); l1 = pl2; set(l1,'visible','off'); end
    if isempty(l2); pl2 = plot(px,py,'kx','Linewidth',1.,'color','m'); l2 = pl2; set(l2,'visible','off'); end
    if isempty(l3); pl2 = plot(px,py,'kx','Linewidth',1.,'color',[0.2 0.8 0.2] ); l3 = pl2; set(l3,'visible','off'); end
    if isempty(l4); pl2 = plot(px,py,'kx','Linewidth',1.,'color','c' ); l4 = pl2; set(l4,'visible','off'); end
    if isempty(l5); pl2 = plot(px,py,'kx','Linewidth',1.,'color','b' ); l5 = pl2; set(l5,'visible','off'); end
    if isempty(l0); l0 = plot(px,py,'kx','Linewidth',1.,'color',[0 0 0 ] );  set(l0,'visible','off'); end

    try
        legend([l1 l2 l3 l4 l5 l0],'NF','NS','SS','TS','TF','U');
    catch
        disp('Legend could not be drawn')
    end

    % Figure settings
    hold on
    axis('equal')
    update(mainmap())
    set(gca,'aspectratio',[0.827 1])
    axis([ s2_west s1_east s4_south s3_north])
    title([name ';  '   num2str(t0b) ' to ' num2str(teb) ],'FontSize',ZmapGlobal.Data.fontsz.s,...
        'Color','k','FontWeight','normal');
    mygca = gca;
    xlabel('Longitude ','FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s)
    ylabel('Latitude ','FontWeight','normal','FontSize',ZmapGlobal.Data.fontsz.s)
    set(gca,'visible','on','FontSize',ZmapGlobal.Data.fontsz.s,'FontWeight','normal',...
        'FontWeight','normal','LineWidth',1.,...
        'Box','on','TickDir','out','Ticklength',[0.01 0.01])

    watchoff;

    % View the variance map
    re3 = r;sha = 'in';
    view_varmap([],re3);

end


classdef QuadPlot < handle
    %QUADPLOT Visualization class for quad

    properties (SetAccess = public)
        k = 0;
        qn;             % quad number
        time = 0;       % time
        state;          % state
        des_state;      % desried state [x; y; z; xdot; ydot; zdot];
        rot;            % rotation matrix body to world

        color;          % color of quad
        wingspan;       % wingspan
        height;         % height of quad
        motor;          % motor position

        state_hist        % position history
        state_des_hist;   % desired position history
        time_hist;      % time history
        max_iter;       % max iteration
    end

    properties (SetAccess = private)
        h_3d
        h_m13;  % motor 1 and 3 handle
        h_m24;  % motor 2 and 4 handle
        h_qz;   % z axis of quad handle
        h_qn;   % quad number handle
        h_pos_hist;     % position history handle
        h_pos_des_hist; % desired position history handle
        text_dist;  % distance of quad number to quad
    end

    methods
        % Constructor
        function Q = QuadPlot(qn, state, wingspan, height, color, max_iter, h_3d)
            Q.qn = qn;
            Q.state = state;
            Q.wingspan = wingspan;
            Q.color = color;
            Q.height = height;
            Q.rot = QuatToRot(Q.state(7:10));
            Q.motor = quad_pos(Q.state(1:3), Q.rot, Q.wingspan, Q.height);
            Q.text_dist = Q.wingspan / 3;
            Q.des_state = Q.state(1:6);

            Q.max_iter = max_iter;
            Q.state_hist = zeros(6, max_iter);
            Q.state_des_hist = zeros(6, max_iter);
            Q.time_hist = zeros(1, max_iter);

            % Initialize plot handle
            if nargin < 7, h_3d = gca; end
            Q.h_3d = h_3d;
            hold(Q.h_3d, 'on')
            Q.h_pos_hist = plot3(Q.h_3d, Q.state(1), Q.state(2), Q.state(3), 'r.');
            Q.h_pos_des_hist = plot3(Q.h_3d, Q.des_state(1), Q.des_state(2), Q.des_state(3), 'b.');
            Q.h_m13 = plot3(Q.h_3d, ...
                Q.motor(1,[1 3]), ...
                Q.motor(2,[1 3]), ...
                Q.motor(3,[1 3]), ...
                '-ko', 'MarkerFaceColor', Q.color, 'MarkerSize', 5);
            Q.h_m24 = plot3(Q.h_3d, ...
                Q.motor(1,[2 4]), ...
                Q.motor(2,[2 4]), ...
                Q.motor(3,[2 4]), ...
                '-ko', 'MarkerFaceColor', Q.color, 'MarkerSize', 5);
            Q.h_qz = plot3(Q.h_3d, ...
                Q.motor(1,[5 6]), ...
                Q.motor(2,[5 6]), ...
                Q.motor(3,[5 6]), ...
                'Color', Q.color, 'LineWidth', 2);
            Q.h_qn = text(...
                Q.motor(1,5) + Q.text_dist, ...
                Q.motor(2,5) + Q.text_dist, ...
                Q.motor(3,5) + Q.text_dist, num2str(qn));
            hold(Q.h_3d, 'off')
        end

        % Update quad state
        function UpdateQuadState(Q, state, time)
            Q.state = state;
            Q.time = time;
            Q.rot = QuatToRot(state(7:10))'; % Q.rot needs to be body-to-world
        end

        % Update desired quad state
        function UpdateDesiredQuadState(Q, des_state)
            Q.des_state = des_state;
        end

        % Update quad history
        function UpdateQuadHist(Q)
            Q.k = Q.k + 1;
            Q.time_hist(Q.k) = Q.time;
            Q.state_hist(:,Q.k) = Q.state(1:6);
            Q.state_des_hist(:,Q.k) = Q.des_state(1:6);
        end

        % Update motor position
        function UpdateMotorPos(Q)
            Q.motor = quad_pos(Q.state(1:3), Q.rot, Q.wingspan, Q.height);
        end

        % Truncate history
        function TruncateHist(Q)
            Q.time_hist = Q.time_hist(1:Q.k);
            Q.state_hist = Q.state_hist(:, 1:Q.k);
            Q.state_des_hist = Q.state_des_hist(:, 1:Q.k);
        end

        % Update quad plot
        function UpdateQuadPlot(Q, state, des_state, time)
            Q.UpdateQuadState(state, time);
            Q.UpdateDesiredQuadState(des_state);
            Q.UpdateQuadHist();
            Q.UpdateMotorPos();
            set(Q.h_m13, ...
                'XData', Q.motor(1,[1 3]), ...
                'YData', Q.motor(2,[1 3]), ...
                'ZData', Q.motor(3,[1 3]));
            set(Q.h_m24, ...
                'XData', Q.motor(1,[2 4]), ...
                'YData', Q.motor(2,[2 4]), ...
                'ZData', Q.motor(3,[2 4]));
            set(Q.h_qz, ...
                'XData', Q.motor(1,[5 6]), ...
                'YData', Q.motor(2,[5 6]), ...
                'ZData', Q.motor(3,[5 6]))
            set(Q.h_qn, 'Position', ...
                [Q.motor(1,5) + Q.text_dist, ...
                Q.motor(2,5) + Q.text_dist, ...
                Q.motor(3,5) + Q.text_dist]);
            set(Q.h_pos_hist, ...
                'XData', Q.state_hist(1,1:Q.k), ...
                'YData', Q.state_hist(2,1:Q.k), ...
                'ZData', Q.state_hist(3,1:Q.k));
            set(Q.h_pos_des_hist, ...
                'XData', Q.state_des_hist(1,1:Q.k), ...
                'YData', Q.state_des_hist(2,1:Q.k), ...
                'ZData', Q.state_des_hist(3,1:Q.k));
            drawnow;
        end
    end

end


% The COBRA Toolbox: testFluxSplits.m
%
% Purpose:
%     - tests the predictFluxSplits function
%
% Authors:
%     - Original file: Hulda Haraldsdottir
%     - CI integration: Laurent Heirendt January 2017
%
% Note:
%     - This test only runs with solvers that can solve LP and QP problems

% save the current path
currentDir = pwd;

% initialize the test
fileDir = fileparts(which('testFluxSplits'));
cd(fileDir);

% define a toy model with single internal loop
model.mets = {'A'; 'B'; 'C'};
model.rxns = {'R1'; 'R2'; 'R3'; 'U'; 'S'};
model.S = [-1  0 -1 -1  0;
            1 -1  0  0  0;
            0  1  1  0 -1];
model.b = [0; 0; 0];
model.lb = [-1000; -1000; -1000; -10; 0];
model.ub = [1000; 1000; 1000; 0; 10];
model.c = [0; 0; 0; 0; 1];

% define inputs
obj = 'S';
met2test = {'C'};
samples = {'model'};
ResultsAllCellLines.model.modelPruned = model;

% define parameteres for tests
tol = 1e-6;
v_ref = [10/3; 10/3; 20/3; -10; 10]; % reference flux distribution

% list of solver packages
solverPkgs = {'tomlab_cplex', 'gurobi'};

for k = 1:length(solverPkgs)

    fprintf(' -- Running testFluxSplits using the solver interface: %s ... ', solverPkgs{k});

    s1 = changeCobraSolver(solverPkgs{k}, 'LP', 0);
    s2 = changeCobraSolver(solverPkgs{k}, 'QP', 0);

    if s1 == 1 && s2 == 1
        % Test of production
        p.rxn = {'R3'}; % max contributing reaction
        p.flux = [20/3, 10, 200/3]; % contributing fluxes
        [BMall, ResultsAllCellLines, ~, maximum_contributing_rxn, maximum_contributing_flux, ~] = predictFluxSplits(model, obj, met2test, samples, ResultsAllCellLines, 1);

        assert(norm(BMall - v_ref) < tol);
        assert(strcmp(maximum_contributing_rxn,p.rxn));
        assert(norm(maximum_contributing_flux - p.flux) < tol);

        % Test of consumption
        c.rxn = {'S'}; % max contributing reaction
        c.flux = [10, 10, 100]; % contributing fluxes
        [BMall, ResultsAllCellLines, ~, maximum_contributing_rxn, maximum_contributing_flux, ~] = predictFluxSplits(model, obj, met2test, samples, ResultsAllCellLines, 0);

        assert(norm(BMall - v_ref) < tol);
        assert(strcmp(maximum_contributing_rxn,c.rxn));
        assert(norm(maximum_contributing_flux - c.flux) < tol);

        % set a status message
        fprintf('Done.\n');
    else
        warning('The test testFluxSplits cannot run using the solver interface: %s. The solver interface is not installed or not configured properly.\n', solverPkgs{k});
    end
end

% change the directory
cd(currentDir)


% main script to launch the estimation
% of the non-linear parameters by using the CalTech
% calibration toolbox and the output from the Svoboda's
% Multicamera self-calibration
%
% How to create the input data:
% 1) Run the MultiCamSelfCam
% 2) Run the MultiCamValidation
%
% $Id: gorad.m,v 2.0 2003/06/19 12:06:00 svoboda Exp $

clear all;

% TODO: isn't this unnecessary now?
addpath ../MultiCamSelfCalib/Cfg

% Read configuration from whatever is specified on command-line (via --config=FILENAME)
config = read_configuration();

% if problem with desactivated images -> some problems with the estimation in general
desactivated_images = [];

idxcams = config.cal.cams2use;
selfcalib.goradproblem = 0;

for i = idxcams,
  [X_1,x_1] = preparedata(sprintf(config.files.points4cal,i));
  go_calib_optim_iter
  if any(isnan(param))
	  % when the iteration fails insert null distortion
	  % it is better than nonsense
	  kc(1:4) = [0,0,0,0];
	  selfcalib.goradproblem=1;
  else
	  visualize_distortions
  end

  disp(sprintf('***** camera %d **********************************',i))
  %
  outputfile = sprintf(config.files.rad,i);

     fprintf(1,'\nExport of intrinsic calibration data to blue-c configuration file\n');
     % outputfile = input('File basename: ', 's');
     configfile = outputfile;
     disp(['Writing ' configfile]);

     fid = fopen(configfile, 'w');

     fprintf(fid, 'K11 = %.16f\n', KK(1,1));
     fprintf(fid, 'K12 = %.16f\n', KK(1,2));
     fprintf(fid, 'K13 = %.16f\n', KK(1,3));
     fprintf(fid, 'K21 = %.16f\n', KK(2,1));
     fprintf(fid, 'K22 = %.16f\n', KK(2,2));
     fprintf(fid, 'K23 = %.16f\n', KK(2,3));
     fprintf(fid, 'K31 = %.16f\n', KK(3,1));
     fprintf(fid, 'K32 = %.16f\n', KK(3,2));
     fprintf(fid, 'K33 = %.16f\n\n', KK(3,3));

     fprintf(fid, 'kc1 = %.16f\n', kc(1));
     fprintf(fid, 'kc2 = %.16f\n', kc(2));
     fprintf(fid, 'kc3 = %.16f\n', kc(3));
     fprintf(fid, 'kc4 = %.16f\n', kc(4));

     status = fclose(fid);

disp('Press any key to continue'),  pause

%%%
% clear already estimated parameters
clear fc kc alpha_c cc
end


function SO3F = log(SO3F)
% overloads |log(SO3F)|
%
% Syntax
%   SO3F = log(SO3F)
%
% Input
%  SO3F - @SO3Fun
%
% Output
%  SO3F - @SO3Fun
%

SO3F = SO3FunHandle(@(rot) log(SO3F.eval(rot)),SO3F.SRight,SO3F.SLeft);

end


%GOBJ_REVOLVE Revolve face/geometry object.
%
%   [ GOBJ, STAT ] = GOBJ_REVOLVE( GOBJ, TH, P, V, PIT, FACE_WPL )
%   Revolve geometry object or face from GOBJ a an angle TH (degrees)
%   around axis defined by point P and direction vector V. PIT is
%   optionally the pitch (distance per revolution) to offset the
%   revolution in the axial direction (to form a coil/helix).
%   FACE_WPL can in 3D indicate a face to extrude or in 2D is a
%   workplane struct defined by (p, n, t).

% Copyright 2013-2022 Precise Simulation, Ltd.


function wfa = sst2wfa(sst,w)
%
%SST2WFA: Convert events from SST form to WFA form.
%      WFA - WaveForm Array form, events separated in nx1 waveform array
%          - (or) into 1xl cell array, each cell containing a nx1 waveform
%          - array of events from a separate station/channel.
%      NAN - NaN form, (1xl waveform) for l station/channels with events in
%            one time series w/ non-events = NaN.
%      SST - Start/Stop Times form, nx2 array of matlab start/stop times
%            (or) 1xl cell array, each cell containing nx2 start/stop
%            times from a separate station/channel.
%
%USAGE: wfa = sst2wfa(sst)
%
%INPUTS: w    - Waveform object that contains events
%        sst  - Events (WFA form)
%
%OUTPUTS: wfa - Events (WFA form)
%
% See also NAN2SST, NAN2WFA, SSD2SST, SST2NAN, SST2SSD, SST2VAL,
%          WFA2NAN, WFA2SST
%
% Author: Dane Ketner, Alaska Volcano Observatory
% $Date$
% $Revision$

if iscell(sst)
   if numel(sst) == numel(w)
      for l=1:numel(sst)
         for n=1:size(sst{l},1)
            wfa{l}(n) = extract(w,'time',sst{l}(n,1),sst{l}(n,2));
         end
      end
   else
      error(['sst2nan:ArgumentDimensions - Number of elements in',...
             ' waveform input ''w'' and cell input ''sst'' must match']);
   end
else
   for n=1:size(sst,1)
      wfa(n) = extract(w,'time',sst(n,1),sst(n,2));
   end
end


function detections = nmsProcess(det, isNMS, nmsThre)
if(isNMS)
    detections = [];
    numFr = max(det(:,1));
    for i = 1:numFr
        idx = det(:,1) == i;
        curdet = det(idx,:);
        pick = nms(curdet(:,3:7), nmsThre);
        detections = cat(1, detections, curdet(pick,:));
    end
else
    detections = det;
end


function im = imread_list(pathstr, file, TOGRAY)
% IMREAD_LIST  Read list of image files into volume.
%
% IMREAD_LIST reads a list of image files, converts them to grayscale if
% desired, and collates them to form a 3D or 4D image volume.
%
% IM = IMREAD_LIST(PATHSTR, FILE)
%
%   PATHSTR is a string with the path to the files. All images must be the
%   same size and have the same number of channels.
%
%   FILE is an array of structs obtained with dir().
%
%   IM is the resulting image volume with indices:
%
%     IM(rows, columns, slice, channel)
%
% IM = IMREAD_LIST(..., TOGRAY)
%
%   TOGRAY is a boolean to convert colour images to grayscale. By default,
%   TOGRAY='false'.

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2014 University of Oxford
% Version: 0.1.1
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see
% <http://www.gnu.org/licenses/>.

% check arguments
narginchk(2, 3);
nargoutchk(0, 1);

% defaults
if (nargin < 3 || isempty(TOGRAY))
    TOGRAY = false;
end

% number of files
N = length(file);

% no files to read
if (N == 0)
    im = [];
    return
end

% get number of rows and columns in the blockface volume, and whether
% images are colour. The easiest way is to just load the first image,
% instead of using imfinfo and then having to convert e.g. BitDepth to a
% Matlab class
im0 = imread([pathstr filesep file(1).name]);

% number of channels
nchan = size(im0, 3);

% initialize output volume
if (nchan == 1 || TOGRAY)
    im = zeros(size(im0, 1), size(im0, 2), N, class(im0));
else
    im = zeros(size(im0, 1), size(im0, 2), N, nchan, class(im0));
end
im(:, :, 1, :) = im0;

% loop image files
for I = 2:N

    % load image from file
    if (nchan == 1 || TOGRAY)
        im(:, :, I) = rgb2gray(imread([pathstr filesep file(I).name]));
    else
        im(:, :, I, :) = imread([pathstr filesep file(I).name]);
    end

end


function D = spm_eeg_correct_sensor_data(S)
% Remove artefacts from the data based on their topography
% FORMAT D = spm_eeg_correct_sensor_data(S)
%
% S      - input structure (optional)
% (optional) fields of S:
%   S.D    - MEEG object or filename of M/EEG mat-file
%   S.mode - 'SSP': simple projection
%          - 'Berg': the method of Berg (see the reference below)
% Output:
% D      - MEEG object (also written on disk)
%
% Implements:
%   Berg P, Scherg M.
%   A multiple source approach to the correction of eye artifacts.
%   Electroencephalogr Clin Neurophysiol. 1994 Mar;90(3):229-41.
%__________________________________________________________________________
% Copyright (C) 2008-2017 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak
% $Id: spm_eeg_correct_sensor_data.m 7701 2019-11-21 21:50:17Z vladimir $

SVNrev = '$Rev: 7701 $';

%-Startup
%--------------------------------------------------------------------------
spm('FnBanner', mfilename, SVNrev);
spm('FigName','Correct sensor data');

if ~isfield(S, 'mode') && isfield(S, 'correction'),  S.mode  = S.correction;  end
if ~isfield(S, 'prefix'),                            S.prefix   = 'T';        end

%-Get MEEG object
%--------------------------------------------------------------------------
D = spm_eeg_load(S.D);

inputfile = fullfile(D);

if ~any(D.sconfounds)
    D = spm_eeg_spatial_confounds(S);
    if ~any(D.sconfounds)
        return;
    end
end

[mod, list] = modality(D, 1, 1);

A = {};
if isequal(mod, 'Multimodal')
    sconf = getfield(D, 'sconfounds');

    for i = 1:numel(list)
        chanind = indchantype(D, list{i}, 'GOOD');
        [sel1, sel2] = spm_match_str(chanlabels(D, chanind), sconf.label);

        if any(sconf.bad(sel2))
            error(['Channels ' sprintf('%s ', sconf.label{sel2}) ' should be set to bad.']);
        end

        A{i} = sconf.coeff(sel2, :);
    end
else
    A = {D.sconfounds};
    list = {mod};
end

Dorig = D;

for i = 1:numel(A)
    label = D.chanlabels(indchantype(D, list{i}, 'GOOD'))';

    montage = [];
    montage.labelorg = label;
    montage.labelnew = label;

    montage.chantypeold = lower(D.chantype(D.indchannel(label)))';
    montage.chantypenew  = lower(montage.chantypeold);

    montage.chanunitold = D.units(D.indchannel(label))';
    montage.chanunitnew  = montage.chanunitold;

    if size(A{i}, 1)~=numel(label)
        error('Spatial confound vector does not match the channels.');
    end

    if isequal(lower(S.mode), 'berg')
        % These are the locations taken from the file BR_Brain Regions_LR.bsa
        % in BESA distribution, transformed to Tailarach coordinates using
        % BESA simulator and then to MNI template space using tal2icbm_spm
        % from http://brainmap.org/icbm2tal/
        sources = [
            -47.3124    6.4922  -10.3381
            -49.1870  -38.7590   -4.3574
            -35.2804   38.7888   21.0944
            -41.0574  -16.4018   46.0553
            -34.9993  -70.8348   20.8450
            0.8786   60.5733   -5.2797
            1.5716   38.5344   44.5853
            1.9792  -16.5380   65.3503
            1.8525  -71.0130   44.3363
            1.2689  -91.6233   -5.6259
            49.1987    6.8326  -12.0156
            51.4597  -38.4040   -6.1068
            37.8063   39.0466   19.8240
            44.5032  -16.1000   44.5681
            38.0874  -70.5770   19.5747
            ];

        [D, ok] = check(D, 'sensfid');

        if ~ok
            if check(D, 'basic')
                error(['The requested file is not ready for source reconstruction.'...
                    'Use prep to specify sensors and fiducials.']);
            else
                error('The meeg file is corrupt or incomplete');
            end
        end

        %-Find or prepare head model
        %==================================================================

        if ~isfield(D, 'val')
            D.val = 1;
        end

        if ~isfield(D, 'inv') || ~iscell(D.inv) ||...
                ~(isfield(D.inv{D.val}, 'forward') && isfield(D.inv{D.val}, 'datareg')) ||...
                ~isa(D.inv{D.val}.mesh.tess_ctx, 'char') % detects old version of the struct
            D = spm_eeg_inv_mesh_ui(D, D.val);
            D = spm_eeg_inv_datareg_ui(D, D.val);
            D = spm_eeg_inv_forward_ui(D, D.val);

            save(D);
        end

        fwd = spm_eeg_inv_get_vol_sens(D, D.val, 'MNI-aligned', 'inv', list{i});

        [vol, sens] = ft_prepare_vol_sens(fwd.(list{i}).vol, fwd.(list{i}).sens, 'channel', label);

        L = ft_compute_leadfield(spm_eeg_inv_transform_points(inv(fwd.transforms.toMNI), sources), sens, vol);
        %[L, D] = spm_eeg_lgainmat(D, [], label);

        B = spm_svd(L*L', 0.01);

        lim = min(0.5*size(L, 1), 45); % 45 is the number of dipoles BESA would use.

        if size(B, 2) > lim;
            B = B(:, 1:lim);
        end

        SX = full([A{i} B]);

        SXi = pinv(SX);
        SXi = SXi(1:size(A{i}, 2), :);

        montage.tra = eye(size(A{i}, 1)) - A{i}*SXi;
    else
        montage.tra = eye(size(A{i}, 1)) - A{i}*pinv(A{i});
    end

    S1   = [];
    S1.D = D;
    S1.montage = montage;
    S1.keepothers = true;
    S1.updatehistory  = false;

    Dnew = spm_eeg_montage(S1);

    if isfield(D,'inv')
        Dnew.inv = D.inv;
    end

    if i>1
        delete(D);
    end

    D = Dnew;
end

%-Change the channel order to the original order
%==========================================================================
tra = eye(D.nchannels);
montage = [];
montage.labelorg = D.chanlabels';
montage.labelnew = Dorig.chanlabels';

montage.chantypeold  = lower(D.chantype)';
montage.chantypenew  = lower(Dorig.chantype)';

montage.chanunitold  = D.units';
montage.chanunitnew  = Dorig.units';

[sel1, sel2]  = spm_match_str(montage.labelnew, montage.labelorg);

montage.tra = tra(sel2, :);

S1   = [];
S1.D = D;
S1.montage = montage;
S1.keepothers = true;
S1.updatehistory  = 0;

Dnew = spm_eeg_montage(S1);

delete(D);
D = Dnew;

if ~isempty(badchannels(Dorig))
    D = badchannels(D, badchannels(Dorig), 1);
end

D = D.history(mfilename, S);
save(D);

D = move(D, spm_file(inputfile, 'prefix', S.prefix));

%-Cleanup
%--------------------------------------------------------------------------
spm('FigName', 'Correct sensor data: done');


% Waveform synthesis for the Harmonic Model + Phase Distortion (HMPD)
%
% Octave compatible
%
% This the main entry point for synthesizing a waveform using HMPD parameters.
%
% Please read the README.txt file for general information about HMPD before
% using it.
%
% Inputs
%  f0s    : [s, Hz] [Nx2] A time/data column vector, containing the
%           fundamental frequency f0 values.
%  AE     : [NxD] A matrix containing the amplitude envelope.
%           D is either opt.dftlen/2+1 (from hmpd_features_compute.m), or
%           opt.amp_order+1, depending if compression is disabled or enabled.
%  PDM    : [NxD] A matrix containing the Phase Distortion Mean.
%           D is either opt.dftlen/2+1 or opt.pdm_order+1, depending if
%           compression is disabled or enabled.
%  PDD    : [NxD] A matrix containing the Phase Distortion Deviation.
%           D is either opt.dftlen/2+1 or opt.pdd_order+1, depending if
%           compression is disabled or enabled.
%  fs     : [Hz] The sampling rate of the waveform.
%           (It has to be the same as the one used during analysis)
% [wavlen]: Length of the synthesized waveform [in number of samples].
%           If this option is omited, it is predicted from the last time instant
%           of the f0s argument.
% [opt]   : Additional options for synthesis (see code below).
%           The option opt.enc has to contain absolutely the options used
%           during analysis.
%
% Outputs
%  syn   : The samples of the synthesized waveform
%  opt   : The options used during synthesis.
%
% Copyright (c) 2012 University of Crete - Computer Science Department (UOC-CSD)
%
% 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 function is part of the Covarep project: http://covarep.github.io/covarep
%
% Author
%  Gilles Degottex <degottex@csd.uoc.gr>
%

function [syn, opt] = hmpd_synthesis(f0s, AE, PDM, PDD, fs, wavlen, opt)

    if nargin<7
        % Options
        opt.enc = hmpd_analysis();
        opt.amp_minphasegain = 1; % 1:minimum-phase, 0:zero-phase, -1:max-phase
        opt.pd_gain = 1;
        opt.rps_randunvoiced = false; % Randomize the RPS in unvoiced segments
                                      % Unvoiced segments are indicated by
                                      % f0=0 values.
                                      % (not used by default with HMPD)
        opt.pdv_corrthresh = 0.75;    % PDD correction threshold

        opt.defdbamp = -300;  % [dB]
        opt.usemex   = false; % Use mex fn, faster but use linear interpolation
        opt.debug    = 1;
    end
    if nargin==0; syn=opt; return; end
    if nargin==1;
        syn = hmpd_synthesis();
        syn.enc = f0s;
        return;
    end

    if opt.debug>0; disp('HMPD Vocoder: Synthesis ...'); end
    if opt.debug>1; disp(opt); end

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

    if nargin<5 || isempty(fs);     fs=44100; end
    if nargin<6 || isempty(wavlen); wavlen=round(fs*f0s(end,1)); end

    unvoiced = f0s(:,2)==0; % Remember the unvoiced indices ...
    f0s = fillf0(f0s);      % ... and replace them with interpolated f0

    [AH, APH] = hmpd_amplitude_decompress(AE, f0s, fs, opt); % Amp decoding
    Hmax = size(AH,2)-1; % Max number of harmonics (without DC)

    % Reconstruct a Relative Phase Shift (RPS) of the voice source
    RPS = hmpd_phase_decompress(PDM, PDD, f0s, fs, opt); % Phase decoding

    % If asked, force full RPS randomization in unvoiced segments
    if opt.rps_randunvoiced
        if opt.debug>0; disp('    Randomize unvoiced segments (where f0=0)');end
        idx = find(unvoiced);
        RPS(idx,:) = wrap(2.*pi.*rand(length(idx),size(RPS,2)));
    end

    % Add the VTF phase
    RPS = wrap(opt.pd_gain*RPS + opt.amp_minphasegain*APH);

    if opt.debug>0; disp(['    HM synthesis (' num2str(Hmax) ' harmonics)']);end
    deflogamp = log(db2mag(opt.defdbamp));

    % Compute instantaneous fundamental frequency along the whole recording
    f1 = interp1(f0s(:,1), f0s(:,2), (0:wavlen-1)'/fs, 'linear');
    f1 = interp1_fixnan(f1)'; % Fix bounds
    p1 = filter(1, [1 -1], (2*pi/fs)*f1);

    syn = zeros(wavlen,1); % Allocate the synthetic signal
    % For each harmonic
    for h=1:Hmax % here h is the harmonic number

        % Synthesize only indices where the frequency doesn't go above Nyquist
        idxsyn = find(f1*h<fs/2);
        if length(idxsyn)==0; break; end
        synts = (idxsyn-1)/fs;

        % Amplitude ------------------------------------------------------------
        % Interpolate on a log scale
        Y = AH(:,1+h);
        if opt.usemex
            am = interp1ordered(f0s(:,1), Y, synts, deflogamp).';
        else
            am = interp1(f0s(:,1), Y, synts, 'linear', deflogamp);
        end

        % Phase ----------------------------------------------------------------
        % Interpolate on RPS domain
        Y = unwrap(RPS(:,1+h));
        if opt.usemex
            rpst = interp1ordered(f0s(:,1), Y, synts, 0).'; % Lose the splines !
        else
            rpst = interp1(f0s(:,1), Y, synts, 'spline');
        end
        % Instantaneous phase = linear phase + relative phase shift
        ph = h.*p1(idxsyn) + rpst;

        % Harmonic synthesis ---------------------------------------------------
        syn(idxsyn) = syn(idxsyn) + 2*exp(am).*cos(ph);
    end

return


function [eventLog] = ma_executeCoast_nBody_goto_dt(dt, initialState, eventNum, forceModel, considerSoITransitions, soiSkipIds, massLoss, maxPropTime, events, contOnSoITrans, celBodyData)
%ma_executeCoast_nBody_goto_dt Summary of this function goes here
%   Detailed explanation goes here
    if(dt < 0)
        errorStr = ['Cannot coast ', num2str(dt), ' seconds.  Reverse time error, skipping event (any revs prior to this event may still be executed).'];
        addToExecutionErrors(errorStr, eventNum, initialState(8), celBodyData);

        eventLog = initialState;
        eventLog(:,13) = eventNum;
        return;
    elseif(dt == 0)
        eventLog = initialState;
        eventLog(:,13) = eventNum;
        return;
    end

    if(dt > maxPropTime)
        dt = maxPropTime;
    end

    ut = initialState(1);
	rVect = initialState(2:4);
    vVect = initialState(5:7);
    dryMass = initialState(9);
    fuelOxMass = initialState(10);
    monoMass = initialState(11);
    xenonMass = initialState(12);

	bodyID = initialState(8);
    bodyInfo = getBodyInfoByNumber(bodyID, celBodyData);
    topLevelBodyInfo = getTopLevelCentralBody(celBodyData);
    bodyInfoSun = topLevelBodyInfo;
    forceModel.gravModelBodyIds(end+1) = bodyInfoSun.id;
    forceModel.gravModelBodyIds = unique(forceModel.gravModelBodyIds);

    [rVect,vVect] = getAbsPositBetweenSpacecraftAndBody(ut, rVect', bodyInfo, bodyInfoSun, celBodyData, vVect');

    rhs = @(t,x) propRHS(t, x, bodyInfoSun, forceModel, massLoss, celBodyData);
    tspan = [ut, ut + dt]; %linspace(ut, ut + dt, numPts); %[ut, ut + dt];
    x0 = [-rVect', -vVect', dryMass, fuelOxMass, monoMass, xenonMass];
    eventFun = @(T,Y) ma_runNBodyEvents(T,Y, events);
    options = odeset('RelTol',1E-8, 'AbsTol',1E-8, 'Events',eventFun);
    [T,Y,TE,YE,IE] = ode113(rhs,tspan,x0,options);

    deltaT = T(end) - T(1);

    [rVect,vVect] = getAbsPositBetweenSpacecraftAndBody(T', Y(:,1:3)', bodyInfoSun, bodyInfo, celBodyData, Y(:,4:6)');

    eventLog = zeros(length(T), length(initialState));
    eventLog(:,1) = T;
    eventLog(:,2:4) = -rVect';
    eventLog(:,5:7) = -vVect';
    eventLog(:,8) = bodyID;
    eventLog(:,9) = Y(:,7);   %Dry Mass
    eventLog(:,10) = Y(:,8);  %Fuel/Ox Mass
    eventLog(:,11) = Y(:,9);  %Monoprop Mass
    eventLog(:,12) = Y(:,10); %Xenon Mass
    eventLog(:,13) = eventNum;

    if(~isempty(IE))
        [~,~,~,eventDescs] = eventFun(TE, YE');
        eDesc = eventDescs{IE};

        if(contains(eDesc, 'SoI Transition'))
            ut =  TE;
            rVect = YE(1:3);
            vVect = YE(4:6);

            if(contains(eDesc,'Up'))
                parentBodyInfo = bodyInfo.getParBodyInfo(celBodyData);
                [rVectNew, vVectNew] = convertRVVectOnUpwardsSoITransition(bodyInfo, celBodyData, ut, rVect, vVect);
                newBodyId = parentBodyInfo.id;
            elseif(contains(eDesc,'Down'))
                tokens = regexpi(eDesc,'- (\d+)\)','tokens');
                bodyId = str2double(tokens{1});
                childBodyInfo = getBodyInfoByNumber(bodyId, celBodyData);

                [rVectNew, vVectNew] = convertRVVectOnDownwardsSoITransition(childBodyInfo, celBodyData, ut, rVect, vVect);
                newBodyId = childBodyInfo.id;
            end

            soiTransInitState = [ut, rVectNew', vVectNew', newBodyId, eventLog(end,9:13)];
            eventLog(end+1,:) = soiTransInitState;

            if(contOnSoITrans == true)
                events = ma_updateEventFcnWithNewBodyInfo(events, getBodyInfoByNumber(newBodyId, celBodyData), celBodyData);

                soiTranseventLog = ma_executeCoast_nBody_goto_dt(dt-deltaT, soiTransInitState, eventNum, forceModel, considerSoITransitions, soiSkipIds, massLoss, maxPropTime-deltaT, events, contOnSoITrans, celBodyData);
                eventLog = [eventLog;soiTranseventLog];
            end
        end
    end
end

function xdot = propRHS(ut, x, cBodyInfo, forceModel, massLoss, celBodyData)
    gBodyIds = forceModel.gravModelBodyIds;

    rVectSC = x(1:3);
    vVectSC = x(4:6);

    gAccel = [0;0;0];
    for(i=1:length(gBodyIds)) %#ok<*NO4LP>
        gBodyId = gBodyIds(i);
        bodyOther = getBodyInfoByNumber(gBodyId, celBodyData);

        [rVect,~] = getAbsPositBetweenSpacecraftAndBody(ut, rVectSC, cBodyInfo, bodyOther, celBodyData);
        r = norm(rVect);

        gAccel = gAccel + (bodyOther.gm/r^3)*rVect; %the negative sign that is normally here is taken care of in the rVect already by virtue of how getAbsPositBetweenSpacecraftAndBody() works
    end

	xdot(1:3) = vVectSC;
    xdot(4:6) = gAccel;
    xdot(7) = 0;
    xdot(8) = 0;
    xdot(9) = 0;
    xdot(10) = 0;

	if(massLoss.use == 1 && ~isempty(massLoss.lossConvert))
        resRates = ma_getResRates(massLoss);

        xdot(8) = resRates(1);
        xdot(9) = resRates(2);
        xdot(10) = resRates(3);
	end

    xdot = xdot';
end


function [Results, pz_d] = CD_PLSA(TrainData, TestData, TrainLabel, TestLabel, numCluster, numIter, numSource, numTrain, numTarget, numTest)

% function [Results, pz_d] = CD_PLSA(Train_Data,Test_Data,Parameter_Setting)

% The common program for CD_PLSA, which can deal with multiple classes,
% multiple source domains and multiple target domains

%%%% Input:
% The parameter Train_data stores the file pathes of training data and the
% corresponding labels
% The parameter Test_data stores the file pathes of test data and the
% corresponding labels
% The parameter Parameterfile stores the parameter setting information

%%%% Output
% The variable Results is a matrix with size numIteration x numTarget, where
% numIteration is the number of iterations, numTarget is the number of
% target domains. Results record the detailed results of each iteration.

% The variable pz_d is a matrix with size n x c, where n is the number of
% instances in all target domains, specifically, n = n_1 + ... + nt (n_t is
% the number of instances in t-th target domain), c is the number of
% classes
%
% Note that if you want to deal with large data set, you should set larget
% memory for Matlab. You can set it in the file C:\boot.ini (This may not
% be true in your system), change '/fastdetect' to '/fastdetect /3GB'.
%
% Be good luck for your research, if you have any questions, you can
% contact the email: zhuangfz@ics.ict.ac.cn

TrainX = TrainData;
TrainY = TrainLabel;
TestX = TestData;
TestY = TestLabel;
numK =  numCluster;
numIteration = numIter;
labelset = union(TrainLabel,[]);
numC = length(labelset);
pyz = rand(numK,numC);
%pyz = ones(numK,numC);
pyz = pyz/sum(sum(pyz));

start = 1;
if start == 1
    DataSetX = [TrainX TestX];
    Learn.Verbosity = 1;
    Learn.Max_Iterations = 200;
    Learn.heldout = .1; % for tempered EM only, percentage of held out data
    Learn.Min_Likelihood_Change = 1;
    Learn.Folding_Iterations = 20; % for TEM only: number of fiolding in iterations
    Learn.TEM = 0; %tempered or not tempered
    [Pw_z,Pz_d,Pd,Li,perp,eta] = pLSA(DataSetX,[],numK,Learn); %start PLSA
    %xlswrite(strcat('pwz_','common_selected','.xls'),Pw_z);
end

%pwy = xlsread(strcat('pwz_','common_selected','.xls'));

pwy = Pw_z;

pw_yc_s = [];
for i = 1:numSource
    pw_yc_s = [pw_yc_s, pwy];
end
pw_yc_t = [];
for i = 1:numTarget
    pw_yc_t = [pw_yc_t, pwy];
end
clear pwy;

pd_zc_s = [];
for i = 1:numSource
    A = zeros(numTrain(i),numC);
    pos = 0;
    if i > 1
        for t = 1:i-1
            pos = pos + numTrain(t);
        end
    end
    if i == 1
        pos = 0;
    end
    for j = 1:numTrain(i)
        for k = 1:numC
            if TrainY(pos+j) == labelset(k)
                A(j,k) = 1;
            end
        end
    end
    for k = 1:numC
        A(:,k) = A(:,k)/sum(A(:,k));
    end
    pd_zc_s = [pd_zc_s;A];
end

% random initialization for pd_z_t
% In our paper, pd_z_t is assigned as the predicted results by supervised classifiers
pd_zc_t = [];
for i = 1:numTarget
    A = ones(numTest(i),numC);
    for k = 1:numC
        A(:,k) = A(:,k)/sum(A(:,k));
    end
    pd_zc_t = [pd_zc_t;A];
end

pc = zeros(1,numSource+numTarget);
numAll = sum(numTrain) + sum(numTest);
for i = 1:numSource
    pc(i) = numTrain(i)/numAll;
end
for i = 1:numTarget
    pc(i+numSource) = numTest(i)/numAll;
end

iter_results = [];

O_s = TrainX;
O_t = TestX;

for iterID = 1:numIteration

    temp_pw_yc_s = [];
    temp_pw_yc_t = [];
    temp_pd_zc_s = [];
    temp_pd_zc_t = [];
    temp_pyz = zeros(size(pyz));
    temp_pc = zeros(size(pc));

    stepLen = 3000;
    numStep = fix(size(TrainX,1)/stepLen);
    step = fix(size(TrainX,1)/numStep);

    for i = 1:numSource
        pos = 0;
        if i > 1
            for t = 1:i-1
                pos = pos + numTrain(t);
            end
        end
        if i == 1
            pos = 0;
        end

        A = [];
        D = zeros(numK,numTrain(i));
        for stepID = 1:numStep
            if stepID < numStep
                tempsum2_s = pw_yc_s((stepID-1)*step+1:stepID*step,(i-1)*numK+1:i*numK)*pyz*pd_zc_s(pos+1:pos+numTrain(i),:)';
                tempsum2_s = tempsum2_s*pc(i);
                [xs ys] = find(tempsum2_s == 0);
                for q = 1:size(xs,1)
                    tempsum2_s(xs(q,1),ys(q,1)) = 1;
                end
                B = O_s((stepID-1)*step+1:stepID*step,pos+1:pos+numTrain(i))./tempsum2_s;
                A = [A; pw_yc_s((stepID-1)*step+1:stepID*step,(i-1)*numK+1:i*numK).*(B*pd_zc_s(pos+1:pos+numTrain(i),:)*pyz')];
                D = D + pw_yc_s((stepID-1)*step+1:stepID*step,(i-1)*numK+1:i*numK)'*B;
                clear B;
            end
            if stepID == numStep
                tempsum2_s = pw_yc_s((stepID-1)*step+1:size(O_s,1),(i-1)*numK+1:i*numK)*pyz*pd_zc_s(pos+1:pos+numTrain(i),:)';
                tempsum2_s = tempsum2_s*pc(i);
                [xs ys] = find(tempsum2_s == 0);
                for q = 1:size(xs,1)
                    tempsum2_s(xs(q,1),ys(q,1)) = 1;
                end
                B = O_s((stepID-1)*step+1:size(O_s,1),pos+1:pos+numTrain(i))./tempsum2_s;
                A = [A; pw_yc_s((stepID-1)*step+1:size(O_s,1),(i-1)*numK+1:i*numK).*(B*pd_zc_s(pos+1:pos+numTrain(i),:)*pyz')];
                D = D + pw_yc_s((stepID-1)*step+1:size(O_s,1),(i-1)*numK+1:i*numK)'*B;
                clear B;
            end
        end

        A = A*pc(i);
        for l = 1:numK
            A(:,l) = A(:,l)/sum(A(:,l));
        end
        temp_pw_yc_s = [temp_pw_yc_s A];
        clear A;

        temp_pyz = temp_pyz + (pyz.*(D*pd_zc_s(pos+1:pos+numTrain(i),:)))*pc(i);
        clear D;
        temp_pc(i) = sum(sum(TrainX(:,pos+1:pos+numTrain(i))));
    end

    for i = 1:numTarget
        pos = 0;
        if i > 1
            for t = 1:i-1
                pos = pos + numTest(t);
            end
        end
        if i == 1
            pos = 0;
        end

        A = [];
        C = zeros(numTest(i),numK);
        D = zeros(numK,numTest(i));
        for stepID = 1:numStep
            if stepID < numStep
                tempsum2_t = pw_yc_t((stepID-1)*step+1:stepID*step,(i-1)*numK+1:i*numK)*pyz*pd_zc_t(pos+1:pos+numTest(i),:)';
                tempsum2_t = tempsum2_t*pc(numSource+i);
                [xs ys] = find(tempsum2_t == 0);
                for q = 1:size(xs,1)
                    tempsum2_t(xs(q,1),ys(q,1)) = 1;
                end
                B = O_t((stepID-1)*step+1:stepID*step,pos+1:pos+numTest(i))./tempsum2_t;
                A = [A; pw_yc_t((stepID-1)*step+1:stepID*step,(i-1)*numK+1:i*numK).*(B*pd_zc_t(pos+1:pos+numTest(i),:)*pyz')];
                C = C + B'*pw_yc_t((stepID-1)*step+1:stepID*step,(i-1)*numK+1:i*numK);
                D = D + pw_yc_t((stepID-1)*step+1:stepID*step,(i-1)*numK+1:i*numK)'*B;
                clear B;
            end
            if stepID == numStep
                tempsum2_t = pw_yc_t((stepID-1)*step+1:size(O_t,1),(i-1)*numK+1:i*numK)*pyz*pd_zc_t(pos+1:pos+numTest(i),:)';
                tempsum2_t = tempsum2_t*pc(numSource+i);
                [xs ys] = find(tempsum2_t == 0);
                for q = 1:size(xs,1)
                    tempsum2_t(xs(q,1),ys(q,1)) = 1;
                end
                B = O_t((stepID-1)*step+1:size(O_t,1),pos+1:pos+numTest(i))./tempsum2_t;
                A = [A; pw_yc_t((stepID-1)*step+1:size(O_t,1),(i-1)*numK+1:i*numK).*(B*pd_zc_t(pos+1:pos+numTest(i),:)*pyz')];
                C = C + B'*pw_yc_t((stepID-1)*step+1:size(O_t,1),(i-1)*numK+1:i*numK);
                D = D + pw_yc_t((stepID-1)*step+1:size(O_t,1),(i-1)*numK+1:i*numK)'*B;
                clear B;
            end
        end

        A = A*pc(numSource+i);
        for l = 1:numK
            A(:,l) = A(:,l)/sum(A(:,l));
        end
        temp_pw_yc_t = [temp_pw_yc_t A];
        clear A;

        A = pd_zc_t(pos+1:pos+numTest(i),:).*(C*pyz);
        clear C;
        A = A*pc(numSource+i);
        for k = 1:numC
            A(:,k) = A(:,k)/sum(A(:,k));
        end
        temp_pd_zc_t = [temp_pd_zc_t;A];

        temp_pyz = temp_pyz + (pyz.*(D*pd_zc_t(pos+1:pos+numTest(i),:)))*pc(numSource+i);
        clear D;
        temp_pc(numSource+i) = sum(sum(TestX(:,pos+1:pos+numTest(i))));
    end

    temp_pyz = temp_pyz/sum(sum(temp_pyz));
    temp_pc = temp_pc/sum(temp_pc);

    pw_yc_s = temp_pw_yc_s;
    pw_yc_t = temp_pw_yc_t;
    pd_zc_t = temp_pd_zc_t;
    pyz = temp_pyz;
    pc = temp_pc;

    pz_d = [];
    for i = 1:numTarget
        pos = 0;
        if i > 1
            for t = 1:i-1
                pos = pos + numTest(t);
            end
        end
        if i == 1
            pos = 0;
        end

        pzd = zeros(numTest(i),numC);
        for j = 1:size(pzd,1)
            for k = 1:size(pzd,2)
                pzd(j,k) = pd_zc_t(pos+j,k)*sum(pyz(:,k));
            end
        end
        pz_d = [pz_d; pzd];
        nCorrect = 0;
        for j = 1:size(pzd,1)
            [va vi] = max(pzd(j,:));
            if labelset(vi) == TestY(pos+j)
                nCorrect = nCorrect + 1;
            end
        end
        acc = [double(iterID) nCorrect/(numTest(i))]
        iter_results(iterID,i) = nCorrect/(numTest(i));
    end
    for i = 1:size(pz_d,1)
         pz_d(i,:) = pz_d(i,:)/sum( pz_d(i,:));
    end

    O_s = TrainX;
    O_t = TestX;
end

Results = iter_results;