function z = mtimes( x, y, oper )

%   Disciplined convex programming information for MTIMES:
%      True matrix multiplications Z = X * Y---that is, where neither X
%      nor Y is a scalar---require both multiplications and additions.
%      For example, element (i,j) of Z is given by
%         X(i,1) * Y(1,j) + X(i,2) * Y(2,j) + ... + X(i,k) * Y(k,j)
%      Therefore, matrix multiplications must satisfy *both* the
%      "no-product" rule of multiplication and the "same curvature" rule
%      of addition. See the help for CVX/TIMES and CVX/PLUS,
%      respectively, for individual descriptions of these rules.
%
%      An exception is made to these general rules for quadratic forms.
%      That is, two affine expressions may be multiplied together if the
%      result can immediately be verified as a convex quadratic form.
%      For example, the construction
%         variable x(n)
%         x' * Q * x  <= 1;
%      would be permitted if Q is *constant* and positive semidefinite.
%
%   Disciplined geometric programming information for TIMES:
%      As mentioned above, true matrix multiplies Z = X * Y require both
%      multiplications and additions. Since only log-convex terms can be
%      summed, both X and Y must be elementwise log-convex/affine.

persistent remap
if nargin < 3, oper = 'times'; end

%
% Check sizes
%

sx = size( x );
sy = size( y );
if all( sx == 1 ) || all( sy == 1 ),
    z = feval( oper, x, y );
    return
elseif length( sx ) > 2 || length( sy ) > 2,
    error( 'Input arguments must be 2-D.' );
elseif sx( 2 ) ~= sy( 1 ),
    error( 'Inner matrix dimensions must agree.' );
else
    sz = [ sx( 1 ), sy( 2 ) ];
end
nz = prod( sz );

%
% Check expression types
%

if cvx_isconstant( x ),

    xC = cvx_constant( x );
    if nnz( isnan( xC ) ),
        error( 'Disciplined convex programming error:\n    Invalid numeric values (NaNs) may not be used in CVX expressions.', 1 ); %#ok
    elseif cvx_isconstant( y ),
        yC = cvx_constant( y );
        if nnz( isnan( yC ) ),
            error( 'Disciplined convex programming error:\n    Invalid numeric values (NaNs) may not be used in CVX expressions.', 1 ); %#ok
        end
        z = feval( [ 'm', oper ], xC, yC );
        if nnz( isnan( z ) ),
            error( 'Disciplined convex programming error:\n    This expression produced one or more invalid numeric values (NaNs).', 1 ); %#ok
        end
        z = cvx( z );
        return
    elseif isequal( oper, 'rdivide' ),
        error( 'Disciplined convex programming error:\n    Matrix divisor must be constant.', 1 ); %#ok
    end
    yA   = cvx_basis( y );
    laff = true;
    cnst = false;
    raff = false;
    quad = false;
    posy = false;
    vpos = false;

elseif cvx_isconstant( y ),

    yC = cvx_constant( y );
    if nnz( isnan( yC ) ),
        error( 'Disciplined convex programming error:\n    Invalid numeric values (NaNs) may not be used in CVX expressions.', 1 ); %#ok
    elseif isequal( oper, 'ldivide' ),
        error( 'Disciplined convex programming error:\n    Matrix divisor must be constant.', 1 ); %#ok
    end
    xA   = cvx_basis( x );
    raff = true;
    laff = false;
    quad = false;
    cnst = false;
    posy = false;
    vpos = false;

else

    if isempty( remap ),
        remap_0 = cvx_remap( 'zero' );
        remap_1 = cvx_remap( 'nonzero', 'complex' );
        temp    = ~( remap_0 | remap_1 );
        remap_2 = cvx_remap( 'affine' ) & temp;
        remap_4 = cvx_remap( 'log-convex' );
        remap_5 = cvx_remap( 'log-concave' ) & ~remap_4;
        remap_4 = remap_4 & temp;
        remap_3 = cvx_remap( 'valid' ) & ~( remap_0 | remap_1 | remap_2 | remap_4 | remap_5 );
        remap   = remap_1 + 2 * remap_2 + 3 * remap_3 + 4 * remap_4 + 5 * remap_5 - cvx_remap( 'invalid' );
    end
    vx = remap( cvx_classify( x ) );
    vy = remap( cvx_classify( y ) );
    xA = cvx_basis( x );
    yA = cvx_basis( y );
    xC = cvx_reshape( xA( 1, : ), sx );
    yC = cvx_reshape( yA( 1, : ), sy );
    vx = reshape( vx, sx );
    vy = reshape( vy, sy );
    cx = xC ~= 0;
    cy = yC ~= 0;
    ax = vx == 2;
    ay = vy == 2;
    px = vx == 4;
    py = vy == 4;
    gx = vx == 5;
    gy = vy == 5;
    quad = +ax * +ay;
    if nnz( quad ) ~= 0,
        if length( quad ) ~= 1,
            error( 'Disciplined convex programming error:\n    Only scalar quadratic forms can be specified in CVX\n.', 1 ); %#ok
        else
            cx = cx & ~ax;
            cy = cy & ~ay;
            xC( ax ) = 0;
            yC( ay ) = 0;
        end
    end
    cnst = +cx * +cy; %#ok
    laff = +cx * +( vy > 1 );
    raff = +( vx > 1 ) * cy;
    posy = +px * +py;
    vpos = +gx * +gy;
    if nnz( raff ) ~= 0,
        raff = true;
        cnst = false;
    elseif nnz( laff ) ~= 0,
        laff = true;
        cnst = false;
    else
        laff = false;
        raff = false;
        cnst = true;
    end
    othr = +( vx > 1 | vx < 0 ) * +( vy > 1 | vy < 0 ) - quad - posy - vpos;
    if nnz( othr ) ~= 0,
        error( 'Disciplined convex programming error:\n    Cannot perform the operation {%s}*{%s}', cvx_class( x ), cvx_class( y ) );
    end
    quad = nnz( quad ) ~= 0;
    posy = nnz( posy ) ~= 0;

end

first = true;

if cnst,
    switch oper,
    case 'ldivide', z2 = xC \ yC;
    case 'rdivide', z2 = xC / yC;
    otherwise,      z2 = xC * yC;
    end
    if first, z = z2; first = false; else z = z + z2; end %#ok
end

if raff,
    % everything * constant
    nA = size( xA, 1 );
    z2 = cvx_reshape( xA, [ nA * sx( 1 ), sx( 2 ) ] );
    if issparse( z2 ),
        tt = any( z2, 2 );
        if cvx_use_sparse( size( z2 ), nnz( tt ) * sx( 2 ), isreal( z2 ) & isreal( yC ) ),
            z2 = z2( tt, : );
        else
            tt = [];
        end
    else
        tt = [];
    end
    switch oper,
    case 'rdivide', z2 = z2 / yC;
    otherwise,      z2 = z2 * yC;
    end
    z2 = cvx_reshape( z2, [ nA, nz ], tt );
    z2 = cvx( sz, z2 );
    if first, z = z2; first = false; else z = z + z2; end
end

if laff,
    % constant * everything
    nA = size( yA, 1 );
    t1 = reshape( 1 : prod( sy ), sy )';
    t2 = reshape( 1 : prod( sz ), [ sz(2), sz(1) ] )';
    z2 = yA; if raff, z2( 1, : ) = 0; end
    z2 = cvx_reshape( z2, [ nA * sy( 2 ), sy( 1 ) ], [], t1 );
    if issparse( z2 ),
        tt = any( z2, 2 );
        if cvx_use_sparse( size( z2 ), nnz( tt ) * sy( 1 ), isreal( z2 ) & isreal( xC ) ),
            z2 = z2( tt, : );
        else
            tt = [];
        end
    else
        tt = [];
    end
    switch oper,
    case 'ldivide', z2 = z2 / xC.';
    otherwise,      z2 = z2 * xC.';
    end
    z2 = cvx_reshape( z2, [ nA, nz ], tt, [], t2 );
    z2 = cvx( sz, z2 );
    if first, z = z2; first = false; else z = z + z2; end
end

if quad,
    % affine * affine
    tt = ax( : ) & ay( : );
    xA = xA( :, tt ); xB = xA( 1, : ); xA( 1, : ) = 0;
    yA = yA( :, tt ); yB = yA( 1, : ); yA( 1, : ) = 0;
    xM = size( xA, 1 ); yM = size( yA, 1 );
    if xM < yM, xA( yM, end ) = 0;
    elseif yM < xM, yA( xM, end ) = 0; end
    %
    % Quadratic form test 1: See if x == a conj( y ) + b for some real a, b,
    % so that the quadratic form involves a simple squaring (or sum of squares)
    %
    cyA   = conj( yA );
    alpha = sum( sum( real( xA .* yA ) ) ) ./ max( sum( sum( cyA .* yA ) ), realmin );
    if sum( sum( abs( xA - alpha * cyA ) ) ) <= 2 * eps * sum( sum( abs( xA ) ) ),
        beta = xB - alpha * conj( yB );
        yt = cvx( [ 1, size( yA, 2 ) ], yA ) + yB;
        if isreal( yA ) && isreal( yB ) && isreal( beta ),
            beta = ( 0.5 / alpha ) * beta;
            z2 = alpha * ( sum_square( yt + beta ) - sum_square( beta ) );
        elseif all( abs( beta ) <= 2 * eps * abs( xB ) ),
            z2 = alpha * sum_square_abs( yt );
        else
            error( 'Disciplined convex programming error:\n    Invalid quadratic form: product is not real.\n', 1 ); %#ok
        end
    else
        %
        % Quadratic form test 2: Extract the quadratic coefficient matrix
        % and test it for semidefiniteness
        %
        dx = find( any( xA, 2 ) | any( yA, 2 ) );
        zb = length( dx );
        cxA = conj( xA( dx, : ) );
        cyA = cyA( dx, : );
        P  = cxA * cyA.';
        Q  = cxA * yB.' + cyA * xB.';
        R  = xB * yB.';
        P  = 0.5 * ( P + P.' );
        if ~isreal( R ) || ~isreal( Q ) || ~isreal( P ),
            error( 'Disciplined convex programming error:\n   Invalid quadratic form: product is complex.', 1 ); %#ok
        else
            xx = cvx( zb, sparse( dx, 1 : zb, 1 ) );
            [ z2, success ] = quad_form( xx, P, Q, R );
            if ~success,
                error( 'Disciplined convex programming error:\n   Invalid quadratic form: neither convex nor concave.', 1 ); %#ok
            end
        end
    end
    if first, z = z2; first = false; else z = z + z2; end
end

if posy,
    [ ix, jx ] = find( reshape( px, sx ) );
    vx = log( cvx_subsref( x, px ) );
    [ iy, jy ] = find( reshape( py, sy ) );
    vy = log( cvx_subsref( y, py ) );
    [ iz, jz ] = find( sparse( 1 : nnz(px), jx, 1 ) * sparse( iy, 1 : nnz(py), 1 ) );
    z2 = exp( vec( cvx_subsref( vx, iz ) ) + vec( cvx_subsref( vy, jz ) ) );
    z2 = sparse( ix(iz), jy(jz), z2, sz(1), sz(2) );
    if first, z = z2; first = false; else z = z + z2; end
end

if vpos,
    [ ix, jx ] = find( reshape( gx, sx ) );
    vx = log( cvx_subsref( x, gx ) );
    [ iy, jy ] = find( reshape( gy, sy ) );
    vy = log( cvx_subsref( y, gy ) );
    [ iz, jz ] = find( sparse( 1 : nnz(gx), jx, 1 ) * sparse( iy, 1 : nnz(gy), 1 ) );
    z2 = exp( vec( cvx_subsref( vx, iz ) ) + vec( cvx_subsref( vy, jz ) ) );
    z2 = sparse( ix(iz), jy(jz), z2, sz(1), sz(2) );
    if first, z = z2; first = false; else z = z + z2; end %#ok
end

%
% Check that the sums are legal
%

v = cvx_vexity( z );
if any( isnan( v( : ) ) ),
    temp = 'Disciplined convex programming error:';
    tt = isnan( cvx_constant( z ) );
    if any( tt ),
        temp = [ temp, '\n    This expression produced one or more invalid numeric values (NaNs).' ];
    end
    if any( isnan( v( ~tt ) ) ),
        temp = [ temp, '\n   Illegal affine combination of convex and/or concave terms detected.' ];
    end
    error( temp, 1 );
end

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


classdef dme_xfmr3p < mp.dm_element
%MP.DME_XFMR3P  MATPOWER data model class for 3-phase transformer data

%   MATPOWER
%   Copyright (c) 2021-2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

    properties
        fbus    %% bus index vector for "from" port (port 1) (all branches)
        tbus    %% bus index vector for "to" port (port 2) (all branches)
        r       %% series resistance (p.u.) for branches that are on
        x       %% series reactance (p.u.) for branches that are on
        base_kva
        base_kv
%         g_to    %% shunt conductance (p.u.) at "to" end for branches that are on
%         b_fr    %% shunt susceptance (p.u.) at "from" end for branches that are on
%         b_to    %% shunt susceptance (p.u.) at "to" end for branches that are on
%         tm      %% transformer off-nominal turns ratio for branches that are on
%         ta      %% xformer phase-shift angle (radians) for branches that are on
%         rate_a  %% long term flow limit (p.u.) for branches that are on
    end     %% properties

    methods
        function name = name(obj)
            name = 'xfmr3p';
        end

        function label = label(obj)
            label = '3-ph Transformer';
        end

        function label = labels(obj)
            label = '3-ph Transformers';
        end

        function name = cxn_type(obj)
            name = 'bus3p';
        end

        function name = cxn_idx_prop(obj)
            name = {'fbus', 'tbus'};
        end

        function names = main_table_var_names(obj)
            names = horzcat( main_table_var_names@mp.dm_element(obj), ...
                {'bus_fr', 'bus_to', 'r', 'x', 'base_kva', 'base_kv', ...
                 'pl1_fr', 'ql1_fr', 'pl2_fr', 'ql2_fr', 'pl3_fr', 'ql3_fr', ...
                 'pl1_to', 'ql1_to', 'pl2_to', 'ql2_to', 'pl3_to', 'ql3_to' ...
                 });
        end

%         function vars = export_vars(obj)
%             vars = {'pl1_fr', 'ql1_fr', ...
%                     'pl2_fr', 'ql2_fr', ...
%                     'pl3_fr', 'ql3_fr', ...
%                     'pl1_to', 'ql1_to', ...
%                     'pl2_to', 'ql2_to', ...
%                     'pl3_to', 'ql3_to' };
%         end

        function obj = initialize(obj, dm)
            initialize@mp.dm_element(obj, dm);  %% call parent

            %% get bus mapping info
            b2i = dm.elements.bus3p.ID2i;   %% bus num to idx mapping

            %% set bus index vectors for port connectivity
            obj.fbus = b2i(obj.tab.bus_fr);
            obj.tbus = b2i(obj.tab.bus_to);
        end

        function obj = update_status(obj, dm)
            %% get bus status info
            bs = dm.elements.bus3p.tab.status;  %% bus status

            %% update status of branches connected to isolated/offline buses
            obj.tab.status = obj.tab.status & bs(obj.fbus) & ...
                                              bs(obj.tbus);

            %% call parent to fill in on/off
            update_status@mp.dm_element(obj, dm);
        end

        function obj = build_params(obj, dm)
            obj.r = obj.tab.r(obj.on);
            obj.x = obj.tab.x(obj.on);
            obj.base_kva = obj.tab.base_kva(obj.on);
            obj.base_kv  = obj.tab.base_kv(obj.on);
        end

        function obj = pretty_print(obj, dm, section, out_e, mpopt, fd, pp_args)
            switch section
                case 'det'
                    %% compute currents/powers for pp_args
                    s_fr = [  obj.tab.pl1_fr + 1j * obj.tab.ql1_fr ...
                            obj.tab.pl2_fr + 1j * obj.tab.ql2_fr ...
                            obj.tab.pl3_fr + 1j * obj.tab.ql3_fr    ];
                    s_to = [  obj.tab.pl1_to + 1j * obj.tab.ql1_to ...
                            obj.tab.pl2_to + 1j * obj.tab.ql2_to ...
                            obj.tab.pl3_to + 1j * obj.tab.ql3_to    ];
                    t = dm.elements.bus3p.tab;    %% bus3p table
                    vm = [ t.vm1 t.vm2 t.vm3 ] .* (t.base_kv/sqrt(3) * [1 1 1]);
                    va = [ t.va1 t.va2 t.va3 ];
                    v_ = vm .* exp(1j * va * pi/180);
                    i_fr = conj( s_fr ./ v_(obj.fbus, :));
                    i_to = conj( s_to ./ v_(obj.tbus, :));
                    c_fr = struct('cm', abs(i_fr), 'ca', angle(i_fr) * 180/pi);
                    c_to = struct('cm', abs(i_to), 'ca', angle(i_to) * 180/pi);

                    pp_args.xfmr3p = {'c', 'f', abs(i_fr), angle(i_fr) * 180/pi};
                    pretty_print@mp.dm_element(obj, dm, section, out_e, mpopt, fd, pp_args);

                    pp_args.xfmr3p = {'c', 't', abs(i_to), angle(i_to) * 180/pi};
                    pretty_print@mp.dm_element(obj, dm, section, out_e, mpopt, fd, pp_args);

                    pp_args.xfmr3p = {'s', 'f', real(s_fr), imag(s_fr)};
                    pretty_print@mp.dm_element(obj, dm, section, out_e, mpopt, fd, pp_args);

                    pp_args.xfmr3p = {'s', 't', real(s_to), imag(s_to)};
                    pretty_print@mp.dm_element(obj, dm, section, out_e, mpopt, fd, pp_args);
                otherwise
                    pretty_print@mp.dm_element(obj, dm, section, out_e, mpopt, fd, pp_args);
            end
        end

        function TorF = pp_have_section_sum(obj, mpopt, pp_args)
            TorF = true;
        end

        function obj = pp_data_sum(obj, dm, rows, out_e, mpopt, fd, pp_args)
            %% call parent
            pp_data_sum@mp.dm_element(obj, dm, rows, out_e, mpopt, fd, pp_args);

            %% print generation summary
            t = obj.tab;
            ploss = [ t.pl1_fr t.pl2_fr t.pl3_fr ] + ...
                    [ t.pl1_to t.pl2_to t.pl3_to ];
            qloss = [ t.ql1_fr t.ql2_fr t.ql3_fr ] + ...
                    [ t.ql1_to t.ql2_to t.ql3_to ];
            fprintf(fd, '  %-29s %12.1f kW %12.1f kVAr\n', 'Total 3-ph transformer loss', ...
                sum(sum(ploss(obj.on, :))), sum(sum(qloss(obj.on, :))) );
        end

        function TorF = pp_have_section_det(obj, mpopt, pp_args)
            TorF = true;
        end

        function h = pp_get_headers_det(obj, dm, out_e, mpopt, pp_args)
            cs = pp_args.xfmr3p{1};
            ft = pp_args.xfmr3p{2};
            if cs == 'c' && ft == 'f'
                h1 = pp_get_headers_det@mp.dm_element(obj, dm, out_e, mpopt, pp_args);
            else
                h1 = {};
            end
            if cs == 'c'
                if ft == 'f'
                    h2 = {'-->  Current Injections at "From" Bus' };
                else    %% ft == 't'
                    h2 = {'', ...
                        '<--  Current Injections at "To" Bus' };
                end
            else    %% cs == 's'
                if ft == 'f'
                    h2 = {'', ...
                        '-->  Power Injections at "From" Bus' };
                else    %% ft == 't'
                    h2 = {'', ...
                        '<--  Power Injections at "To" Bus' };
                end
            end
            switch cs
                case 'c'
                    h = [ h1 h2 ...
                        {   '  3-ph    3-ph Bus  3-ph Bus          Phase A Current  Phase B Current  Phase C Current', ...
                            'Xfrm ID    From ID   To ID    Status   (A)    (deg)     (A)    (deg)     (A)    (deg)', ...
                            '--------  --------  --------  ------  ------  ------   ------  ------   ------  ------' } ];
                    %%       1234567 123456789 123456789 -----1 123456.89 12345.7 12345.78 12345.7 12345.78 12345.7
                case 's'
                    h = [ h1 h2 ...
                        {   '  3-ph    3-ph Bus  3-ph Bus          Phase A Power    Phase B Power    Phase C Power', ...
                            'Xfmr ID    From ID   To ID    Status   (kW)   (kVAr)    (kW)   (kVAr)    (kW)   (kVAr)', ...
                            '--------  --------  --------  ------  ------  ------   ------  ------   ------  ------' } ];
                    %%       1234567 123456789 123456789 -----1 1234567.9 12345.7 123456.8 12345.7 123456.8 12345.7
            end
        end

        function str = pp_data_row_det(obj, dm, k, out_e, mpopt, fd, pp_args)
            switch pp_args.xfmr3p{1}    %% cs
                case 'c'
                    cm = pp_args.xfmr3p{3}(k, :);
                    ca = pp_args.xfmr3p{4}(k, :);
                    str = sprintf('%7d %9d %9d %6d %9.2f %7.1f %8.2f %7.1f %8.2f %7.1f', ...
                        obj.tab.uid(k), obj.tab.bus_fr(k), obj.tab.bus_to(k), ...
                        obj.tab.status(k), ...
                        cm(:, 1), ca(:, 1), ...
                        cm(:, 2), ca(:, 2), ...
                        cm(:, 3), ca(:, 3) );
                case 's'
                    p = pp_args.xfmr3p{3}(k, :);
                    q = pp_args.xfmr3p{4}(k, :);
                    str = sprintf('%7d %9d %9d %6d %9.1f %7.1f %8.1f %7.1f %8.1f %7.1f', ...
                        obj.tab.uid(k), obj.tab.bus_fr(k), obj.tab.bus_to(k), ...
                        obj.tab.status(k), ...
                        p(:, 1), q(:, 1), ...
                        p(:, 2), q(:, 2), ...
                        p(:, 3), q(:, 3) );
            end
        end
    end     %% methods
end         %% classdef


classdef AMICO_VERDICTPROSTATE

properties
    id, name                % id and name of the model
    max_dirs                % maximum number of directions to fit
    dIC                     %
    Rs                      %
    dEES                    %
    P                       %
    OUTPUT_names            % suffix of the output maps
    OUTPUT_descriptions     % description of the output maps
end

methods

    % =================================
    % Setup the parameters of the model
    % =================================
    function obj = AMICO_VERDICTPROSTATE()
        global CONFIG

        % set the parameters of the model
        obj.id        = 'VerdictProstate';
        obj.name      = 'VERDICT prostate';
        obj.max_dirs  = 0; % no need to estimate directions, it's an isotropic model
        obj.dIC       = 2.0 * 1E-3;
        obj.Rs        = linspace(0.01,20.1,20);
        obj.dEES      = 2.0 * 1E-3;
        obj.P         = 8.0 * 1E-3;
        obj.OUTPUT_names        = {'R', 'fIC', 'fEES', 'fVASC', 'Fobj'};
        obj.OUTPUT_descriptions = {'R', 'fIC', 'fEES', 'fVASC', 'Fobj'};

        % set the parameters to fit it
        CONFIG.OPTIMIZATION.SPAMS_param.mode    = 2;
        CONFIG.OPTIMIZATION.SPAMS_param.pos     = true;
        CONFIG.OPTIMIZATION.SPAMS_param.lambda  = 0;    % l1 regularization
        CONFIG.OPTIMIZATION.SPAMS_param.lambda2 = 1e-3; % l2 regularization
    end

    % ==================================================================
    % Generate high-resolution kernels and rotate them in harmonic space
    % ==================================================================
    function GenerateKernels( obj, ATOMS_path, schemeHR, AUX, idx_IN, idx_OUT )
        global CONFIG AMICO_data_path CAMINO_path

        % check if high-resolution scheme has been created
        schemeHrFilename = fullfile(ATOMS_path,'protocol_HR.scheme');
        if ~exist( schemeHrFilename, 'file' )
            error( '[AMICO_VERDICTPROSTATE.GenerateKernels] File "protocol_HR.scheme" not found in folder "%s"', ATOMS_path )
        end

        filenameHr = [tempname '.Bfloat'];
        progress = ProgressBar( numel(obj.Rs) + 2 );

        % IC compartment
        % ==============
        for R = obj.Rs
            % generate
            if exist( filenameHr, 'file' ), delete( filenameHr ); end
            CMD = sprintf( '%s/datasynth -synthmodel compartment 1 SPHEREGPD %E %E -schemefile %s -voxels 1 -outputfile %s 2> /dev/null', CAMINO_path, obj.dIC*1e-6, R*1e-6, schemeHrFilename, filenameHr );
            [status result] = system( CMD );
            if status>0
                disp(result)
                error( '[AMICO_VERDICTPROSTATE.GenerateKernels] Problems generating the signal with datasynth' );
            end

            % rotate and save
            fid = fopen( filenameHr, 'r', 'b' );
            signal = fread(fid,'float');
            fclose(fid);
            delete( filenameHr );
            lm = AMICO_RotateKernel( signal, AUX, idx_IN, idx_OUT, true );
            save( fullfile( ATOMS_path, sprintf('A_%03d.mat',progress.i) ), '-v6', 'lm' )
            progress.update();
        end

        % EES compartment
        % ===============
        % generate
        if exist( filenameHr, 'file' ), delete( filenameHr ); end
        CMD = sprintf( '%s/datasynth -synthmodel compartment 1 BALL %E -schemefile %s -voxels 1 -outputfile %s 2> /dev/null', CAMINO_path, obj.dEES*1e-6, schemeHrFilename, filenameHr );
        [status result] = system( CMD );
        if status>0
            disp(result)
            error( '[AMICO_VERDICTPROSTATE.GenerateKernels] problems generating the signal' );
        end

        % resample and save
        fid = fopen( filenameHr, 'r', 'b' );
        signal = fread(fid,'float');
        fclose(fid);
        delete( filenameHr );
        lm = AMICO_RotateKernel( signal, AUX, idx_IN, idx_OUT, true );
        save( fullfile( ATOMS_path, sprintf('A_%03d.mat',progress.i) ), '-v6', 'lm' )
        progress.update();

        % VASC compartment
        % ================
        % generate
        if exist( filenameHr, 'file' ), delete( filenameHr ); end
        CMD = sprintf( '%s/datasynth -synthmodel compartment 1 ASTROSTICKS %E -schemefile %s -voxels 1 -outputfile %s 2> /dev/null', CAMINO_path, obj.P*1e-6, schemeHrFilename, filenameHr );
        [status result] = system( CMD );
        if status>0
            disp(result)
            error( '[AMICO_VERDICTPROSTATE.GenerateKernels] problems generating the signal' );
        end

        % resample and save
        fid = fopen( filenameHr, 'r', 'b' );
        signal = fread(fid,'float');
        fclose(fid);
        delete( filenameHr );
        lm = AMICO_RotateKernel( signal, AUX, idx_IN, idx_OUT, true );
        save( fullfile( ATOMS_path, sprintf('A_%03d.mat',progress.i) ), '-v6', 'lm' )
        progress.update();

        progress.close();
end

    % ==============================================
    % Project kernels from harmonic to subject space
    % ==============================================
    function ResampleKernels( obj, ATOMS_path, idx_OUT, Ylm_OUT )
        global CONFIG AMICO_data_path KERNELS

        % Setup the KERNELS structure
        % ===========================
        nIC = numel(obj.Rs);

        KERNELS = {};
        KERNELS.model    = 'VERDICTPROSTATE';
        KERNELS.nS       = CONFIG.scheme.nS;
        KERNELS.nA       = nIC + 2; % number of atoms

        KERNELS.Aic      = zeros( [KERNELS.nS nIC], 'single' );
        KERNELS.Aic_R    = zeros( 1, nIC, 'single' );

        KERNELS.Aees      = zeros( [KERNELS.nS 1], 'single' );
        KERNELS.Aees_d    = NaN;

        KERNELS.Avasc     = zeros( [KERNELS.nS 1], 'single' );
        KERNELS.Avasc_P   = NaN;

        progress = ProgressBar( KERNELS.nA );

        % IC compartment
        % ==============
        for i = 1:nIC
            load( fullfile( ATOMS_path, sprintf('A_%03d.mat',progress.i) ), 'lm' );
            KERNELS.Aic(:,i) = AMICO_ResampleKernel( lm, idx_OUT, Ylm_OUT, true );
            KERNELS.Aic_R(i) = obj.Rs(i);
            progress.update();
        end

        % Precompute norms of coupled atoms (for the l1 minimization)
        A = double( KERNELS.Aic(CONFIG.scheme.dwi_idx,:) );
        KERNELS.Aic_norm = repmat( 1./sqrt( sum(A.^2) ), [size(A,1),1] );
        clear A

        % EES compartment
        % ===============
        load( fullfile( ATOMS_path, sprintf('A_%03d.mat',progress.i) ), 'lm' );
        KERNELS.Aees   = AMICO_ResampleKernel( lm, idx_OUT, Ylm_OUT, true );
        KERNELS.Aees_d = obj.dEES;
        progress.update();

        % VASC compartment
        % ================
        load( fullfile( ATOMS_path, sprintf('A_%03d.mat',progress.i) ), 'lm' );
        KERNELS.Avasc   = AMICO_ResampleKernel( lm, idx_OUT, Ylm_OUT, true );
        KERNELS.Avasc_P = obj.P;
        progress.update();

        progress.close();
    end

    % ===========================
    % Fit the model to each voxel
    % ===========================
    function [ MAPs ] = Fit( obj, y, i1, i2 )
        global CONFIG KERNELS

%         A = double( [ KERNELS.Aic(CONFIG.scheme.dwi_idx,:) KERNELS.Aees(CONFIG.scheme.dwi_idx) KERNELS.Avasc(CONFIG.scheme.dwi_idx) ] );
%         AA = [ ones(1,KERNELS.nA) ; A ];
%         yy = [ 1 ; y(CONFIG.scheme.dwi_idx) ];
        A = double( [ KERNELS.Aic KERNELS.Aees KERNELS.Avasc ] );
        AA = A;%[ ones(1,KERNELS.nA) ; A ];
        yy = y;%[ 1 ; y(CONFIG.scheme.dwi_idx) ];

        switch( 1 )

            case 1
            % [ normal fitting ]
            norms = repmat( 1./sqrt(sum(AA.^2)), [size(AA,1),1] );
            AA = AA .* norms;
            x = full( mexLasso( yy, AA, CONFIG.OPTIMIZATION.SPAMS_param ) );
            x = x .* norms(1,:)';

            case 2
            params = CONFIG.OPTIMIZATION.SPAMS_param;
            params.loss = 'square';
            params.regul = 'group-lasso-l2';
            params.groups = int32([ repmat(1,1,numel(KERNELS.Aic_R)) 2 3 ]);  % all the groups are of size 2
            params.intercept = false;
            x = full( mexFistaFlat( yy, AA, zeros(size(A,2),1), params ) );

            case 3
            % [NODDI style] estimate and remove EES and VASC contributions
            y = y(CONFIG.scheme.dwi_idx);
            x = lsqnonneg( AA, yy, CONFIG.OPTIMIZATION.LS_param );
            y = y - x(end)*A(:,end);
            y = y - x(end-1)*A(:,end-1);

            % find sparse support for remaining signal
            An = A(:,1:size(KERNELS.Aic,2)) .* KERNELS.Aic_norm;
            x = full( mexLasso( y, An, CONFIG.OPTIMIZATION.SPAMS_param ) );

            % debias coefficients
            idx = [ x>0 ; true ; true ];
            x(idx) = lsqnonneg( AA(:,idx), yy, CONFIG.OPTIMIZATION.LS_param );
        end

        % compute MAPS
        xIC = x( 1:end-2 );
        fIC = sum( xIC );
        MAPs(1) = KERNELS.Aic_R * xIC / ( fIC + eps );           % cell radius
        MAPs(2) = fIC;                                           % fIC
        MAPs(3) = x( end-1 );                                    % fEES
        MAPs(4) = x( end );                                      % fVASC

        y_predicted = A*x;
        MAPs(5) = norm(y-y_predicted) / norm(y);
%         sigma = 0;
%         MAPs(5) = sum( (y - sqrt((y_predicted).^2+sigma^2) ) ).^2;
    end

end

end


function [ekg_RSlinB__ELF_Cto_SFu] = fuse_rr_is(ekg_RSlinB_am_ELF_Cto, ekg_RSlinB_bw_ELF_Cto, ekg_RSlinB_fm_ELF_Cto, up)
%UNTITLED5 Summary of this function goes here
%   Detailed explanation goes here
rel_sub_comps = up.al.sub_components.fus_mod;
% Identify relevant data
feat_mods = {'bw', 'am', 'fm'};
for mod_no = 1:3
    mod = feat_mods(mod_no);
    eval(['rel_data.' mod{1,1} ' = ekg_RSlinB_', mod{1,1}, '_ELF_Cto' ';']);
    %eval(['rel_data.' mod{1,1} ' = rrEsts.' temp.bef{fusable_rr_est_no}, mod{1,1}, temp.aft{fusable_rr_est_no} ';']);
    %eval(['rel_data.' mod{1,1} ' = rrEsts.' temp.bef{fusable_rr_est_no}, mod{1,1}, temp.aft{fusable_rr_est_no} ';']);
end

for sub_comp_no = 1 : length(rel_sub_comps)
    % Do fusion
    temp_rr = feval(rel_sub_comps{sub_comp_no}, rel_data, up); clear rel_data
    % store this series of rrs:
    save_name = ['ekg_RSlinB__ELF_Cto_SFu'];
    eval([save_name, ' = temp_rr;']);
end

end


function [Gamma,vpath,error,Ypred] = tudadecode(X,Y,T,tuda,new_experiment,parallel_trials)
% Having estimated the TUDA model (i.e. the corresponding decoding models)
% in the same or a different data set, this function finds the model time
% courses (with no re-estimation of the decoding parameters)
%
% INPUT
% X: Brain data, (time by regions)
% Y: Stimulus, (time by q); q is no. of stimulus features
%               For binary classification problems, Y is (time by 1) and
%               has values -1 or 1
%               For multiclass classification problems, Y is (time by classes)
%               with indicators values taking 0 or 1.
%           If the stimulus is the same for all trials, Y can have as many
%           rows as trials, e.g. (trials by q)
% T: Length of series or trials
% tuda: Estimated TUDA model, using tudatrain
% new_experiment: Whether or not the estimated model is going to be applied
%   on data that follows the same paradigm used to train the model. If the
%   paradigm changes, then new_experiment should be 1. For example, that
%   would be the case if we train the model on perception and test it on
%   recalling.
% parallel_trials: if set to 1, then
%   all trials have the same experimental design and that the
%   time points correspond between trials; in this case, all trials
%   must have the same length. If set to 0, then there is not a fixed
%   experimental design for all trials.
%
% OUTPUT
% Gamma: Time courses of the states (decoding models) probabilities given data
% vpath: Most likely state path of hard assignments
% error: Error for each state on the new data;
%        if parallel_trials = 1, then error is
%          (trial tim by no. of stimuli by no. of states);
%        otherwise, this is
%          (total time by no. of stimuli by no. of states).
% Ypred: Predicted stimulus at each time point
%
% Author: Diego Vidaurre, OHBA, University of Oxford (2018)

if nargin < 5, new_experiment = 0; end
if nargin < 6, parallel_trials = 0; end

max_num_classes = 5;
do_preproc = 1;

N = length(T); q = size(Y,2); ttrial = T(1); p = size(X,2); K = tuda.train.K;

% Check options and put data in the right format
tuda.train.parallel_trials = 0;
if isfield(tuda.train,'orders')
    orders = tuda.train.orders;
    tuda.train = rmfield(tuda.train,'orders');
else
    orders = [];
end
if isfield(tuda.train,'active')
    active = tuda.train.active;
    tuda.train = rmfield(tuda.train,'active');
else
    active = [];
end

classification = length(unique(Y(:))) < max_num_classes;
if classification
    Ycopy = Y;
    if size(Ycopy,1) == N
        Ycopy = repmat(reshape(Ycopy,[1 N q]),[ttrial 1 1]);
    end
    % no demeaning by default if this is a classification problem
    if ~isfield(tuda.train,'demeanstim'), tuda.train.demeanstim = 0; end
end

if do_preproc
    if isfield(tuda.train,'embeddedlags'), el = tuda.train.embeddedlags; end
    tuda.train.intercept = 0;
    [X,Y,T,options] = preproc4hmm(X,Y,T,tuda.train); % this demeans Y
    p = size(X,2);
    if classification && length(el) > 1
        Ycopy = reshape(Ycopy,[ttrial N q]);
        Ycopy = Ycopy(-el(1)+1:end-el(end),:,:);
        Ycopy = reshape(Ycopy,[T(1)*N q]);
    end
end
if ~isempty(active), tuda.train.active = active; end
if ~isempty(orders),  tuda.train.orders = orders;  end

if isfield(options,'A') % it is done in preproc4hmm
    options = rmfield(options,'A');
end
if isfield(options,'parallel_trials')
    options = rmfield(options,'parallel_trials');
end
if isfield(options,'add_noise')
    options = rmfield(options,'add_noise');
end

% Put X and Y together
Ttmp = T;
T = T + 1;
Z = zeros(sum(T),q+p,'single');
for j = 1:N
    t1 = (1:T(j)) + sum(T(1:j-1));
    t2 = (1:Ttmp(j)) + sum(Ttmp(1:j-1));
    if strcmp(options.classifier,'LDA') || (isfield(options,'encodemodel') && options.encodemodel)
        Z(t1(2:end),1:p) = X(t2,:);
        Z(t1(1:end-1),(p+1):end) = Y(t2,:);
    else
        Z(t1(1:end-1),1:p) = X(t2,:);
        Z(t1(2:end),(p+1):end) = Y(t2,:);
    end
end

if new_experiment
    off_diagonal = [tuda.P(triu(true(K),1)); tuda.P(tril(true(K),-1))];
    in_diagonal = tuda.P(eye(K)==1);
    tuda.P(triu(true(K),1)) = mean(off_diagonal);
    tuda.P(tril(true(K),-1)) = mean(off_diagonal);
    tuda.P(eye(K)==1) = mean(in_diagonal);
    tuda.Pi(:) = mean(tuda.Pi);
end

% Run TUDA inference
options.S = -ones(p+q);
if strcmp(options.classifier,'LDA') || (isfield(options,'encodemodel') && options.encodemodel)
    options.S(p+1:end,1:p) = 1;
else
    options.S(1:p,p+1:end) = 1;
end
options.updateObs = 0;
options.updateGamma = 1;
options.updateP = 1;
options.hmm = tuda;
options.repetitions = 0;
options.pca = 0;
options.cyc = 1;
options.tuda = 0;
[~,Gamma,~,vpath] = hmmmar(Z,T,options);
T = T - 1;

if parallel_trials
    if classification, error = zeros(max(T),K);
    else, error = zeros(max(T),q,K);
    end
else
    if classification, error = zeros(size(Gamma,1),K);
    else, error = zeros(size(Gamma,1),q,K);
    end
end
Betas = tudabeta(tuda);
if nargout>2
    for k = 1:K
      Ypred = X * Betas(:,:,k);
      if classification
          Ypred = continuous_prediction_2class(Ycopy,Ypred);
          Y = continuous_prediction_2class(Ycopy,Y);
          if q == 1
              e = abs(Y - Ypred) < 1e-4;
          else
              e = sum(abs(Y - Ypred),2) < 1e-4;
          end
      else
          e = (Y - Ypred).^2;
      end
      if parallel_trials
          maxT = max(T);
          me = zeros(maxT,1);
          ntrials = zeros(maxT,1);
          for j = 1:N
              t0 = sum(T(1:j-1));
              ind_1 = (1:T(j)) + t0;
              ind_2 = 1:length(ind_1);
              me(ind_2,:) = me(ind_2,:) + e(ind_1,:);
              ntrials(ind_2) = ntrials(ind_2) + 1;
          end
          e = me ./ ntrials;
      end
      if classification, error(:,k) = e;
      else, error(:,:,k) = e;
      end
    end

    error = squeeze(error);
end

end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Translate the coordinates back into the
% original image.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function B = getROIBBox(B, roi)

ratio = (roi([3 4]) - roi([1 2]))';
B = bsxfun(@times, B, ratio([1 2 1 2])');
B = bsxfun(@plus, B, roi([1 2 1 2]));


% VL_KDTREEQUERY Query KD-tree
%   [INDEX, DIST] = VL_KDTREEQUERY(KDTREE, X, Y) computes the nearest
%   column of X to each column of Y (in Euclidean distance). KDTREE is
%   a forest of kd-trees build by VL_KDTREEBUILD(). X is a
%   NUMDIMENSIONS x NUMDATA data matrix of class SINGLE or DOUBLE with
%   the data indexed by the kd-trees (it must be the same data matrix
%   passed to VK_KDTREEBUILD() to build the trees). Y is the
%   NUMDIMENSIONS x NUMQUERIES matrix of query points and must have
%   the same class of X. INDEX is a 1 x NUMQUERIES matrix of class
%   UINT32 with the index of the nearest column of X for each column
%   of Y. DIST is a 1 x NUMQUERIES vector of class SINGLE or DOUBLE
%   (depending on the class of X and Y) with the corresponding squared
%   Euclidean distances.
%
%   [INDEX, DIST] = VL_KDTREEQUERY(..., 'NUMNEIGHBORS', NN) can be
%   used to return the N nearest neighbors rather than just the
%   nearest one. In this case INDEX and DIST are NN x NUMQUERIES
%   matrices. Neighbors are returned by increasing distance.
%
%   VL_KDTREEQUERY(..., 'MAXNUMCOMPARISONS', NCOMP) performs at most
%   NCOMP comparisons for each query point. In this case the result is
%   only approximate (i.e. approximated nearest-neighbors, or ANNs)
%   but the speed can be greatly improved.
%
%   Options:
%
%   NumNeighbors::
%     Sets the number of neighbors to compute for each query point (by
%     default 1).
%
%   MaxNumComparisons::
%     Sets the maximum number of comparisons per query point. The
%     special value 0 means unbounded. The default is 0.
%
%   See also: VL_KDTREEBUILD(), VL_HELP().

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


function H = ldivide( F, G )
%.\   Pointwise DISKFUNV left divide.
%   F.\G if G is a DISKFUNV and F is a double this returns (1/F)*G
%
%   F.\G if G is a double and F is a DISKFUNV this returns G\F, but this
%   does not work if F becomes numerically close to zero.
%
%   F.\G is not allowed if both F and G are DISKFUNV objects.
%
%   F.\G is the same as the command LDIVIDE(F, G)
%
% See also RDIVIDE.

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

% Empty check:
if ( ( isempty(F) ) || ( isempty(G) ) )
    H = diskfunv();
    return
end

if ( isa( F, 'double' ) )                % DOUBLE .\ DISKFUNV
    nG = G.nComponents;
    Gc = G.components;
    H = G;
    for j = 1:nG
        H.components{j} = ldivide(F, Gc{j});
    end
elseif ( isa(G, 'double') )              % DISKFUNV .\ DOUBLE
    nF = F.nComponents;
    Fc = F.nComponents;
    H = F;
    for j = 1:nF
        H.components{j} = ldivide(Fc{j}, G);
    end
else                                     % DISKFUNV.\DISKFUNV
    nF = F.nComponents;
    nG = G.nComponents;
    if ( nF ~= nG )
        error('DISKFUN:DISKFUNV:ldivide:dimensionMismatch', ...
            'DISKFUNV do not have the same number of components.')
    end
    H = F;
    for j = 1 : nF
        H.components{j} = ldivide( F.components{j}, G.components{j} );
    end
end

end


function s = minus(f,g)
%-   Subtraction of two SINGFUN objects.
%   F - G subtracts G from F, where F and G are SINGFUN objects or scalars.
%
% See also PLUS.

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

% Call PLUS():
s = plus(f, -g);

end


%% Display Start message
disp('Running Fading Channel BER Simulation set')
disp('To produce smoother simulation curves, increase')
disp('maxNumErr inside Fading_Simulate.m to collect more')
disp('errors.')
disp('By default, this script does not run the Monte Carlo simulations.')
disp('It simply loads results from a previous run.')
sim_mode = input('Do you want to (R)un simulations or (L)oad results from disk? [R/L]','s');
if isempty(sim_mode)
    sim_mode = 'l';
end
sim_mode = lower(sim_mode);

%% Plot theoretical curves
SNRs = 0:25;
[h_fig, h_lines] = Fading_BER_Curves(SNRs);
%% Run Monte Carlo simulations
total_time = tic;
% Pre-allocate
fBER = zeros(6,length(SNRs));
figure(h_fig)
drawnow
if strcmp(sim_mode,'r')
    hold on
    % Create place-holder plots
    simLines = semilogy(SNRs, fBER,'*');
    fBER = Fading_Simulate(SNRs, simLines);
else
    % Load from Disk (NO SIMULATIONS ARE RUN)
    load fBER  % Loads simulation results from disk instead of running them
    hold on
    simLines = semilogy(SNRs, fBER,'*');
end
toc(total_time)

%% Add Legend
% Do MATLAB graphics magic to create concise legend
% See "Controling Legends" in MATLAB doc

% group lines together
simGrp = hggroup('DisplayName','Simulation');
theoGrp = hggroup('DisplayName','Theoretical');
set(simLines,'Parent',simGrp)
set(h_lines,'Parent',theoGrp)
set(get(get(simGrp,'Annotation'),'LegendInformation'),...
    'IconDisplayStyle','on'); % Include this hggroup in the legend
set(get(get(theoGrp,'Annotation'),'LegendInformation'),...
    'IconDisplayStyle','on'); % Include this hggroup in the legend
legend show

figure1 = h_fig;
% Create textbox
annotation(figure1,'textbox',[0.6046 0.6266 0.1248 0.04538],...
    'String',{'No Diversity'},...
    'EdgeColor','none',...
    'BackgroundColor',[1 1 1]);

% Create textbox
annotation(figure1,'textbox',[0.63 0.4612 0.07359 0.04538],...
    'String',{'L = 2'},...
    'EdgeColor','none',...
    'BackgroundColor',[1 1 1]);

% Create textbox
annotation(figure1,'textbox',[0.6018 0.3718 0.07359 0.04538],...
    'String',{'L = 3'},...
    'EdgeColor','none',...
    'BackgroundColor',[1 1 1]);

% Create textbox
annotation(figure1,'textbox',[0.321 0.2733 0.08804 0.04538],...
    'String',{'AWGN'},...
    'EdgeColor','none',...
    'BackgroundColor',[1 1 1]);

% Create textarrow
annotation(figure1,'textarrow',[0.2853 0.4502],[0.5005 0.5],...
    'TextEdgeColor','none',...
    'TextBackgroundColor',[1 1 1],...
    'String',{'L = 4'});

% Create textarrow
annotation(figure1,'textarrow',[0.2912 0.4502],[0.4445 0.4455],...
    'TextEdgeColor','none',...
    'TextBackgroundColor',[1 1 1],...
    'String',{'L = 6'});

% Create textarrow
annotation(figure1,'textarrow',[0.3091 0.4517],[0.3945 0.3955],...
    'TextEdgeColor','none',...
    'TextBackgroundColor',[1 1 1],...
    'String',{'L = 8'});

figure(h_fig)


function out = mrdivide(T,S)
% implements T / S
%

if isa(S,'double')

  T.M = T.M / S;
  out = T;

elseif isa(S,'tensor')

  T.M = T.M / S.M;
  out = T;

end


function [outputStruct]=febioStructTemplate_v2p5(varargin)

switch nargin
    case 0
        inputStruct=[];
    case 1
        inputStruct=varargin{1};
    otherwise
        error('Wrong number of input arguments');
end

%% Set febio_spec version
febio_spec.ATTR.version='2.5';

%% Module section
febio_spec.Module.ATTR.type='solid'; %Use default set

%% Control section

febio_spec.Control.analysis.ATTR.type='static';
% febio_spec.Control.title='temp';
febio_spec.Control.time_steps=10;
febio_spec.Control.step_size=0.1;
febio_spec.Control.dtol=0.001;
febio_spec.Control.etol=0.01;
febio_spec.Control.rtol=0;
febio_spec.Control.lstol=0.9;
febio_spec.Control.time_stepper.dtmin=febio_spec.Control.step_size/3;
febio_spec.Control.time_stepper.dtmax=febio_spec.Control.step_size*3; %Constant
% febio_spec.Control.time_stepper.dtmax.ATTR.lc=1; %Load curve based
% febio_spec.Control.time_stepper.dtmax.VAL=0.1; %Load curve based
febio_spec.Control.time_stepper.max_retries=5;
febio_spec.Control.time_stepper.opt_iter=10;
febio_spec.Control.max_refs=15;
febio_spec.Control.max_ups=10;
febio_spec.Control.optimize_bw=0;
% febio_spec.Control.restart.ATTR.file='restartDumpFile.dmp'; %On with file specified
% febio_spec.Control.restart.VAL=0; %Off
febio_spec.Control.plot_level='PLOT_MAJOR_ITRS';
febio_spec.Control.plot_range=[0,-1];
febio_spec.Control.plot_stride=1;
febio_spec.Control.plot_zero_state=0;
febio_spec.Control.cmax=1e5;
febio_spec.Control.print_level='PRINT_MINOR_ITRS';
febio_spec.Control.min_residual=1e-20;
% febio_spec.Control.integration='N/A';
febio_spec.Control.output_level='OUTPUT_MAJOR_ITRS';

%% Globals section

febio_spec.Globals.Constants.T=0;
febio_spec.Globals.Constants.R=0;
febio_spec.Globals.Constants.Fc=0;

%% Material section
% febio_spec.Material.material{1}.ATTR.type='Ogden';
% febio_spec.Material.material{1}.ATTR.id=1;
% febio_spec.Material.material{1}.c1=1e-3;
% febio_spec.Material.material{1}.m1=6;
% febio_spec.Material.material{1}.c2=1e-3;
% febio_spec.Material.material{1}.m2=-6;
% febio_spec.Material.material{1}.k=1e-1;

%% LoadData section

febio_spec.LoadData.loadcurve{1}.ATTR.id=1;
febio_spec.LoadData.loadcurve{1}.ATTR.type='linear';
febio_spec.LoadData.loadcurve{1}.point.VAL=[0 0; 1 1];

%% Output section

% Plot file
febio_spec.Output.plotfile.ATTR.type='febio';
febio_spec.Output.plotfile.var{1}.ATTR.type='displacement';
febio_spec.Output.plotfile.var{2}.ATTR.type='stress';
febio_spec.Output.plotfile.var{3}.ATTR.type='strain energy density';
febio_spec.Output.plotfile.var{4}.ATTR.type='relative volume';
febio_spec.Output.plotfile.var{5}.ATTR.type='reaction forces';
febio_spec.Output.plotfile.var{6}.ATTR.type='contact pressure';

%% Fill in missing if input structure is provided

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


function plotBoundingBox(img, bb, score, colors)
% Visualices and image and a set of bounding boxes
%
%   img = image
%   bb = each row is [xmin ymin xmax ymax]

Nbb = size(bb,1);
if nargin==2
    score = 3*ones(Nbb,1);
end

if ~isempty(img)
    image(img); axis('off'); axis('equal')
    if size(img,3)==1; colormap(gray(256)); end
    hold on
end

if nargin<4
    colors = 'rrgbcmy';
end
for i = 1:Nbb
    plot([bb(i,1) bb(i,3) bb(i,3) bb(i,1) bb(i,1)], [bb(i,2) bb(i,2) bb(i,4) bb(i,4) bb(i,2)], 'k', 'linewidth', score(i))
    plot([bb(i,1) bb(i,3) bb(i,3) bb(i,1) bb(i,1)], [bb(i,2) bb(i,2) bb(i,4) bb(i,4) bb(i,2)], colors(mod(i,6)+1), 'linewidth', score(i)-2)
end

%title(sprintf('There are %d boxes', Nbb))


function [] = showTSDF(sdf, grid)
sdf(or(sdf <= grid.disp_range(1), sdf >= grid.disp_range(2))) = nan;

h = slice(grid.x, grid.y, grid.z, sdf, [], [], grid.z);

set(h, 'EdgeColor','none', 'FaceColor','interp')
set(h, 'EdgeColor','none')
alpha(.2)
axis equal
end


function [interpolated,discarded] = Interpolate(samples,timestamps,varargin)

%Interpolate - Interpolate samples (positions, spikes, LFP, etc.) at given timestamps.
%
% Interpolate samples (positions, spikes, LFP, etc.) at given timestamps. As a special
% case, a point process can also be 'interpolated' by changing each original timestamp
% t to the closest target timestamp t* such that t* <= t.
%
%  USAGE
%
%    [interpolated,discarded] = Interpolate(samples,timestamps,<options>)
%
%    samples        a list of samples to interpolate
%    timestamps     a list of timestamps
%    <options>      optional list of property-value pairs (see table below)
%
%    =========================================================================
%     Properties    Values
%    -------------------------------------------------------------------------
%     'type'        'linear' if samples are linear values (default), or
%                   'circular' otherwise
%     'trim'        discard ('on', default) or keep ('off') samples that would
%                   require extrapolation. If kept, these samples are set to
%                   NaN (this can be useful when the output is required to
%                   have the same size as the input) (default = 'on')
%     'maxGap'      time gaps between original and target times exceeding this
%                   threshold will be ignored (default = Inf)
%    =========================================================================
%
%  OUTPUT
%
%    interpolated   list of interpolated samples
%    discarded      logical vector indicating for which timestamps the samples were
%                   not interpolated (see option 'maxGap')
%
%  SEE
%
%    See also Diff.

% Copyright (C) 2004-2011 by Michaël Zugaro
%
% 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.

% Default values
trim = 'on';
maxGap = Inf;
type = 'linear';

if nargin < 2 | mod(length(varargin),2) ~= 0,
	error('Incorrect number of parameters (type ''help Interpolate'' for details).');
end
if ~isdvector(timestamps),
	error('Incorrect timestamps - should be a vector (type ''help Interpolate'' for details).');
end
timestamps = timestamps(:);

% Parse parameter list
for j = 1:2:length(varargin),
	if ~ischar(varargin{j}),
		error(['Parameter ' num2str(j+2) ' is not a property (type ''help Interpolate'' for details).']);
	end
	switch(lower(varargin{j})),
		case 'type',
			type = varargin{j+1};
			if ~isstring_FMAT(type,'linear','circular'),
				error('Incorrect value for property ''type'' (type ''help Interpolate'' for details).');
			end
		case 'trim',
			trim = lower(varargin{j+1});
			if ~isstring_FMAT(trim,'on','off'),
				error('Incorrect value for property ''trim'' (type ''help Interpolate'' for details).');
			end
		case 'maxgap',
			maxGap = varargin{j+1};
			if ~isdscalar(maxGap,'>0'),
				error('Incorrect value for property ''maxGap'' (type ''help Interpolate'' for details).');
			end
		otherwise,
			error(['Unknown property ''' num2str(varargin{j}) ''' (type ''help Interpolate'' for details).']);
	end
end

interpolated = [];
if isempty(timestamps) | isempty(samples), return; end

pointProcess = isvector(samples);

% Determine which target timestamps are too far away from sample timestamps (isolated) and should be discarded
[unused,isolated] = Match(timestamps,samples(:,1),'match','closest','error',maxGap);

if pointProcess,
	% 'Interpolate' samples at timestamps (see help above)
	[interpolated,unused,discarded] = Match(samples,timestamps,'error',maxGap);
else
	% Determine which timestamps would require extrapolation
	outside = logical(zeros(size(timestamps)));
	if strcmp(trim,'on'),
		outside = timestamps<samples(1,1)|timestamps>samples(end,1);
	end
	% Discard isolated timestamps and timestamps that would require extrapolation
	discarded = outside|isolated;
	timestamps(discarded) = [];
	% Circular data?
	if strcmp(type,'circular'),
		range = isradians(samples(:,2:end));
		samples(:,2:end) = exp(i*samples(:,2:end));
	end
	% Interpolate samples at timestamps
	interpolated = [timestamps interp1(samples(:,1),samples(:,2:end),timestamps)];
	% Circular data?
	if strcmp(type,'circular'),
		interpolated(:,2:end) = wrap(angle(interpolated(:,2:end)),range);
	end
end


function [hs,probs] = forestApply( data, forest, maxDepth, minCount )
% Apply learned forest classifier.
%
% USAGE
%  [hs,probs] = forestApply( data, forest, [maxDepth], [minCount] )
%
% INPUTS
%  data     - [NxF] N length F feature vectors
%  forest   - learned forest classification model
%  maxDepth - [] maximum depth of tree
%  minCount - [] minimum number of data points to allow split
%
% OUTPUTS
%  hs       - [Nx1] predicted output labels
%  probs    - [NxH] predicted output label probabilities
%
% EXAMPLE
%
% See also forestTrain
%
% Piotr's Image&Video Toolbox      Version 3.01
% Copyright 2012 Piotr Dollar.  [pdollar-at-caltech.edu]
% Please email me if you find bugs, or have suggestions or questions!
% Licensed under the Simplified BSD License [see external/bsd.txt]
if(nargin<3 || isempty(maxDepth)), maxDepth=0; end
if(nargin<4 || isempty(minCount)), minCount=0; end
assert(isa(data,'single')); M=length(forest);
for i=1:M, tree=forest(i);
  if(maxDepth>0), tree.child(tree.depth>=maxDepth) = 0; end
  if(minCount>0), tree.child(tree.count<=minCount) = 0; end
  ids = forestInds(data,tree.thrs,tree.fids,tree.child);
  p=tree.distr(ids,:); if(i==1), probs=p; else probs=probs+p; end
end
[~,hs] = max(probs,[],2);
end


% ------------------------------------------------------------------------
%  Copyright (C)
%  Universitat Politecnica de Catalunya BarcelonaTech (UPC) - Spain
%  University of California Berkeley (UCB) - USA
%
%  Jordi Pont-Tuset <jordi.pont@upc.edu>
%  Pablo Arbelaez <arbelaez@berkeley.edu>
%  June 2014
% ------------------------------------------------------------------------
% This file is part of the MCG package presented in:
%    Arbelaez P, Pont-Tuset J, Barron J, Marques F, Malik J,
%    "Multiscale Combinatorial Grouping,"
%    Computer Vision and Pattern Recognition (CVPR) 2014.
% Please consider citing the paper if you use this code.
% ------------------------------------------------------------------------
function [f_lp, f_ms, cands, start_ths, end_ths] = full_cands_from_hiers(lps,ms,ths,n_cands)

n_hiers  = length(ms);
n_r_cand = size(n_cands,1);
assert(size(n_cands,2)==n_hiers)

% Scan all hierarchies
all_cands = cell(n_hiers,n_r_cand);
for ii=1:n_hiers
    if size(ms{ii},1)>0
        n_r_hier = ms{ii}(end,end);
        assert(length(unique(lps(:,:,ii)))==ms{ii}(1,end)-1)
        assert(ms{ii}(1,end)-1+size(ms{ii},1)==n_r_hier)

        % Get all pairs of neighboring leave regions
        [~, idx_neighbors] = seg2gridbmap(lps(:,:,ii));
        K = max(idx_neighbors.matrix_max(:)) + 1;
        neigh_pairs = unique(idx_neighbors.matrix_min+K*idx_neighbors.matrix_max);
        neigh_pairs(neigh_pairs==0) = [];
        neigh_pairs_min = mod(neigh_pairs,K);
        neigh_pairs_max = (neigh_pairs-neigh_pairs_min)/K;

        if isrow(neigh_pairs_min)
            neigh_pairs_min = neigh_pairs_min';
        end
        if isrow(neigh_pairs_max)
            neigh_pairs_max = neigh_pairs_max';
        end

        % Get the 'n_cands' top candidates from each hierarchy
        % Singletons
        if n_r_hier<=n_cands(1,ii)
            all_cands{ii,1} = (1:n_r_hier)';
        else
            all_cands{ii,1} = (n_r_hier-n_cands(1,ii)+1:n_r_hier)';
        end

    %     % Pairs, triplets
    %     [all_cands{ii,2}, all_cands{ii,3}] = ...
    %         mex_get_tree_cands(double(lps(:,:,ii))-1, double(ms{ii})-1,...
    %                              neigh_pairs_min-1, neigh_pairs_max-1,...
    %                              [n_cands(2,ii), n_cands(3,ii)]);

        % Pairs, triplets, etc.
        all_cands(ii,2:n_r_cand) = ...
        mex_get_tree_cands(double(lps(:,:,ii))-1, double(ms{ii})-1,...
                             neigh_pairs_min-1, neigh_pairs_max-1,...
                             n_cands(2:end,ii));
    else
        all_cands{1} = 1;
    end
end

% Put all them together (for each hierarchy)
full_cands = cell(n_hiers,1);
for ii=1:n_hiers
    % Pre-allocate
    n_tot_cand = 0;
    for jj=1:n_r_cand
        n_tot_cand = n_tot_cand + size(all_cands{ii,jj},1);
    end
    full_cands{ii} = zeros(n_tot_cand,n_r_cand);

    if n_tot_cand
        % Store
        curr_n = 0;
        for jj=1:n_r_cand
            if size(all_cands{ii,jj},1)>0
                full_cands{ii}(curr_n+1:curr_n+size(all_cands{ii,jj},1),1:jj) = all_cands{ii,jj};
                curr_n = curr_n+size(all_cands{ii,jj},1);
            end
        end
    end
end

% Compute the 'unique' hierarchy
lps = double(lps);
luts = cell(n_hiers,1);
for ii=1:n_hiers
    needed_regs = unique(full_cands{ii}(:));
    needed_regs(needed_regs==0) = [];

    if isempty(needed_regs) || isempty(ms{ii})
        lps(:,:,ii) = ones(size(lps,1),size(lps,2));
    else
        [lps(:,:,ii),ms{ii},luts{ii}] = mex_prune_tree_to_regions(lps(:,:,ii)-1,ms{ii}-1,needed_regs-1);
    end
end

% Fuse
[f_lp, f_ms] = fuse_bpts(lps,ms);

% Reduce zeros
f_ms = f_ms(:,logical(sum(f_ms)>0));

% Redo cands (relabel)
n_int = length(unique(f_lp));
curr_n_regs = n_int;
cands = [];
for jj=1:n_hiers
    if ~isempty(ms{jj})
        curr_part = lps(:,:,jj);
        assert(max(curr_part(:))+size(ms{jj},1)==size(luts{jj},1))
        new_cands = zeros(size(full_cands{jj}));
        for xx=1:size(full_cands{jj},1)
            for yy=1:size(full_cands{jj},2)
                if full_cands{jj}(xx,yy)>0
                    pos = logical(full_cands{jj}(xx,yy)==luts{jj}(:,2));
                    if sum(pos)~=1
                        error('Oh oh')
                    end
                    new_cands(xx,yy) = curr_n_regs+luts{jj}(pos,1);
                end
            end
        end
        cands = [cands; new_cands]; %#ok<AGROW>
        curr_n_regs = curr_n_regs + ms{jj}(end,end);
        % Sanity check
        assert(ms{jj}(end,end)==length(unique(lps(:,:,jj))) + size(ms{jj},1))
    else
        if ~isempty(full_cands{jj})
            cands = [cands; full_cands{jj}]; %#ok<AGROW>
        end
    end
end

% Sanity checks
if ~isempty(cands)
    assert(isequal(size(cell2mat(full_cands)), size(cands)))
else
    assert(isempty(cell2mat(full_cands)))
end

% Redo ths
start_ths = zeros(1,n_int);
end_ths = zeros(1,n_int);
for jj=1:n_hiers
    if ~isempty(ms{jj})
        curr_part = lps(:,:,jj);
        assert(max(curr_part(:))+size(ms{jj},1)==size(luts{jj},1))

        start_ths = [start_ths ths{jj}.start_ths(luts{jj}(:,2))]; %#ok<AGROW>
        end_ths   = [end_ths ths{jj}.end_ths(luts{jj}(:,2))]; %#ok<AGROW>
    end
end
assert(length(start_ths)==n_int+size(f_ms,1))

end


% ENVPROJ - plot envelopes of projections of selected ICA component
%             projections against envelope of the original data
%
% Usage:    >> [envdata] = envproj(data,weights,compnums);
%           >> [envdata] = envproj(data,weights,compnums, ...
%                                  title,limits,chanlist,compnames,colors);
% Inputs:
%   data      = RUNICA input data (chans,frames) <- best one epoch only!
%   weights   = unmixing weight matrix (RUNICA weights*sphere)
%   compnums  = list of component numbers to project and plot
%
% Optional inputs:
%   title     = 'fairly short plot title' (in quotes) (0 -> none)
%   limits    = [xmin xmax ymin ymax] (x's in msec)
%                       (0 or both y's 0 -> [min max])
%   chanlist  = list of data channels to use for max/min (0 -> all)
%   compnames = file of component labels (exactly 5 chars per line,
%               trailing '.' = space) (default|0 -> compnums)
%   colors    = file of color codes, 3 chars per line  ('.' = space)
%                       (0 -> default color order (black/white first))
%
% Output:
%   envdata   = [2,(frames*length(compnums)+1)] envelopes of data, comps.
%
% Author: Scott Makeig, SCCN/INC/UCSD, La Jolla, 1/1997
%
% See also: ENVTOPO

% Copyright (C) 01-23-97 Scott Makeig, SCCN/INC/UCSD, scott@sccn.ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

% 03-19-97 use datamean instead of frames/baseframes, diag(COV) for VAR -sm
% 04-03-97 changed name to ENVPROJ -sm
% 05-20-97 used sum-of-squares for var instead of DIAG to allow long data
%          read MAXPLOTDATACHANS from icadefs.m -sm
% 06-07-97 changed order of args to conform to runica -sm
% 06-18-97 read MAXENVPLOTCHANS instead of MAXPLOTDATACHANS -sm
% 07-23-97 dropped datamean from args; mean is distributed among components -sm
% 10-11-97 range of max/min for default ylimits over chanlist only! -sm
% 11-05-97 disallowed white lines unless axis color is white -sm & ch
% 11-13-97 rm'd errorcode variable to improve limits handling -sm
% 11-18-97 added legend to plot; varied line types -sm
% 11-30-97 added f=figure below to keep previous plot from being altered -sm
% 12-01-97 added thicker lines for data envelope -sm
% 12-08-97 debugged thicker lines for data envelope -sm
% 12-10-97 changed f=figure below to f=gcf to avoid matlab bug (gcf confusion) -sm
% 12-10-97 implemented compnames arg -sm
% 12-13-97 took out compnames=compnames'; bug -sm
% 02-06-98 added 'show-largest' feature to legend when numcomps > 7 -sm
% 02-09-98 fixed numcomps bug -sm
% 02-12-98 test for outofbounds compnums early -sm
% 04-28-98 made to work for rectangular weights -sm
% 06-05-98 made NEG_UP optional -sm
% 02-22-99 added FILL mode default when numcomps==1 -sm
% 03-14-99 made envelope finding code more efficient -sm
% 12-19-00 updated ICAPROJ args -sm
% 01-25-02 reformated help & license, added links -ad

function [envdata] = envproj(data,weights,compnums,titl,limits,chanlist,compnames,colors)

FILL = 1; % 1;  % 1 = fill in component envelope unless ncomps>1
DATA_LINEWIDTH = 1.5; % 2
COMP_LINEWIDTH = 1.5; % 1
MAXENVPLOTCHANS = 256;

if nargin < 3,
    help envproj
    fprintf('envproj(): must have at least three arguments.\n');
    return
end

icadefs        % load ENVCOLORS & MAXENVPLOTCHANS default variables
MAX_LEG = 7;   % maximum number of component line types to label in legend
NEG_UP = 0;    % 1 = plot negative up

%
%%%%%%%%%%%% Substitute for omitted arguments %%%%%%%%%%%%%%%%%%%%%%%%
%
if nargin < 8,
    colors = 'envproj.col';
elseif colors(1)==0,
    colors = 'envproj.col';
end

[chans,frames] = size(data);

if nargin < 7
   compnames = 0;
end

if nargin < 6
    chanlist = 0;
end
if nargin < 5,
    limits = 0;
end
if nargin < 4,
    titl = 0;
end
%
%%%%%%%%%%%%%%%%%%%%%%%% Test data size %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
[wr,wc]       = size(weights);
%
%%%%%%%%%%%%%%%% Substitute for zero arguments %%%%%%%%%%%%%%%%%%%%%%%%%
%
if chanlist == 0,
    chanlist = [1:chans];
end
if compnums == 0,
    compnums = [1:wr];
end
if size(compnums,1)>1,        % handle column of compnums !
    compnums = compnums';
end
numcomps = length(compnums);
if numcomps > MAXENVPLOTCHANS,
    fprintf(...
'envproj(): cannot plot more than %d channels of data at once.\n',...
                  MAXENVPLOTCHANS);
    return
end

if max(compnums)>wr
 fprintf('\nenvproj(): Component index %d out of bounds (1:%d).\n',...
                                             max(compnums),wr);
 return
end

if min(compnums)<1,
 fprintf('\nenvproj(): Component index %d out of bounds (1:%d).\n',...
                                             min(compnums),wr);
 return
end

if FILL>0 && numcomps == 1
   FILL = 1;
else
   FILL = 0;
end
%
%%%%%%%%%%%%%%%%%%%% Read and adjust limits %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
  if limits==0,
    xmin=0;xmax=1;
    ymin=min(min(data(chanlist,:)));
    ymax=max(max(data(chanlist,:)));
  else
    if length(limits)~=4,
        fprintf( ...
 'envproj(): limits should be 0 or an array [xmin xmax ymin ymax].\n');
        return
      end
        if limits(1,1) == 0 && limits(1,2) ==0,
            xmin=0;
            xmax=0;
        else
            xmin = limits(1,1);
            xmax = limits(1,2);
        end
         if limits(1,3) == 0 && limits(1,4) ==0,
            ymin=0;
            ymax=0;
        else
            ymin = limits(1,3);
            ymax = limits(1,4);
        end
  end

  if xmax == 0 && xmin == 0,
    x = (0:1:frames-1);
    xmin = 0;
    xmax = frames-1;
  else
    dx = (xmax-xmin)/(frames-1);
    x=xmin*ones(1,frames)+dx*(0:frames-1); % construct x-values
  end

  if ymax == 0 && ymin == 0,
    ymax=max(max(data(chanlist,:)));
    ymin=min(min(data(chanlist,:)));
  end

%
%%%%%%%%%%%%%%%%%%%% Read the color names %%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
    if ~ischar(colors)
        fprintf('envproj(): color file name must be a string.\n');
        return
    end
    cid = fopen(colors,'r');
    if cid <3,
        fprintf('envproj(): cannot open file %s.\n',colors);
        return
    else
        colors = fscanf(cid,'%s',[3 MAXENVPLOTCHANS]);
        colors = colors';
        [r c] = size(colors);
        for i=1:r
            for j=1:c
                if colors(i,j)=='.',
                    colors(i,j)=' ';
                end
            end
        end
    end
[rr cc] = size(colors);

%
%%%%%%%%%%%% Compute projected data for single components %%%%%%%%%%%%%
%
projdata = [data(chanlist,:)];
envdata = [min(projdata); max(projdata)]; % begin with envelope of data
fprintf('envproj(): Projecting component(s) ');
maxvars = zeros(1,length(compnums));
n=1;
for c=compnums,            % for each component
  fprintf('%d ',c);
  % [icaproj] = icaproj(data,weights,compindex); % new arg order 12/00
  proj = icaproj(data,weights,c); % let offsets be
                                         % distributed among comps.
  [val,i] = max(sum(proj.*proj)); % find max variance
  maxvars(n) = val;
  proj = proj(chanlist,:);
  projdata = [projdata proj];
  envtmp = [ min(proj) ; max(proj)];
  envdata = [envdata envtmp];
                 % append envelope of projected data sets onto envdata
  % Note: size(envdata) = [length(chanlist)  frames*(numcomps+1)]
  n = n+1;
end
fprintf('\n');
%
%%%%%%%%%%%%%%%%%%%%%%%% Make the plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
if ~ischar(titl)
  if titl==0,
    titl = ' ';
  else
    fprintf('envproj(): titl unrecognized.\n');
    return
  end
end

set(gcf,'Color',BACKCOLOR); % set the background color
set(gca,'Color','none'); % set the axis color to the background color
if NEG_UP
  set(gca,'Ydir','reverse');
end
n = 1;
H = zeros(1,numcomps+1);

for c=1:numcomps+1;
  %
  % Plot envelopes
  %
  if n <= 6
    if n == 1              % thick lines, store H for legend()
      H(n)=plot(x,envdata(1,(c-1)*frames+1:c*frames)',...
                                     colors(c),'Linewidth',DATA_LINEWIDTH);
      hold on;
           plot(x,envdata(2,(c-1)*frames+1:c*frames)',...
                                     colors(c),'Linewidth',DATA_LINEWIDTH);
    else
       if FILL
            fillx = [x x(frames:-1:1)];
            filly = [envdata(1,(c-1)*frames+1:c*frames) ...
                            envdata(2,c*frames:-1:(c-1)*frames+1)];
            i = find(isnan(filly)==1);
            if ~isempty(i)
                fprintf('Replacing %d NaNs in envelope with 0s.\n',length(i)/2);
                filly(i)=0;
            end
            H(n) = fill(fillx,filly,colors(c));
       else
            H(n)= plot(x,envdata(1,(c-1)*frames+1:c*frames)',...
                                     colors(c),'Linewidth',COMP_LINEWIDTH);
             hold on;
            plot(x,envdata(2,(c-1)*frames+1:c*frames)',...
                                     colors(c),'Linewidth',COMP_LINEWIDTH);
       end
    end
  else
    H(n)= plot(x,envdata(1,(c-1)*frames+1:c*frames)',...
                                     colors(c),'LineStyle',':','LineWidth',DATA_LINEWIDTH);
    hold on;
          plot(x,envdata(2,(c-1)*frames+1:c*frames)',...
                                     colors(c),'LineStyle',':','LineWidth',DATA_LINEWIDTH);
  end
  n = n+1;
end
set(gca,'Color','none'); % set the axis color to the background color

l=xlabel('Time (ms)');      % xaxis label
set(l,'FontSize',14);

l=ylabel('Potential (uV)'); % yaxis label
set(l,'FontSize',14);

if xmax > 0  && xmin < 0
  plot([0 0],[ymin ymax],'k','linewidth',1.5); % plot vertical line at time 0
end

if ymax ~= 0 |ymin~= 0,
    axis([min(x),max(x),ymin,ymax]);
else
    axis([min(x),max(x),min(envdata(1,:)'),max(envdata(2,:)')]);
end
legtext = [ 'Data ' ];
if compnames(1) ~= 0
    pid = fopen(compnames,'r');
    if pid < 3
       fprintf('envproj(): file %s not found.\n',compnames);
       return
    end
    compnames = fscanf(pid,'%s',[5 numcomps]);
    compnames = [ ['Data.']' compnames];
    compnames = compnames';
    if size(compnames,1) ~= numcomps+1
      fprintf('envproj(): no. of compnames must equal no. of compnums.\n');
      return
    end
    for c=1:5 % remove padding with .'s
      for r = 1:size(compnames,1)
         if compnames(r,c) == '.'
           compnames(r,c) = ' ';
         end
      end
    end
    legtext = compnames;
else
  legtext = ['Data'];
  for c = compnums
      legtext = strvcat(legtext,int2str(c));
  end
end

if numcomps<MAX_LEG+1
  if FILL <= 0  % no legend in FILL mode
       l=legend(H,legtext,0);      % plot legend
  end
else
  fprintf('Finding largest components for legend...\n');
  [maxvars,i] = sort(maxvars);
  maxvars = maxvars(length(maxvars):-1:1); % sort large-to-small
  i= i(length(i):-1:1);
  H = [H(1) H(i+1)];
  H = H(1:MAX_LEG+1);
  legtext = [legtext(1,:);legtext(i+1,:)];
  legtext = legtext(1:MAX_LEG+1,:);
  legend(H,legtext,0); % MAX_LEG largest-peaked comps
end

set(gca,'FontSize',12);
fprintf('If desired, use mouse to move legend or >> delete(legend).\n');

%
%%%%%%%%%%%%% Compute percentage of variance accounted for %%%%%%%%%%%%
%
sumdata = zeros(length(chanlist),frames);
for e=2:numcomps+1,              % sum the component activities
    sumdata = sumdata + projdata(:,(e-1)*frames+1:e*frames);
end

sigssqr = sum(data(chanlist,:).*data(chanlist,:))/(length(chanlist)-1);
dif    = data(chanlist,:)-sumdata;
difssqr = sum(dif.*dif)/(length(chanlist)-1);
pvaf   = round(100.0*(1.0-difssqr/sigssqr)); % % variance accounted for
rtitl = ['(' int2str(pvaf) '%)'];
%titl = [titl '   ' rtitl];

t=title(titl);              % plot title
set(t,'FontSize',14);


function cleaned_matches = removeOutliers(I1_l, I1_r, I2_l, I2_r, matches, match_params)
%REMOVEOUTLIERS Performs outliers removal by applying normalized cross-correlation
% score between patches around the matched points.
%
% INPUT:
%
%   - I1_l: left image for time t-1
%   - I1_r: right images for time t-1
%   - I2_l: left image for time t
%   - I2_r: right images for time t
%   - matches (1,N): strcutre of matched points
%       - pt1_l: keypoint in left image at time t-1
%       - pt1_r: keypoint in right image at time t-1
%       - pt2_l: keypoint in left image at time t
%       - pt2_r: keypoint in right image at time t
%   - match_params: structure comprising of following
%       - match_ncc_window: window size of the patch for normalized cross-correlation
%       - match_ncc_tolerance: threshold for normalized cross-correlation
%
% OUTPUT:
%   - cleaned_matches(1, N2): processed structure of matched points
%       - pt1_l: location of keypoint in left image at time t-1
%       - pt1_r: location of keypoint in right image at time t-1
%       - pt2_l: location of keypoint in left image at time t
%       - pt2_r: location of keypoint in right image at time t

% initialize parameters
ncc_window = match_params.match_ncc_window;
ncc_tolerance = match_params.match_ncc_tolerance;

% store indices of matches that are valid
valid_match_indices = ones(length(matches), 1, 'logical');

% for all matches do
parfor i = 1:length(matches)
    match = matches(i);

    % verify match by computing NCC score
    % a) left frame at t-1 with right frame at t-1
    validity = verifyMatchNCC(I1_l, I1_r, match.pt1_l.location, match.pt1_r.location, ...
                                ncc_window, ncc_tolerance);
    if not(validity)
        valid_match_indices(i) = 0;
        continue;
    end

    % b) right frame at t-1 with right frame at t
    validity = verifyMatchNCC(I1_r, I2_r, match.pt1_r.location, match.pt2_r.location, ...
                                ncc_window, ncc_tolerance);
    if not(validity)
        valid_match_indices(i) = 0;
        continue;
    end

    % c) right frame at t with left frame at t
    validity = verifyMatchNCC(I2_r, I2_l, match.pt1_r.location, match.pt2_l.location, ...
                                ncc_window, ncc_tolerance);
    if not(validity)
        valid_match_indices(i) = 0;
        continue;
    end

    % d) left frame at t with left frame at t-1
    validity = verifyMatchNCC(I2_l, I1_l, match.pt2_l.location, match.pt1_l.location, ...
                                ncc_window, ncc_tolerance);
    if not(validity)
        valid_match_indices(i) = 0;
        continue;
    end
end

% cleaned matched points after NCC
cleaned_matches = matches(valid_match_indices);

end


function alpha_star=getAlpha_star(mask)
% alpha_star=getAlpha_star(mask) get the pri-known alpha values according
% to the mask. See equation (6) in our iccv2009 paper.
%
% Input arguments:
% mask:   MxN matrix specifying scribbles, with 1 foreground, -1 background
%         and 0 otherwise
%
% Output arguments:
% alpha_star:     (MxN) matrix showing the prio-known value of alpha.
%                 The value is 1 for foreground scribble pixels, and 0
%                 otherwise
%
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% @InProceedings{ZhengICCV09,
%   author = {Yuanjie Zheng and Chandra Kambhamettu},
%   title = {Learning Based Digital Matting},
%   booktitle = {The 20th IEEE International Conference on Computer Vision},
%   year = {2009},
%   month = {September--October}
% }
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% Copyright Yuanjie Zheng @ PICSL @ UPenn on May 9th, 2011
% zheng.vision@gmail.com
% http://sites.google.com/site/zhengvision/
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %

disp('Computing preknown alpha values ... ...')

alpha_star=zeros(size(mask,1),size(mask,2));
alpha_star(mask>0)=1;
alpha_star(mask<0)=-1;


classdef WrapperResFile < FileReader

    properties (Access = private)
       dataBase
       stress
       exponent
       alpha
       lineNumber
       linesEndValue
    end

    properties (Access = private)
       nElem
       nNodes
       dimension
    end

    methods (Access = public)

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

        function read(obj)
            obj.openFile();
            obj.readStress();
            obj.readStrain();
            obj.readDisplacement();
            obj.readStress();
            obj.readStrain();
            obj.readDisplacement();
            obj.readAmplifiedStressNormP();
            %obj.readCompliance();
            obj.readAngle();
            obj.readAngle();
            obj.readAmplifiedStressNormP();
            obj.readDensity();
            obj.readScalarInNodes();
            obj.readScalarInNodes();
            obj.readScalarInGauss();
            obj.readScalarInNodes();
            obj.readScalarInNodes();
            obj.closeFile();
        end

        function d = getDataBase(obj)
            d = obj.dataBase;
        end

    end

    methods (Access = private)

        function init(obj,cParams)
            obj.filePath  = cParams.filePath;
            obj.nElem     = cParams.nElem;
            obj.nNodes    = cParams.nNodes;
            obj.dimension = cParams.dimension;
            obj.lineNumber = 14;
            obj.linesEndValue = 2;
        end

        function readStress(obj)
            obj.readTensorFieldInGauss()
        end

        function readStrain(obj)
            obj.readTensorFieldInGauss()
        end

        function readDisplacement(obj)
            obj.readVectorFieldInNodes();
        end

        function readCompliance(obj)
            obj.readScalarInGauss();
        end

        function readAmplifiedStressNormP(obj)
            obj.readScalarInGauss();
        end

        function readAngle(obj)
            obj.readVectorFieldInGauss();
        end

        function readDensity(obj)
            obj.readScalarInGauss();
        end

        function readLevelSet(obj)
            obj.readScalarInNodes();
        end

        function readVectorFieldInGauss(obj)
            obj.readVectorInGauss(obj.dimension)
        end

        function readVectorFieldInNodes(obj)
            obj.readVectorInNodes(obj.dimension)
        end

        function readTensorFieldInGauss(obj)
            switch obj.dimension
                case 2
                    nComp = 3;
                case 3
                    nComp = 6;
            end
            obj.readVectorInGauss(nComp);
        end

        function readScalarInGauss(obj)
            nLines = obj.nElem;
            linesJump = 2;
            nComp = 1;
            obj.readField(obj.lineNumber,nLines,linesJump,nComp);
            obj.updateLineNumber(nLines + linesJump + obj.linesEndValue);
        end

        function readVectorInGauss(obj,nComp)
            nLines = obj.nElem;
            linesJump = 3;
            obj.readField(obj.lineNumber,nLines,linesJump,nComp);
            obj.updateLineNumber(nLines + linesJump + obj.linesEndValue);
        end

        function readVectorInNodes(obj,nComp)
            nLines = obj.nNodes;
            linesJump = 3;
            obj.readField(obj.lineNumber,nLines,linesJump,nComp);
            obj.updateLineNumber(nLines + linesJump + obj.linesEndValue);
        end

        function readScalarInNodes(obj)
            nLines = obj.nNodes;
            linesJump = 2;
            nComp = 1;
            obj.readField(obj.lineNumber,nLines,linesJump,nComp);
            obj.updateLineNumber(nLines + linesJump + obj.linesEndValue);
        end

        function [fName,fValue] = readField(obj,lineNumber,nLines,linesJump,nComp)
            fName = obj.readFieldName(lineNumber);
            lineNumber = lineNumber + linesJump;
            fValue = obj.readlFieldValues(lineNumber,nLines,nComp);
            obj.dataBase.(fName) = fValue;
        end

        function name = readFieldName(obj,lineNumber)
            lineText = obj.readLines(lineNumber,1);
            lSplit = split(lineText{1});
            name = lSplit(2);
            name = obj.eraseQuationMarks(name{1});
        end

        function fValue = readlFieldValues(obj,lineNumber,nLines,nComp)
            lines = obj.readLines(lineNumber,nLines);
            namesSplit = split(lines{:});
            lines = str2double(namesSplit);
            index = (1:nComp) + 1;
            fValue = lines(:,index);
        end

        function tLine = readLines(obj,lineNumber,nLines)
            fseek(obj.fid,0,'bof');
            tLine = textscan(obj.fid,'%s',nLines,'delimiter','\n', 'headerlines',lineNumber-1);
        end

        function updateLineNumber(obj,lines)
            obj.lineNumber = obj.lineNumber + lines;
        end

    end

    methods (Access = private, Static)

        function str = eraseQuationMarks(str)
            str = erase(str,"""");
        end

    end

end


function  wtree = ind2wtree(pyr, ind)

%this function is called by vifvec.m
% converts the output of Eero Simoncelli's pyramid routines into subbands in a cell array
C=pyr;
S=ind;

offset=0;
numsubs=size(ind,1);
for i=1:numsubs
    wtree{numsubs-i+1}=reshape(C(offset+1:offset+prod(S(i,:))), S(i,1),S(i,2));
    offset=offset+prod(S(i,:));
end