function rx = rxRecenterRx(rx,recenter3D);
%
% rx = rxRecenterRx(rx,[recenter3D]);
%
% Recenter a prescription using the mouse,
% on the Rx Figure.
%
% The clicked-on location will be the center
% of the prescription in the two dimensions
% being displayed in the Rx Figure's image, but
% the third dimension will be ignored. E.g.,
% if you're looking at the prescription on axials,
% it will recenter along the sagittal and coronal,
% but not axial, dimensions. This can be overridden
% if the recenter3D argument is entered as 1 [default
% is 0, ignore 3rd dimension].
%
%
% ras 03/05.
% ras 01/06: think I fixed why it wasn't always working -- the mapping
% of necessary rotations for the xform matrix (which goes:
%   coronal rotation, axial rotation, sagittal rotation
% ), and the orientation button order (which goes:
%   axial, coronal, sagittal
%   and which corresponds to the mrVista conventions) is weird. This
% seems to work, as long as you set 3D recenter to be the default.
% setting it to 0 is nice, if the rx is orthogonal to where you're viewing
% the volume, but weird if it's oblique w.r.t. the slice axis.
if ieNotDefined('rx')
    cfig = findobj('Tag','rxControlFig');
    rx = get(cfig,'UserData');
end

if ieNotDefined('recenter3D')
    recenter3D = 1;
end

if ~ishandle(rx.ui.rxFig)
    % exit quietly
    return
end

%%%%%params
slice = get(rx.ui.volSlice.sliderHandle,'Value');
ori = findSelectedButton(rx.ui.volOri);

pt = get(gca,'CurrentPoint');
x = pt(1,1); y = pt(1,2);

%%%%%figure out offset from current location
% center of current rx (vol coordinate system)
cen = rx2vol(rx,[rx.rxDims/2]')';

% desired location (vol coordinate system)
switch ori
    case 1, tgt = [y slice x]; % axial
    case 2, tgt = [slice y x]; % coronal
    case 3, tgt = [x y slice]; % sagittal
    otherwise, return; % not yet implemented
end

offset = tgt - cen;

if recenter3D ~= 1
    % ignore dimension orthogonal to view
    order = [2 1 3]; % weird mapping of orientation buttons -> trans axes
    offset(order(ori)) = 0;
end

%%%%%update existing rx
[trans rot scale skew] = affineDecompose(rx.xform);
trans = trans + offset;
newXform = affineBuild(trans, rot, scale, skew);
rx = rxSetXform(rx, newXform);

return


function y = prod( x, dim )

%   Disciplined geometric programming information for PROD:
%      PROD(X) and PROD(X,DIM) are vectorized versions of multiplication
%      so in most cases it would be incompatible with DCPs. Therefore it
%      has not been implemented to support DCPs. DGPs however support
%      products more liberally. When PROD is used in a DCP, elements in
%      each subvector must satisfy the corresponding combination rule
%      for multiplication (see TIMES). For example, suppose that X looks
%      like this:
%         X = [ log-convex log-concave log-affine  ;
%               log-affine log-concave log-concave ]
%      Then PROD(X,1) would be permittted, but PROD(X,2) would not,
%      because the top row contains the product of log-convex and
%      log-concave terms, in violation of the DGP ruleset.

narginchk(1,2);

%
% Size check
%

try
    ox = x;
    if nargin < 2, dim = []; end
    [ x, sx, sy, zx, zy, nx, nv, perm ] = cvx_reduce_size( x, dim ); %#ok
catch exc
    error( exc.message );
end

%
% Quick exit for easy cases
%

if isempty( x ),
    if ~any( zy ), zy = 1; end
    y = cvx( ones( zy ) );
    return
elseif nx == 1,
    y = ox;
    return
end

%
% Type check
%

persistent remap_1 remap_2 remap_3 remap_0
if isempty( remap_3 ),
    remap_0 = cvx_remap( 'zero' );
    remap_1 = cvx_remap( 'constant' );
    remap_2 = cvx_remap( 'log-convex' );
    remap_3 = cvx_remap( 'log-concave' );
end
vx = cvx_reshape( cvx_classify( x ), sx );
t0 = any( reshape( remap_0( vx ), sx ) );
t1 = all( reshape( remap_1( vx ), sx ) );
t2 = all( reshape( remap_2( vx ), sx ) ) | ...
     all( reshape( remap_3( vx ), sx ) );
t3 = t0 & t1;
ta = t3 + 2 * ( t2 & ~t3 );
nu = sort( ta(:) );
nu = nu([true;diff(nu)~=0]);
nk = length( nu );

%
% Perform the computations
%

if nk > 1,
    y = cvx( [ 1, nv ], [] );
end
for k = 1 : nk,

    if nk == 1,
        xt = x;
    else
        tt = ta == nu( k );
        xt = cvx_subsref( x, ':', tt );
    end

    switch nu( k ),
        case 0,
            error( 'Disciplined convex programming error:\n   Invalid computation: prod( {%s} )', cvx_class( xt, true, true ) );
        case 1,
            yt = cvx( prod( cvx_constant( xt ) ) );
        case 2,
            yt = exp( sum( log( xt ) ) );
        otherwise,
            error( 'Shouldn''t be here.' );
    end

    if nk == 1,
        y = yt;
    else
        y = cvx_subsasgn( y, tt, yt );
    end

end

%
% Reverse the reshaping and permutation steps
%

y = reshape( y, sy );
if ~isempty( perm ),
    y = ipermute( y, perm );
end

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


function test_failed = test_libltfat_fftifftshift(varargin)
test_failed = 0;

fprintf(' ===============  %s ================ \n',upper(mfilename));

definput.flags.complexity={'double','single'};
[flags]=ltfatarghelper({},definput,varargin);
dataPtr = [flags.complexity, 'Ptr'];

Larr = [1,9,11,110,111];

for L = Larr

        z = cast((1:L)',flags.complexity);
        zi = complex2interleaved(fft(z));
        zout = randn(size(zi),flags.complexity);

        ziPtr = libpointer(dataPtr,zi);
        zoutPtr = libpointer(dataPtr,zout);

        trueres = ifftshift(z);

        funname = makelibraryname('fftifftshift',flags.complexity,1);
        status = calllib('libltfat',funname,ziPtr,L,zoutPtr);

        res = norm(trueres - real(ifft(interleaved2complex(zoutPtr.Value))));

        [test_failed,fail]=ltfatdiditfail(res+status,test_failed);
        fprintf(['FFTIFFTSHIFT OP L:%3i, %s %s %s\n'],L,flags.complexity,ltfatstatusstring(status),fail);

        status = calllib('libltfat', funname, ziPtr,L,ziPtr);

        res = norm(trueres - real(ifft(interleaved2complex(ziPtr.Value))));

        [test_failed,fail]=ltfatdiditfail(res+status,test_failed);
        fprintf(['FFTIFFTSHIFT IP L:%3i, %s %s %s\n'],L,flags.complexity,ltfatstatusstring(status),fail);

        z = cast((1:L)',flags.complexity);
        zi = complex2interleaved(fftreal(z));
        zout = randn(size(zi),flags.complexity);

        ziPtr = libpointer(dataPtr,zi);
        zoutPtr = libpointer(dataPtr,zout);

        trueres = ifftshift(z);

        funname = makelibraryname('fftrealifftshift',flags.complexity,1);
        status = calllib('libltfat',funname,ziPtr,L,zoutPtr);

        res = norm(trueres - ifftreal(interleaved2complex(zoutPtr.Value),L));

        [test_failed,fail]=ltfatdiditfail(res+status,test_failed);
        fprintf(['FFTREALIFFTSHIFT OP L:%3i, %s %s %s\n'],L,flags.complexity,ltfatstatusstring(status),fail);

        status = calllib('libltfat', funname, ziPtr,L,ziPtr);

        res = norm(trueres - ifftreal(interleaved2complex(ziPtr.Value),L));

        [test_failed,fail]=ltfatdiditfail(res+status,test_failed);
        fprintf(['FFTREALIFFTSHIFT IP L:%3i, %s %s %s\n'],L,flags.complexity,ltfatstatusstring(status),fail);

end


function varargout=ceil(varargin)
%CEIL (overloaded)

switch class(varargin{1})

    case 'sdpvar' % Overloaded operator for SDPVAR objects. Pass on args and save them.

        x = varargin{1};
        dim = size(x);
        x = reshape(x,prod(dim),1);
        y = [];
        for i = 1:prod(dim)
            y = [y;yalmip('define',mfilename,extsubsref(x,i))];
        end
        y = reshape(y,dim);
        varargout{1} = y;

    case 'char' % YALMIP send 'graph' when it wants the epigraph or hypograph
        switch varargin{1}
            case {'milp','graph','exact'}
                % Description using epigraphs
                t = varargin{2};
                X = varargin{3};

                F = ([X <= t <= X + 1]) + (integer(t));

                varargout{1} = F;
                varargout{2} = struct('convexity','none','monotonicity','none','definiteness','none','model','integer');
                varargout{3} = X;

            otherwise
                error('SDPVAR/CEIL called with CHAR argument?');
        end
    otherwise
        error('Strange type on first argument in SDPVAR/CEIL');
end


function SO3VF = power(SO3VF,a)
% overloads |SO3VF.^2|
%
% Syntax
%   SO3VF = SO3VF.^2
%
% Input
%  SO3VF - @SO3VectorField
%  a - double
%
% Output
%  SO3VF - @SO3VectorField
%

if isa(a,'vector3d')
  a = a.xyz;
end

if ~isnumeric(a)
  error('The exponent has to be numeric.')
end

SO3VF = SO3VectorFieldHandle(@(rot) SO3VF.eval(rot).^(a(:)),SO3VF.SRight,SO3VF.SLeft);

end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright 2014 the National Renewable Energy Laboratory and Sandia Corporation
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
%     http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Plots solver-to-solver comparison for the newly run simulation for the
% regular waves.

%% Load Data
cd regular
load('regular_org.mat')       % Load WEC-Sim Run Data
cd .. ; cd regularCIC
load('regularCIC_org.mat')    % Load WEC-Sim Run Data
cd .. ; cd regularSS
load('regularSS_org.mat')     % Load WEC-Sim Run Data
cd ..

%% Plot Heave Comparisons
h=figure('units','normalized','outerposition',[0 0 1 1]);
% First Row = All simulations, all times
% Second Row = All simulations, t=350-400s
% Third Row = Original and New WEC-Sim runs only, t=350-400s

%First Column: Body 1 Heave
startTime = 100;
subplot(2,3,1)
m = plot(regular.B1.WEC_Sim_new.time,regular.B1.WEC_Sim_new.heave,'k:',...
	regularCIC.B1.WEC_Sim_new.time,regularCIC.B1.WEC_Sim_new.heave,'r--',...
    regularSS.B1.WEC_Sim_new.time,regularSS.B1.WEC_Sim_new.heave,'b-.');
a=get(m(1),'LineWidth')+1;
set(m(1),'LineWidth',a)
xlabel('time(s)')
ylabel('Heave(m)')
title('Float 1DOF 1200PTO')
xlim([0 150])
ylim([-2 2])

subplot(2,3,4)
m = plot(   regular.B1.WEC_Sim_new.time(find(    regular.B1.WEC_Sim_new.time==startTime):end),...
          regular.B1.WEC_Sim_new.heave(find(   regular.B1.WEC_Sim_new.time==startTime):end),'k:',...
       regularCIC.B1.WEC_Sim_new.time(find( regularCIC.B1.WEC_Sim_new.time==startTime):end),...
       regularCIC.B1.WEC_Sim_new.heave(find(regularCIC.B1.WEC_Sim_new.time==startTime):end),'r--',...
        regularSS.B1.WEC_Sim_new.time(find(  regularSS.B1.WEC_Sim_new.time==startTime):end),...
        regularSS.B1.WEC_Sim_new.heave(find( regularSS.B1.WEC_Sim_new.time==startTime):end),'b-.');
a=get(m(1),'LineWidth')+1;
set(m(1),'LineWidth',a)
xlabel('time(s)')
ylabel('Heave(m)')
xlim([100 150])
ylim([-2 2])

%Second Column: Body 2 Heave
subplot(2,3,2)
m = plot(   regular.B2.WEC_Sim_new.time,   regular.B2.WEC_Sim_new.heave,'k:',...
     regularCIC.B2.WEC_Sim_new.time,regularCIC.B2.WEC_Sim_new.heave,'r--',...
      regularSS.B2.WEC_Sim_new.time, regularSS.B2.WEC_Sim_new.heave,'b-.');
a=get(m(1),'LineWidth')+1;
set(m(1),'LineWidth',a)
xlabel('time(s)')
ylabel('Heave(m)')
title('Spar/Plate 1DOF 1200PTO')
xlim([0 150])
ylim([-0.2 0.2])

subplot(2,3,5)
m=plot(   regular.B2.WEC_Sim_new.time(find(    regular.B2.WEC_Sim_new.time==startTime):end),...
          regular.B2.WEC_Sim_new.heave(find(   regular.B2.WEC_Sim_new.time==startTime):end),'k:',...
       regularCIC.B2.WEC_Sim_new.time(find( regularCIC.B2.WEC_Sim_new.time==startTime):end),...
       regularCIC.B2.WEC_Sim_new.heave(find(regularCIC.B2.WEC_Sim_new.time==startTime):end),'r--',...
        regularSS.B2.WEC_Sim_new.time(find(  regularSS.B2.WEC_Sim_new.time==startTime):end),...
        regularSS.B2.WEC_Sim_new.heave(find( regularSS.B2.WEC_Sim_new.time==startTime):end),'b-.');
a=get(m(1),'LineWidth')+1;
set(m(1),'LineWidth',a)
xlabel('time(s)')
ylabel('Heave(m)')
xlim([100 150])
ylim([-0.2 0.2])

%Third Column: Relative Heave
subplot(2,3,3)
m= plot(   regular.Rel.WEC_Sim_new.time,   regular.Rel.WEC_Sim_new.heave,'k:',...
     regularCIC.Rel.WEC_Sim_new.time,regularCIC.Rel.WEC_Sim_new.heave,'r--',...
      regularSS.Rel.WEC_Sim_new.time, regularSS.Rel.WEC_Sim_new.heave,'b-.');
a=get(m(1),'LineWidth')+1;
set(m(1),'LineWidth',a)
xlabel('time(s)')
ylabel('Heave(m)')
title('Relative Motion 1DOF 1200PTO')
xlim([0 150])
ylim([-2 2])
l=legend('"regular"','"regularCIC"','"regularCIC" with State Space');
set(l,'Position',[0.765 0.84 0.07 0.07],'Units','normalized',...
    'FontSize',12);

subplot(2,3,6)
m=plot(   regular.Rel.WEC_Sim_new.time(find(    regular.Rel.WEC_Sim_new.time==startTime):end),...
          regular.Rel.WEC_Sim_new.heave(find(   regular.Rel.WEC_Sim_new.time==startTime):end),'k:',...
       regularCIC.Rel.WEC_Sim_new.time(find( regularCIC.Rel.WEC_Sim_new.time==startTime):end),...
       regularCIC.Rel.WEC_Sim_new.heave(find(regularCIC.Rel.WEC_Sim_new.time==startTime):end),'r--',...
        regularSS.Rel.WEC_Sim_new.time(find(  regularSS.Rel.WEC_Sim_new.time==startTime):end),...
        regularSS.Rel.WEC_Sim_new.heave(find( regularSS.Rel.WEC_Sim_new.time==startTime):end),'b-.');
a=get(m(1),'LineWidth')+1;
set(m(1),'LineWidth',a)
xlabel('time(s)')
ylabel('Heave(m)')
xlim([100 150])
ylim([-2 2])

clear a h l m B1_H_Tolerance B2_H_Tolerance Rel_H_Tolerance str1 str2


function ExecFlag=DorfExec(handles)

global VObj;
global VMag;
global VVar;
global VSeq;
global VCtl;
global VSig;
global VCoi;

%preserve VObj VMag & VCoi
VTmpObj=VObj;
VTmpMag=VMag;
VTmpCoi=VCoi;

handles.Simuh=guidata(handles.Simuh.SimuPanel_figure);
DoDisableButton([],[],handles.Simuh);
%% Do spin execution
try
    % Read tab parameters
    fieldname=fieldnames(handles.Attrh0);
    for i=1:length(fieldname)/2
        switch get(handles.Attrh0.(fieldname{i*2}),'Style')
            case 'edit'
                eval(['RF.' fieldname{i*2} '=[' get(handles.Attrh0.(fieldname{i*2}),'String') '];']);
            case 'popupmenu'
                TAttr=get(handles.Attrh0.(fieldname{i*2}),'String');
                eval(['RF.' fieldname{i*2} '=''' TAttr{get(handles.Attrh0.(fieldname{i*2}),'Value')}  ''';']);
        end
    end

    % Prescan config
    DoPreScan(handles.Simuh);

    % Create SpinWatcher VOrf
    if strcmp(RF.Freq_Flag,'on') % spatial-spectral analysis
        if strcmp(RF.Spat_Flag,'on') % 2D spatial analysis
            error('Freq_Flag is incompatible with Spat_Flag! Turn Spat_Flag to off.');
        end
        set(handles.SliProfile_uipanel,'Title','Spin Response : Spatial-Spectral');
        Freq=linspace(RF.FreqDownLimit,RF.FreqUpLimit,RF.FreqRes)/VCtl.B0;

        VOrf=VObj;
        VOrf.Gyro=RF.Gyro;
        VOrf.ChemShift=Freq;
        VOrf.SpinNum=1;
        VOrf.TypeNum=length(Freq);
        VOrf.XDim=1;
        VOrf.YDim=1;
        VOrf.ZDim=RF.ZSpin;
        VOrf.XDimRes=1e-3;
        VOrf.YDimRes=1e-3;
        VOrf.ZDimRes=RF.ZSpinGap;
        VOrf=rmfield(VOrf, 'Rho');
        VOrf=rmfield(VOrf, 'T1');
        VOrf=rmfield(VOrf, 'T2');
        VOrf=rmfield(VOrf, 'T2Star');
        VOrf=rmfield(VOrf, 'Type');
        for i=1:VOrf.TypeNum
            VOrf.Rho(:,:,1:RF.ZSpin,i)=RF.Rho(1);
            VOrf.T1(:,:,1:RF.ZSpin,i)=RF.T1(1);
            VOrf.T2(:,:,1:RF.ZSpin,i)=RF.T2(1);
            VOrf.T2Star(:,:,1:RF.ZSpin,i)=0;
        end
        VOrf=rmfield(VOrf, 'Mx');
        VOrf=rmfield(VOrf, 'My');
        VOrf=rmfield(VOrf, 'Mz');
        VOrf.Mx= zeros(1,1,VOrf.ZDim,VOrf.SpinNum,VOrf.TypeNum);
        VOrf.My= zeros(1,1,VOrf.ZDim,VOrf.SpinNum,VOrf.TypeNum);
        VOrf.Mz= zeros(1,1,VOrf.ZDim,VOrf.SpinNum,VOrf.TypeNum);
        for i=1:VOrf.TypeNum
            VOrf.Mz(:,:,:,:,i)= ones(1,1,RF.ZSpin,VOrf.SpinNum,1).*(RF.Rho(1)./VOrf.SpinNum);
        end
    elseif strcmp(RF.Spat_Flag,'on') % 2D spatial analysis
        set(handles.SliProfile_uipanel,'Title','Spin Response : 2D Spatial');
        VOrf=VObj;
        VOrf.Gyro=RF.Gyro;
        VOrf.ChemShift=RF.ChemShift(1);
        VOrf.SpinNum=1;
        VOrf.TypeNum=1;
        VOrf.XDim=RF.XSpin;
        VOrf.YDim=RF.YSpin;
        VOrf.ZDim=1;
        VOrf.XDimRes=RF.XSpinGap;
        VOrf.YDimRes=RF.YSpinGap;
        VOrf.ZDimRes=1e-3;
        VOrf=rmfield(VOrf, 'Rho');
        VOrf=rmfield(VOrf, 'T1');
        VOrf=rmfield(VOrf, 'T2');
        VOrf=rmfield(VOrf, 'T2Star');
        VOrf=rmfield(VOrf, 'Type');

        VOrf.Rho(1:RF.YSpin,1:RF.XSpin,1,1)=RF.Rho(1);
        VOrf.T1(1:RF.YSpin,1:RF.XSpin,1,1)=RF.T1(1);
        VOrf.T2(1:RF.YSpin,1:RF.XSpin,1,1)=RF.T2(1);
        VOrf.T2Star(1:RF.YSpin,1:RF.XSpin,1,1)=0;

        VOrf=rmfield(VOrf, 'Mx');
        VOrf=rmfield(VOrf, 'My');
        VOrf=rmfield(VOrf, 'Mz');
        VOrf.Mx= zeros(VOrf.YDim,VOrf.XDim,1,VOrf.SpinNum,VOrf.TypeNum);
        VOrf.My= zeros(VOrf.YDim,VOrf.XDim,1,VOrf.SpinNum,VOrf.TypeNum);
        VOrf.Mz= zeros(VOrf.YDim,VOrf.XDim,1,VOrf.SpinNum,VOrf.TypeNum);
        for i=1:VOrf.TypeNum
            VOrf.Mz(:,:,:,:,i)= ones(VOrf.YDim,VOrf.XDim,1,VOrf.SpinNum,1).*(RF.Rho(i)./VOrf.SpinNum);
        end
    else  % normal 1D analysis
        set(handles.SliProfile_uipanel,'Title','Spin Response : 1D Spatial');
        VOrf=VObj;
        VOrf.Gyro=RF.Gyro;
        VOrf.ChemShift=RF.ChemShift;
        VOrf.SpinNum=1;
        VOrf.TypeNum=RF.TypeNum;
        VOrf.XDim=1;
        VOrf.YDim=1;
        VOrf.ZDim=RF.ZSpin;
        VOrf.XDimRes=1e-3;
        VOrf.YDimRes=1e-3;
        VOrf.ZDimRes=RF.ZSpinGap;
        VOrf=rmfield(VOrf, 'Rho');
        VOrf=rmfield(VOrf, 'T1');
        VOrf=rmfield(VOrf, 'T2');
        VOrf=rmfield(VOrf, 'T2Star');
        VOrf=rmfield(VOrf, 'Type');
        for i=1:VOrf.TypeNum
            VOrf.Rho(:,:,1:RF.ZSpin,i)=RF.Rho(i);
            VOrf.T1(:,:,1:RF.ZSpin,i)=RF.T1(i);
            VOrf.T2(:,:,1:RF.ZSpin,i)=RF.T2(i);
            VOrf.T2Star(:,:,1:RF.ZSpin,i)=0;
        end
        VOrf=rmfield(VOrf, 'Mx');
        VOrf=rmfield(VOrf, 'My');
        VOrf=rmfield(VOrf, 'Mz');
        VOrf.Mx= zeros(1,1,VOrf.ZDim,VOrf.SpinNum,VOrf.TypeNum);
        VOrf.My= zeros(1,1,VOrf.ZDim,VOrf.SpinNum,VOrf.TypeNum);
        VOrf.Mz= zeros(1,1,VOrf.ZDim,VOrf.SpinNum,VOrf.TypeNum);
        for i=1:VOrf.TypeNum
            VOrf.Mz(:,:,:,:,i)= ones(1,1,RF.ZSpin,VOrf.SpinNum,1).*(RF.Rho(i)./VOrf.SpinNum);
        end
    end

    if strcmp(RF.Spat_Flag,'on') % 2D analysis
        % Gradient Grid
        VMrf=VMag;
        VMrf=rmfield(VMrf, 'Gxgrid');
        VMrf=rmfield(VMrf, 'Gygrid');
        VMrf=rmfield(VMrf, 'Gzgrid');
        VMrf=rmfield(VMrf, 'dB0');
        VMrf=rmfield(VMrf, 'dWRnd');
        VMrf=rmfield(VMrf, 'FRange');

        [VMrf.Gxgrid,VMrf.Gygrid,VMrf.Gzgrid]=meshgrid((-RF.XCenter+1)*RF.XSpinGap:RF.XSpinGap:(RF.XSpin-RF.XCenter)*RF.XSpinGap, ...
                                                       (-RF.YCenter+1)*RF.YSpinGap:RF.YSpinGap:(RF.YSpin-RF.YCenter)*RF.YSpinGap,1);
        VMrf.dB0=ones([RF.YSpin RF.XSpin 1])*RF.dB0;
        VMrf.dWRnd=zeros(size(VOrf.Mz));
        VMrf.FRange=ones(size(VOrf.Rho));

        % Coil
        VCrf=VCoi;
        VCrf.TxCoilmg  = ones([RF.YSpin RF.XSpin 1]);  % Unit B1+ for rf analysis
        VCrf.TxCoilpe  = zeros([RF.YSpin RF.XSpin 1]);
        VCrf.TxCoilNum = 1;

    else % spatial-spectral analysis or 1D analysis
        % Gradient Grid
        VMrf=VMag;
        VMrf=rmfield(VMrf, 'Gxgrid');
        VMrf=rmfield(VMrf, 'Gygrid');
        VMrf=rmfield(VMrf, 'Gzgrid');
        VMrf=rmfield(VMrf, 'dB0');
        VMrf=rmfield(VMrf, 'dWRnd');
        VMrf=rmfield(VMrf, 'FRange');

        [VMrf.Gxgrid,VMrf.Gygrid,VMrf.Gzgrid]=meshgrid(0,0,(-RF.ZCenter+1)*RF.ZSpinGap:RF.ZSpinGap:(RF.ZSpin-RF.ZCenter)*RF.ZSpinGap); % assume constant unit gradient in GzSS
        VMrf.dB0=ones([1 1 RF.ZSpin])*RF.dB0;
        VMrf.dWRnd=zeros(size(VOrf.Mz));
        VMrf.FRange=ones(size(VOrf.Rho));

        % Coil
        VCrf=VCoi;
        VCrf.TxCoilmg  = ones([1 1 RF.ZSpin]);  % Unit B1+ for rf analysis
        VCrf.TxCoilpe  = zeros([1 1 RF.ZSpin]);
        VCrf.TxCoilNum = 1;

    end
    %% Spin execution
    VObj=VOrf;
    VMag=VMrf;
    VCoi=VCrf;

    % Generate Pulse line
    if isfield(handles,'rfNode')
        for parai=1:length(handles.rfNode.Attributes)
            if ~isempty(handles.rfNode.Attributes(parai).Value)
                switch handles.rfNode.Attributes(parai).Value(1)
                    case '$'
                        eval(['AttributeOpt={' handles.rfNode.Attributes(parai).Value(3:end) '};']);
                        eval(['p.' handles.rfNode.Attributes(parai).Name '=AttributeOpt{' handles.rfNode.Attributes(parai).Value(2) '};']);
                    otherwise
                        if ~strcmp(handles.rfNode.Attributes(parai).Name,'Notes')
                            eval(['p.' handles.rfNode.Attributes(parai).Name '=' handles.rfNode.Attributes(parai).Value ';']);
                        else
                            eval(['p.' handles.rfNode.Attributes(parai).Name '=''' handles.rfNode.Attributes(parai).Value ''';']);
                        end
                end

            else
                eval(['p.' handles.rfNode.Attributes(parai).Name '=[];']);
            end
        end
        VVar.TRCount=1; % may used for rfUser
        eval(['[rfAmp,rfPhase,rfFreq,rfCoil,rfTime]=' handles.rfNode.Name '(p);']);
    else
        errordlg('Please choose a rf wave type (e.g. rfSinc)!');
        ExecFlag=0;
        %recover VObj VMag VCoi
        VObj=VTmpObj;
        VMag=VTmpMag;
        VCoi=VTmpCoi;
        return
    end

    if strcmp(RF.Spat_Flag,'off')
        if isfield(handles,'GzNode')
            for parai=1:length(handles.GzNode.Attributes)
                if ~isempty(handles.GzNode.Attributes(parai).Value)
                    switch handles.GzNode.Attributes(parai).Value(1)
                        case '$'
                            eval(['AttributeOpt={' handles.GzNode.Attributes(parai).Value(3:end) '};']);
                            eval(['p.' handles.GzNode.Attributes(parai).Name '=AttributeOpt{' handles.GzNode.Attributes(parai).Value(2) '};']);
                        otherwise
                            if ~strcmp(handles.GzNode.Attributes(parai).Name,'Notes')
                                eval(['p.' handles.GzNode.Attributes(parai).Name '=' handles.GzNode.Attributes(parai).Value ';']);
                            else
                                eval(['p.' handles.GzNode.Attributes(parai).Name '=''' handles.GzNode.Attributes(parai).Value ''';']);
                            end
                    end

                else
                    eval(['p.' handles.GzNode.Attributes(parai).Name '=[];']);
                end
            end
            VVar.TRCount=1; % may used for GzUser
            eval(['[GzAmp,GzTime]=' handles.GzNode.Name '(p);']);
        else
            GzAmp=[0 RF.ConstantGrad RF.ConstantGrad 0];
            GzTime=[0 VCtl.MinUpdRate max(rfTime)-VCtl.MinUpdRate max(rfTime)];
            warndlg('Please choose a GzSS gradient type (e.g. GzSelective), otherwise constant gradient (i.e. ConstantGrad) will be used!');
        end

    else
        if isfield(handles,'GyNode')
            for parai=1:length(handles.GyNode.Attributes)
                if ~isempty(handles.GyNode.Attributes(parai).Value)
                    switch handles.GyNode.Attributes(parai).Value(1)
                        case '$'
                            eval(['AttributeOpt={' handles.GyNode.Attributes(parai).Value(3:end) '};']);
                            eval(['p.' handles.GyNode.Attributes(parai).Name '=AttributeOpt{' handles.GyNode.Attributes(parai).Value(2) '};']);
                        otherwise
                            if ~strcmp(handles.GyNode.Attributes(parai).Name,'Notes')
                                eval(['p.' handles.GyNode.Attributes(parai).Name '=' handles.GyNode.Attributes(parai).Value ';']);
                            else
                                eval(['p.' handles.GyNode.Attributes(parai).Name '=''' handles.GyNode.Attributes(parai).Value ''';']);
                            end
                    end

                else
                    eval(['p.' handles.GyNode.Attributes(parai).Name '=[];']);
                end
            end
            VVar.TRCount=1; % may used for GyUser
            eval(['[GyAmp,GyTime]=' handles.GyNode.Name '(p);']);
        else
            GyAmp=[0 RF.ConstantGrad RF.ConstantGrad 0];
            GyTime=[0 VCtl.MinUpdRate max(rfTime)-VCtl.MinUpdRate max(rfTime)];
            warndlg('Please choose a GyPE gradient type, otherwise constant gradient (i.e. ConstantGrad) will be used!');
        end

        if isfield(handles,'GxNode')
            for parai=1:length(handles.GxNode.Attributes)
                if ~isempty(handles.GxNode.Attributes(parai).Value)
                    switch handles.GxNode.Attributes(parai).Value(1)
                        case '$'
                            eval(['AttributeOpt={' handles.GxNode.Attributes(parai).Value(3:end) '};']);
                            eval(['p.' handles.GxNode.Attributes(parai).Name '=AttributeOpt{' handles.GxNode.Attributes(parai).Value(2) '};']);
                        otherwise
                            if ~strcmp(handles.GxNode.Attributes(parai).Name,'Notes')
                                eval(['p.' handles.GxNode.Attributes(parai).Name '=' handles.GxNode.Attributes(parai).Value ';']);
                            else
                                eval(['p.' handles.GxNode.Attributes(parai).Name '=''' handles.GxNode.Attributes(parai).Value ''';']);
                            end
                    end

                else
                    eval(['p.' handles.GxNode.Attributes(parai).Name '=[];']);
                end
            end
            VVar.TRCount=1; % may used for GxUser
            eval(['[GxAmp,GxTime]=' handles.GxNode.Name '(p);']);
        else
            GxAmp=[0 RF.ConstantGrad RF.ConstantGrad 0];
            GxTime=[0 VCtl.MinUpdRate max(rfTime)-VCtl.MinUpdRate max(rfTime)];
            warndlg('Please choose a GxR gradient type, otherwise constant gradient (i.e. ConstantGrad) will be used!');
        end
    end

    if strcmp(RF.Spat_Flag,'on') % 2D analysis
        SEt=[0 max([rfTime, GxTime, GyTime])]; % SEt time landmark must start from 0
        SEflag=repmat([0 0 0 0 0 0]',[1 2]);
        rfflag=repmat([1 0 0 0 0 0]',[1 max(size(rfTime))]);
        Gyflag=repmat([0 0 1 0 0 0]',[1 max(size(GyTime))]);
        Gxflag=repmat([0 0 0 1 0 0]',[1 max(size(GxTime))]);

        ts=[SEt rfTime GyTime GxTime];
        flags=[SEflag rfflag Gyflag Gxflag];
        [ts,ind]=sort(ts);
        uts=unique(ts);
        flags=flags(:,ind);

        rfAmp(abs(rfAmp)<eps)=0;
        VSeq.rfAmpLine=rfAmp;
        VSeq.rfPhaseLine=rfPhase;
        VSeq.rfFreqLine=rfFreq;
        VSeq.rfCoilLine=ones(size(rfCoil)); % default single-Tx
        VSeq.GzAmpLine=0;
        VSeq.GyAmpLine=GyAmp;
        VSeq.GxAmpLine=GxAmp;
        VSeq.ADCLine=0;
        VSeq.ExtLine=0;
        VSeq.utsLine=uts;
        VSeq.tsLine=ts;
        VSeq.flagsLine=flags;

        % Initialize Mx, My, Mz, Muts in VSig
        VSig.Mx= zeros(VObj.YDim,VObj.XDim,1,1,VObj.TypeNum, max(size(VSeq.utsLine)));
        VSig.My= zeros(VObj.YDim,VObj.XDim,1,1,VObj.TypeNum, max(size(VSeq.utsLine)));
        VSig.Mz= zeros(VObj.YDim,VObj.XDim,1,1,VObj.TypeNum, max(size(VSeq.utsLine)));
        VSig.Muts=zeros(max(size(VSeq.utsLine)),1);

    else % spatial-spectral analysis or 1D analysis

        SEt=[0 max(max(rfTime),max(GzTime))]; % SEt time landmark must start from 0
        SEflag=repmat([0 0 0 0 0 0]',[1 2]);
        rfflag=repmat([1 0 0 0 0 0]',[1 max(size(rfTime))]);
        Gzflag=repmat([0 1 0 0 0 0]',[1 max(size(GzTime))]);

        ts=[SEt rfTime GzTime];
        flags=[SEflag rfflag Gzflag];
        [ts,ind]=sort(ts);
        uts=unique(ts);
        flags=flags(:,ind);

        rfAmp(abs(rfAmp)<eps)=0;
        VSeq.rfAmpLine=rfAmp;
        VSeq.rfPhaseLine=rfPhase;
        VSeq.rfFreqLine=rfFreq;
        VSeq.rfCoilLine=ones(size(rfCoil)); % default single-Tx
        VSeq.GzAmpLine=GzAmp;
        VSeq.GyAmpLine=0;
        VSeq.GxAmpLine=0;
        VSeq.ADCLine=0;
        VSeq.ExtLine=0;
        VSeq.utsLine=uts;
        VSeq.tsLine=ts;
        VSeq.flagsLine=flags;

        % Initialize Mx, My, Mz, Muts in VSig
        VSig.Mx= zeros(1,1,VObj.ZDim,1,VObj.TypeNum, max(size(VSeq.utsLine)));
        VSig.My= zeros(1,1,VObj.ZDim,1,VObj.TypeNum, max(size(VSeq.utsLine)));
        VSig.Mz= zeros(1,1,VObj.ZDim,1,VObj.TypeNum, max(size(VSeq.utsLine)));
        VSig.Muts=zeros(max(size(VSeq.utsLine)),1);

    end

    VSig.Mx(:,:,:,:,:,1)=VObj.Mx;
    VSig.My(:,:,:,:,:,1)=VObj.My;
    VSig.Mz(:,:,:,:,:,1)=VObj.Mz;
    VSig.Muts(1)=0;

    % Simulation Process
    try
        VCtl.CS=double(VObj.ChemShift*VCtl.B0);
        VCtl.RunMode=int32(1); % Spin scan
        VCtl.MaxThreadNum=int32(handles.Simuh.CPUInfo.NumThreads);
        DoDataTypeConv(handles.Simuh);
        DoScanAtCPU; % global (VSeq,VObj,VCtl,VMag,VCoi,VVar,VSig) are needed
    catch me
        error_msg{1,1}='ERROR!!! rf execution process aborted.';
        error_msg{2,1}=me.message;
        errordlg(error_msg);
        ExecFlag=0;
        %recover VObj VMag VCoi
        VObj=VTmpObj;
        VMag=VTmpMag;
        VCoi=VTmpCoi;
        return;
    end

    %modify sequence line for display purpose
    if strcmp(RF.Spat_Flag,'on') % 2D analysis
        handles.rfAmp=[0 rfAmp 0];
        handles.rfPhase=[0 rfPhase 0];
        handles.rfFreq=[0 rfFreq 0];
        handles.rfTime=[SEt(1) rfTime SEt(2)];
        handles.GyAmp=[0 GyAmp 0];
        handles.GyTime=[SEt(1) GyTime SEt(2)];
        handles.GxAmp=[0 GxAmp 0];
        handles.GxTime=[SEt(1) GxTime SEt(2)];
    else % spatial-spectral analysis or 1D analysis
        handles.rfAmp=[0 rfAmp 0];
        handles.rfPhase=[0 rfPhase 0];
        handles.rfFreq=[0 rfFreq 0];
        handles.rfTime=[SEt(1) rfTime SEt(2)];
        handles.GzAmp=[0 GzAmp 0];
        handles.GzTime=[SEt(1) GzTime SEt(2)];
    end

    if strcmp(RF.Freq_Flag,'on')
        handles.Mx=permute(VSig.Mx,[3, 5, 6, 1, 2, 4]).*double(VObj.SpinNum);
        handles.My=permute(VSig.My,[3, 5, 6, 1, 2, 4]).*double(VObj.SpinNum);
        handles.Mz=permute(VSig.Mz,[3, 5, 6, 1, 2, 4]).*double(VObj.SpinNum);
        handles.Mx=handles.Mx(:,:,:,1,1,1);
        handles.My=handles.My(:,:,:,1,1,1);
        handles.Mz=handles.Mz(:,:,:,1,1,1);
        handles.Muts=VSig.Muts;
        handles.Freq=Freq;
    elseif strcmp(RF.Spat_Flag,'on')
        handles.Mx=permute(VSig.Mx,[1, 2, 6, 3, 4, 5]).*double(VObj.SpinNum);
        handles.My=permute(VSig.My,[1, 2, 6, 3, 4, 5]).*double(VObj.SpinNum);
        handles.Mz=permute(VSig.Mz,[1, 2, 6, 3, 4, 5]).*double(VObj.SpinNum);
        handles.Mx=handles.Mx(:,:,:,1,1,1);
        handles.My=handles.My(:,:,:,1,1,1);
        handles.Mz=handles.Mz(:,:,:,1,1,1);
        handles.Muts=VSig.Muts;
    else
        handles.Mx=VSig.Mx.*double(VObj.SpinNum);
        handles.My=VSig.My.*double(VObj.SpinNum);
        handles.Mz=VSig.Mz.*double(VObj.SpinNum);
        handles.Muts=VSig.Muts;
    end

    handles.Freq_Flag=RF.Freq_Flag;
    handles.Spat_Flag=RF.Spat_Flag;
    handles.Gxgrid=VMag.Gxgrid;
    handles.Gygrid=VMag.Gygrid;
    handles.Gzgrid=VMag.Gzgrid;
catch me
    error_msg{1,1}='ERROR!!! rf execution process aborted.';
    error_msg{2,1}=me.message;
    errordlg(error_msg);
    ExecFlag=0;
    %recover VObj VMag VCoi
    VObj=VTmpObj;
    VMag=VTmpMag;
    VCoi=VTmpCoi;
    return;
end

%recover VObj VMag VCoi
VObj=VTmpObj;
VMag=VTmpMag;
VCoi=VTmpCoi;

guidata(handles.rfDesignPanel_figure, handles);
ExecFlag=1;

end


function gee_its_simple_check (A, name, b)
%GEE_ITS_SIMPLE_CHECK private function to check input arguments
% Ensures the matrix A is square, and that the right-hand-side b has the same
% number of rows as A (if present).  All matrices must be 2D, as well.
%
% Example:
%   gee_its_simple_check (A, 'A', b)
%
% See also: gee_its_simple

% Copyright 2007, Timothy A. Davis.
% http://www.cise.ufl.edu/research/sparse

[m n] = size (A) ;
if (m ~= n)
    error ('%s must be square', name) ;
end

if (ndims (A) ~= 2)
    error ('%s must be a 2D matrix', name) ;
end

if (nargin > 2)
    if (m ~= size (b,1))
        error ('%s and b must have the same number of rows', name) ;
    end
    if (ndims (b) ~= 2)
        error ('b must be a 2D matrix') ;
    end
end


function sig = fix_length(sig,N)
%FIX_LENGTH pads zeros or removes entries from signal accroding to length N
%
%   Usage: sig = fix_length(sig,N)
%
%   Input parameters:
%       sig - input signal (matrix with sigs as columns)
%       N   - number of samples size(sig,1) should be
%
%   Output paramteres:
%       sig - corrected sig
%
%   FIX_LENGTH(sig,N) pads zeros or removes the end of the given signal in
%   order to have a sig with a size(sig,1)==N.
%
%   see also: fix_irs_length, convolution

%*****************************************************************************
% 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 = 2;
nargmax = 2;
narginchk(nargmin,nargmax);

%% ===== Fix IR ==========================================================
% Length of IR
samples = size(sig,1);
channels = size(sig,2);

if samples<N
    % Append zeros if to short
    sig = [sig; zeros(N-samples,channels)];
else
    % Remove the end of the IR, if to long
    sig = sig(1:N,:);
end


function LOCS = tapas_physio_create_LOCS_from_VOLLOCS(VOLLOCS, t, sqpar)
% Compute slice scan events as locations in time vector (LOCS) from volume
% scan locations and sequence parameters (TR, nSlices)
%
% LOCS = tapas_physio_create_LOCS_from_VOLLOCS(VOLLOCS, t, sqpar);
%
%
% IN
%   NOTE: The detailed description of all input structures can be found as
%   comments in tapas_physio_new
%
%   VOLLOCS - index locations in time vector (of physiological recordings),
%                             when volume scan events started
%   t       - time vector of phys time course
%
%   sqpar   - sequence timing parameters, used for computation
%             of scan events from 'nominal' timing
%           .Nslices        - number of slices per volume in fMRI scan
%           .TR             - repetition time in seconds
%           .time_slice_to_slice - time between the acquisition of 2 subsequent
%                             slices; typically TR/Nslices or
%                             minTR/Nslices, if minimal temporal slice
%                             spacing was chosen
%
% OUT
%   LOCS    - locations in time vector, when slice or volume scan
%             events started
%
%   See also tapas_physio_new tapas_physio_main_create_regresssors

% Author: Lars Kasper
% Created: 2013-08-23
% Copyright (C) 2016 Institute for Biomedical Engineering, ETH/Uni Zurich.
%
% This file is part of the PhysIO toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

NallVols        = sqpar.Ndummies+sqpar.Nscans;
Nslices         = sqpar.Nslices;
TR              = sqpar.TR;
LOCS            = NaN(NallVols*Nslices,1);

%default for equidistantly spaced slices
if isempty(sqpar.time_slice_to_slice)
    sqpar.time_slice_to_slice = TR/Nslices;
end

iFirstValidVolume = find(~isnan(VOLLOCS), 1);
tRef = t(VOLLOCS(iFirstValidVolume));

for n = iFirstValidVolume:NallVols

    % first, restrict search interval to within TR
    LOCVOLSTART = VOLLOCS(n);

    if n == NallVols
        LOCVOLEND = numel(t);
    else
        LOCVOLEND = VOLLOCS(n+1);
    end

    % Then, find slice-by-slice nearest neighbour of actual and
    % reference time
    tSearchInterval = t(LOCVOLSTART:LOCVOLEND) - ...
        (tRef + sqpar.TR*(n-iFirstValidVolume));

    % Note: Why not the same as other slices? Some jitter problem...
    % if TR is not given with high enough precision, therefore reset for
    % each volume!
    LOCS((n-1)*Nslices + 1) = LOCVOLSTART;
    for s = 2:sqpar.Nslices
        [tmp, RELATIVELOC] = min(abs(tSearchInterval - ...
            sqpar.time_slice_to_slice*(s-1)) );

        LOCS((n-1)*Nslices + s) = LOCVOLSTART + RELATIVELOC - 1;
    end
end


function [bboxLeft3M,bboxRight3M] = getBreastMask(scan3M)
% AI 1/16/18

%Get no. of slices,rows,  cols
nSlices = size(scan3M,3);
nCol = size(scan3M,2);
nRow = size(scan3M,1);
airTh = 400;
tol = 0;
filt = gausswin(13,1.5);
filt = filt./sum(filt(:));

%Loop over slices
bboxLeft3M = false(size(scan3M));
bboxRight3M = false(size(scan3M));
fVoxV = nan(1,nSlices);
bsizeV = nan(1,nSlices);

for i = 1: nSlices

    sliceM = scan3M(:,:,i);

    %Get index of last voxel in each column with inensity > threshold
    th_maskM = sliceM>airTh;
    th_maskM = bwareaopen(th_maskM,50);

    fVoxV(i) = nnz(th_maskM(:))/numel(th_maskM(:));
    rowIdxV = nan(nCol,1);
    for j = 1 : nCol
        idx = find(th_maskM(:,j),1,'last');
        if ~isempty(idx)
            rowIdxV(j) = idx;
        end
    end
    colIdxV = [1:nCol].';
    % startCol = find(~isnan(rowIdxV),1);
    % endCol = find(~isnan(rowIdxV),1,'last');

    try

        %Smooth outline
        outlineV = smooth(colIdxV,rowIdxV,'rlowess');

        %Find peaks
        outSmoothV = conv(outlineV,filt,'same');
        [~,boundsV] = findpeaks(outSmoothV,'MinPeakProminence',10,'SortStr','descend');
        boundsV = sort(boundsV(1:2));

        %AI 2/10/20
        %Added to handle cases where one side is not visible
        if abs(outSmoothV(boundsV(2))-outSmoothV(boundsV(1)))>100
            %skip slice
            emptyMaskM = false(size(th_maskM));
            bboxLeft3M(:,:,i) = emptyMaskM;
            bboxRight3M(:,:,i) = emptyMaskM;
            fVoxV(i) = 0;
            bsizeV(i)=0;
        else
            %Find valley between peaks
            flipSigV = nRow-outlineV(boundsV(1):boundsV(2));
            [~,locV] = findpeaks(flipSigV,'MinPeakProminence',30,'SortStr','descend');
            if isempty(locV)
                [~,locV] = findpeaks(flipSigV,'SortStr','descend');
            end
            loc = locV(1) + boundsV(1);
            rowLim = outlineV(loc);
            rowLim = rowLim-tol;

            % --- For testing ----
            %Display
            %   figure,scatter(colIdxV,rowIdxV,'bo'),axis([1 nCol 1 nRow]);
            %   hold on
            %   plot(colIdxV,outlineV,'--r')
            %---------------------

            outlineV(outlineV<rowLim) = rowLim;
            bsizeV(i) = max(outlineV)- rowLim;

            %Create mask
            xV = [flipud(colIdxV);colIdxV];
            yV = [repmat(rowLim,nCol,1);outlineV];
            maskM = poly2mask(xV,yV,nRow,nCol) & th_maskM;
            maskM = bwareaopen(maskM,100);
            leftMaskM = maskM;
            leftMaskM(:,loc+1:end) = 0;
            rightMaskM = maskM;
            rightMaskM(:,1:loc) = 0;

            %Morphological processing
            leftMaskM = imfill(leftMaskM,'holes');
            leftMaskM = imclose(leftMaskM,strel('disk',4));
            rightMaskM = imfill(rightMaskM,'holes');
            rightMaskM = imclose(rightMaskM,strel('disk',4));

            bboxLeft3M(:,:,i) = leftMaskM;
            bboxRight3M(:,:,i) = rightMaskM;
        end

    catch

        fVoxV(i) = 0;
        bsizeV(i) = 0;

    end
end

%Plot size across slices
sliceV = 1:length(bsizeV);
% Smooth to remove sudden spikes
filtV = gausswin(64,10.5);
filtV = filtV./sum(filtV);
smooth_bsizeV = medfilt1(bsizeV,10);
smooth_bsizeV = conv(smooth_bsizeV,filtV,'same');
% Get dir of change in size
diffV = diff(smooth_bsizeV);
signV = [0 sign(diffV)];
signV = movmean(signV,10);             %Smooth

%Identify slices to retain
startsV = find([1,diff(signV)]);       %Starts of runs
runsV = diff(find([1,diff(signV),1])); %Lengths of runs
[runsV,orderV] = sort(runsV,'descend');
startsV = startsV(orderV);

% Find start slice
count = 0;
incFlag = 0;
while ~incFlag
    count = count+1;
    start1Idx = startsV(count);
    incFlag = signV(start1Idx)>0;
end
end1Idx = start1Idx+runsV(count)-1;
% Find end slice
run2IdxV = startsV>end1Idx;
startsV = startsV(run2IdxV);
runsV = runsV(run2IdxV);
count = 0;
decFlag = 0;
while ~decFlag
    count = count+1;
    start2Idx = startsV(count);
    decFlag = signV(start2Idx)<0;
end
end2Idx = start2Idx+runsV(count)-1;
minSizIdx = find(smooth_bsizeV(start2Idx:end2Idx)>= smooth_bsizeV(start1Idx)*.8,1,'last');
end2Idx = start2Idx + minSizIdx - 1;
keepSlicesV = start1Idx:end2Idx;
skipIdxV = ~ismember(sliceV,keepSlicesV);

% --- For testing (plot of bsizeV)----
% h = figure('visible','On');
% plot(sliceV,bsizeV,'-kx','lineWidth',1);
% axis([1 numel(sliceV),0,max(smooth_bsizeV)])
% hold on
% plot(sliceV,smooth_bsizeV,'--bx','lineWidth',1);
% line([start1Idx,start1Idx],[0,max(smooth_bsizeV)],'Color','r','LineStyle','--');
% line([end2Idx,end2Idx],[0,max(smooth_bsizeV)],'Color','r','LineStyle','--');
% xlabel('Size');
% ylabel('Slice #');
%----------------------------------

%Skip selected slices
bboxLeft3M(:,:,skipIdxV) = false(size(scan3M,1),size(scan3M,2),nnz(skipIdxV));
bboxRight3M(:,:,skipIdxV) = false(size(scan3M,1),size(scan3M,2),nnz(skipIdxV));

end


function [ fighandle, surfh ] = DrawImageSlice3D( dicom_filename,  fighandle,  transparency )
%============================
% [ fighandle, surfh ] = DrawImageSlice3D( dicom_filename,  fighandle,  transparency )
% This is a function for drawing slices in 3D space based on the dicom header
% information.
% Input:
%   dicom_filename = full path to a DICOM image file. Default = '*'
%                   empty string ('') or and string with a wildcard (*) will prompt the file browser
%   figh = figure handle
%   transparency = alpha for the image slice.
%                   Use values < 1 to get partial transparency when
%                   plotting multiple slices in one figure
% Example:
% First pick and image (assuming the DICOM file extension is IMA) and draw the slice semi-transparent
%  [ fighandle, surfh(1) ] = DrawImageSlice3D( '*.IMA',  [],  0.5 );
% Next, call up a second image and draw a slice in the same figure
%  [ fighandle, surfh(2) ] = DrawImageSlice3D( 'mysecond_dicomim.IMA', fighandle,  0.5 );
%
% The axes are rotated at the end of this function.
% A simple edit setting 'show_rotate' to 0 will suppress this.
%
% NOTE: In the DICOM file there are several series UID and reference frame UID to
% ensure that the slices are from the same study and position.
% No check for this is included in this function. One could compose figures
% with slices of different subjects if so inclined.
% The DICOM fields used should be universal, the reference frame should be
% patient orientation dependend X = RL, Y =AP, Z = FH
%
%======================================================================

%======================================================================
% Ronald Ouwerkerk , NIH/NIDDK, June 2010
% Tested on Mac OS 10.5 with Martlab  2008b on Siemens DICOM images (VB15 export to offline)
% Images were all head first supine. Let me know if other orientations
% create problems.
%======================================================================

%% Define constants
topl = 1;
topr = 2;
botl = 3;
botr = 4;

X = 1;
Y = 2;
Z = 3;

%% Set defaults for input arguments
if nargin <1
    dicom_filename = '*';
end

if nargin <2
    fighandle = [];
end

if ~ishandle( fighandle )
    msgstr = sprintf('Warning in %s: Second argument is not a valid figure handle. Creating a new one', mfilename);
    disp( msgstr)
     fighandle = [];
end

if nargin <3
   transparency = 1;
end

if isempty( dicom_filename )
    dicom_filename = '*';
end

%save the current path
orig_path = pwd;

% Call the filebrowswer UI if the dicom filename contains a wildcard
if ~isempty( findstr( dicom_filename, '*') )
    [ filename, fpath ] = uigetfile( dicom_filename , 'Select DICOM file');
    cd( fpath );
    dicom_filename =filename;
end

%% Read DICOM header and image data
dinfo= dicominfo( dicom_filename );
imdata = dicomread(  dicom_filename );
cd( orig_path )

%% Calculate slice corner positions from the DICOM header info
% Get the top left corner position in XYZ coordinates
pos    = dinfo.ImagePositionPatient;

nc = double(dinfo.Columns);
nr = double(dinfo.Rows);

% Get the row and column direction vercors in XYZ coordinates
row_dircos(X) = dinfo.ImageOrientationPatient(1);
row_dircos(Y) = dinfo.ImageOrientationPatient(2);
row_dircos(Z) = dinfo.ImageOrientationPatient(3);
col_dircos(X) = dinfo.ImageOrientationPatient(4);
col_dircos(Y) = dinfo.ImageOrientationPatient(5);
col_dircos(Z) = dinfo.ImageOrientationPatient(6);

% % Check normality and orthogonality of the row and col vectors
% Crownorm = dot(row_dircos, row_dircos);
% Ccolnorm = dot(col_dircos, col_dircos);
% Cdotprod = dot(row_dircos, col_dircos);
%
% if abs(Cdotprod) > 1e-5
%     warnstr = sprintf('Possible dicominfo error: the dotproduct of the row and col vectors is %f should be 0',Cdotprod );
%     disp(warnstr)
% end

% Calculate image dimensions
row_length = dinfo.PixelSpacing(1) * nr;
col_length = dinfo.PixelSpacing(2) * nc;

%% Set up the corner positions matrix in XYZ coordinates
% Top Left Hand Corner
corners( topl, X) = pos(X);
corners( topl, Y) = pos(Y);
corners( topl, Z) = pos(Z);

% Top Right Hand Corner
corners( topr, X) = pos(X) + row_dircos(X) * row_length;
corners( topr, Y) = pos(Y) + row_dircos(Y) * row_length;
corners( topr, Z) = pos(Z) + row_dircos(Z) * row_length;

% Bottom Left Hand Corner
corners( botl, X) = pos(X) + col_dircos(X) * col_length;
corners( botl, Y) = pos(Y) + col_dircos(Y) * col_length;
corners( botl, Z) = pos(Z) + col_dircos(Z) * col_length;

% Bottom Right Hand Corner
corners( botr, X) = pos(X) + row_dircos(X) * row_length + col_dircos(X) * col_length;
corners( botr, Y) = pos(Y) + row_dircos(Y) * row_length + col_dircos(Y) * col_length;
corners( botr, Z) = pos(Z) + row_dircos(Z) * row_length + col_dircos(Z) * col_length;

%% Prepare the figure
% Select active figure, set hold on to alow multiple slices in one figure
if isempty(  fighandle )
     fighandle = figure;
     colormap( gray );
     newfig = 1;
else
    newfig = 0;
end

figure( fighandle );
hold on;

%Tidy up the figure
% set aspect ratio
daspect( [1,1,1]);
set( gca, 'color', 'none')

%% Display slice
%  normalize image data
imdata = double( imdata );
imdata = imdata / max( imdata(:));
% scale the image
I = imdata*255;
% create an alternative matrix for corner points
A( 1,1 , 1:3 ) = corners( topl, : );
A( 1,2 , 1:3 ) = corners( topr, : );
A( 2,1 , 1:3 ) = corners( botl, : );
A( 2,2 , 1:3 ) = corners( botr, : );
% extract the coordinates for the surfaces
x = A( :,:,X );
y = A( :,:,Y );
z = A( :,:,Z );

% plot surface
surfh = surface('XData',x,'YData',y,'ZData',z,...
'CData', I,...
'FaceColor','texturemap',...
'EdgeColor','none',...
'LineStyle','none',...
'Marker','none',...
'MarkerFaceColor','none',...
'MarkerEdgeColor','none',...
'CDataMapping','direct');
%set transparency level
set( surfh, 'FaceAlpha', transparency );
% label axes and optimize figure
xlabel('RL');
ylabel('AP');
zlabel('FH');

% if only one slice is in the figure this may flatten the 3rd axis
if ~newfig
    axis tight
end

%% Optional: rotate to show all
% edit this to create a movie
do_movie = 0;
show_rotate = 1

if do_movie
    % open avifile
    aviobj = avifile('slice3Drotate.avi');
    show_rotate = 1;
end

if show_rotate
    % tilt and rotate
    el = 22;
    for azplus = 0:10:360
        az = mod( 45+azplus, 360);
        view( [az, el] );
        if do_movie
            % add farem to the movie
            frame = getframe(fh);
            aviobj = addframe(aviobj,frame);
        else
            % needed to see the intemediate steps
           drawnow;
        end
    end
end

if do_movie
    % close avifile
    close( aviobj );
end

return


function alpha_filter = getAlphaFilter(kgrid, medium, filter_cutoff, taper_ratio)
%GETALPHAFILTER Create filter for medium.alpha_filter.
%
% DESCRIPTION:
%       getAlphaFilter uses getWin to create a Tukey window via rotation to
%       pass to the medium.alpha_filter input field of the first order
%       simulation functions (kspaceFirstOrder1D, kspaceFirstOrder2D, and
%       kspaceFirstOrder3D). This parameter is used to regularise time
%       reversal image reconstruction when absorption compensation is
%       included.
%
% USAGE:
%       alpha_filter = getAlphaFilter(kgrid, medium, filter_cutoff)
%       alpha_filter = getAlphaFilter(kgrid, medium, filter_cutoff, taper_ratio)
%
% INPUTS:
%       kgrid           - k-Wave grid structure returned by makeGrid
%       medium          - k-Wave medium structure
%       filter_cutoff   - alpha_filter cutoff frequency [Hz], where
%                         filter_cutoff = [f_all] in 1D
%                         filter_cutoff = [f_all] or [f_x, f_y] in 2D
%                         filter_cutoff = [f_all] or [f_x, f_y, f_z] in 3D
%
%                         Any of the filter_cutoff inputs may be set to
%                         'max' to set the cutoff frequency to the maximum
%                         frequency supported by the grid
%
% OPTIONAL INPUTS
%       taper_ratio     - taper ratio for Tukey Window (default = 0.5)
%
% OUTPUTS:
%       alpha_filter    - filter
%
% ABOUT:
%       author          - Bradley Treeby
%       date            - 6th May 2010
%       last update     - 28th October 2011
%
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009-2014 Bradley Treeby and Ben Cox
%
% See also getWin

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

% update the command line status
disp('Creating absorption filter...');

% check to see if the taper ratio is given
if nargin == 3
    taper_ratio = 0.5;
elseif nargin ~= 4
    error('incorrect number of inputs');
end

% update command line status
disp(['  taper ratio: ' num2str(taper_ratio)]);

% extract the dimensions
dim = numDim(kgrid.k);

% extract the alpha_filter cutoff frequencies
if numel(filter_cutoff) == 1
    filter_cutoff_x = filter_cutoff;
    if dim > 2
        filter_cutoff_z = filter_cutoff;
    end
    if dim > 1
        filter_cutoff_y = filter_cutoff;
    end
elseif numel(filter_cutoff) ~= dim
    error(['input filter_cutoff must have 1 or ' num2str(dim) ' elements for a ' num2str(dim) 'D grid']);
else
    if dim == 1
        filter_cutoff_x = filter_cutoff{1};
    end
    if dim == 2
        filter_cutoff_x = filter_cutoff{1};
        filter_cutoff_y = filter_cutoff{2};
    end
    if dim == 3
        filter_cutoff_x = filter_cutoff{1};
        filter_cutoff_y = filter_cutoff{2};
        filter_cutoff_z = filter_cutoff{3};
    end
end

% extract the maximium sound speed
c = max(medium.sound_speed(:));

% calculate the alpha_filter size in the z direction for 3D data
if dim > 2
    if strcmp(filter_cutoff_z, 'max')
        % set the alpha_filter size to be the same as the grid size
        filter_size_z = kgrid.Nz;
        filter_cutoff_z = kgrid.kz_max*c/(2*pi);
    else
        % convert the cutoff frequency to a wavenumber
        k_cutoff_z = 2*pi*filter_cutoff_z ./ c;

        % set the alpha_filter size
        filter_size_z = round(kgrid.Nz*k_cutoff_z/kgrid.kz(end));

        % check the alpha_filter size
        if filter_size_z > kgrid.Nz
            % set the alpha_filter size to be the same as the grid size
            filter_size_z = kgrid.Nz;
            filter_cutoff_z = kgrid.kz_max*c/(2*pi);
        end
    end
end

% calculate the alpha_filter size in the y direction for 2 and 3D data
if dim > 1
    if strcmp(filter_cutoff_y, 'max')
        % set the alpha_filter size to be the same as the grid size
        filter_size_y = kgrid.Ny;
        filter_cutoff_y = kgrid.ky_max*c/(2*pi);
    else
        % convert the cutoff frequency to a wavenumber
        k_cutoff_y = 2*pi*filter_cutoff_y ./ c;

        % set the alpha_filter size
        filter_size_y = round(kgrid.Ny*k_cutoff_y/kgrid.ky(end));

        % check the alpha_filter size
        if filter_size_y > kgrid.Ny
            % set the alpha_filter size to be the same as the grid size
            filter_size_y = kgrid.Ny;
            filter_cutoff_y = kgrid.ky_max*c/(2*pi);
        end
    end
end

% calculate the alpha_filter size in the x direction for 1, 2, and 3D data
if strcmp(filter_cutoff_x, 'max')
    % set the alpha_filter size to be the same as the grid size
    filter_size_x = kgrid.Nx;
    filter_cutoff_x = kgrid.kx_max*c/(2*pi);
else
    % convert the cutoff frequency to a wavenumber
    k_cutoff_x = 2*pi*filter_cutoff_x ./ c;

    % set the alpha_filter size
    filter_size_x = round(kgrid.Nx*k_cutoff_x/kgrid.kx(end));

    % check the alpha_filter size
    if filter_size_x > kgrid.Nx
        % set the alpha_filter size to be the same as the grid size
        filter_size_x = kgrid.Nx;
        filter_cutoff_x = kgrid.kx_max*c/(2*pi);
    end
end

% create the alpha_filter using getWin
switch dim
    case 1
        % create the alpha_filter
        filter_sec = getWin(filter_size_x, 'Tukey', 'Param', taper_ratio, 'Rotation', true);

        % enlarge the alpha_filter to the size of the grid
        alpha_filter  = zeros(kgrid.Nx, 1);
        x_index = round((kgrid.Nx - filter_size_x)/2) + 1;
        alpha_filter(x_index:x_index + filter_size_x - 1) = filter_sec;

        % update the command line status
        disp(['  filter cutoff: ' scaleSI(filter_cutoff_x) 'Hz']);
    case 2
        % create the alpha_filter
        filter_sec = getWin([filter_size_x, filter_size_y], 'Tukey', 'Param', taper_ratio, 'Rotation', true);

        % enlarge the alpha_filter to the size of the grid
        alpha_filter  = zeros(kgrid.Nx, kgrid.Ny);
        x_index = round((kgrid.Nx - filter_size_x)/2) + 1;
        y_index = round((kgrid.Ny - filter_size_y)/2) + 1;
        alpha_filter(x_index:x_index + filter_size_x - 1, y_index:y_index + filter_size_y - 1) = filter_sec;

        % update the command line status
        disp(['  filter cutoff: ' scaleSI(filter_cutoff_x) 'Hz by ' scaleSI(filter_cutoff_y) 'Hz']);
    case 3
        % create the alpha_filter
        filter_sec = getWin([filter_size_x, filter_size_y, filter_size_z], 'Tukey', 'Param', taper_ratio, 'Rotation', true);

        % enlarge the alpha_filter to the size of the grid
        alpha_filter  = zeros(kgrid.Nx, kgrid.Ny, kgrid.Nz);
        x_index = round((kgrid.Nx - filter_size_x)/2) + 1;
        y_index = round((kgrid.Ny - filter_size_y)/2) + 1;
        z_index = round((kgrid.Nz - filter_size_z)/2) + 1;
        alpha_filter(x_index:x_index + filter_size_x - 1, y_index:y_index + filter_size_y - 1, z_index:z_index + filter_size_z - 1) = filter_sec;

        % update the command line status
        disp(['  filter cutoff: ' scaleSI(filter_cutoff_x) 'Hz by ' scaleSI(filter_cutoff_y) 'Hz by ' scaleSI(filter_cutoff_z) 'Hz']);
end


function newcat2=plotmi(var1, newcat2, mi)
    %plot misfit (?)
    % TODO make this work with the new catalogs
    report_this_filefun(mfilename('fullpath'));

    global  mif2 mif1
    global tmp % REALLY? global tmp?  "tmp" is 1:nEvents
    % cumu2 mi2
    figNumber=findobj('Type','Figure','-and','Name','Misfit ');
    figure(figNumber);
    delete(findobj(figNumber,'Type','axes'));
    rect = [0.15,  0.15, 0.75, 0.65];
    axes('position',rect)
    ax=gca;
    nEvents=newcat2.Count;
    tmp=1:nEvents;
    sixSlices=round(0 : nEvents/5 : nEvents);
    sixSlices(1)=1;

    var2=var1;

    misfitAngle = mi(:,2);
    X = 1:nEvents;
    xtitle=sprintf('Number of Eqs (sorted by %s)',lower(var1));
    switch (var1)
        case {'Longitude','Latitude','Magnitude','Depth'}
            % plot_by_lon(); %by lon
            plot_by_field(var1);
        case 'Time'
            plot_by_time(); % by date
        case 'Strike'
            plot_by_strike(); % along strike
        case 'Default'
            option_7(); %unsorted
        otherwise
            error('unknown choice for plotmi');
    end

    grid('on')
    set(ax,'Color',color_bg);
    set(ax,'box','on',...
        'SortMethod','childorder','TickDir','out','FontWeight',...
        'bold','FontSize',ZmapGlobal.Data.fontsz.m,'Linewidth',1.2)
    ylabel('Cumulative Misfit ','FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m);
    xlabel(xtitle,'FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m)

    if ~ strcmp(var1 ,'Default')
        hold on
        for i=1:6
            plot(ax,tmp(sixSlices(i)),cumu2(sixSlices(i)),'xr');
            str=['  ',num2str(newcat2(sixSlices(i),var2))];
            te=text(tmp(sixSlices(i)),cumu2(sixSlices(i)),str);
            set(te,'FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.s)
        end
    else

    end

    function plot_by_field(name)
        % assumes that misfit matrix (mi) has same number of rows as
        % number of earthquakes in catalog
        [~,is] = sort(newcat2.(name));
        newcat2.sort(name); % sort the catalog itself by this field

        cumu2=cumsum(misfitAngle(is));
        plot(1:nEvents , cumu2 , 'o');
        xtitle=sprintf('Number of Eqs (sorted by %s)',lower(name));
    end

    function plot_by_time()
        [~,is] = sort(newcat2.Date);
        newcat2.sort(Date);
        cumu2=cumsum(misfitAngle(is));
        pl = plot(tmp,cumu2,'o');
        xtitle='Number of Eqs (sorted by time)';
    end

    function plot_by_strike()
        % [~,is] = sort(newcat2(:,15));
        [~,is] = sort(newcat2(:,end));
        newa2 = newcat2.subset(is) ;
        cumu2=cumsum(misfitAngle(is));
        pl = plot(newa2(:,16)-18.6,cumu2,'o');
        xtitle='Number of Eqs (sorted along strike)';
        var2=15;
    end

    function option_7()
        mi2 = mi ;
        cumu2=cumsum(mi2(:,2));
        pl = plot(tmp,cumu2,'o');
        xtitle='Number of Eqs ';
    end
end


function outBfull()
    global config mem;
    current_layer = config.misc.current_layer;
    mem.grads{current_layer+1} = mem.deltas{current_layer+1} * mem.activations{current_layer}';
    mem.grads{current_layer+1+config.layer_num} = sum(mem.deltas{current_layer+1}, 2);
end


function res = removeObsRobpca(data,i,k,Hsets_min_i,same,factor_ind,csteps)

%REMOVEOBSROBPCA is an auxiliary function to perform cross-validation with ROBPCA,
% RPCR, RSIMPLS, RSIMCA (see cvRobpca.m, cvRpcr.m, cvRsimpls.m).
%
% Input:
%    data : the data set
%       i : the observation that is removed, index with respect to the whole data set.
%       k : the number of principal components that has to be calculated.
%  Hsets_min_i : contains H0_min_i, H1_min_i and Hfreq_min_i as first, second and third row respectively.
%                The h-subsets are implemented by means of indices of the observations in data_min_i, which is
%                is the original data set minus sample i.
%  same : structure :
%           same.value : indicates whether some part of this algorithm can be skipped (= 1) or not ( = 0).
%           same.res : if same.value = 1, then some additional information is needed.
%  factor : optional. default  = 0, then the original consistency factor is used.
%             Else factor = 1, the consistency factor is adapted to the kmax approach.
%  csteps : optional structure:
%            csteps.value : 1 (default, then csteps are performed within robpca), 0 (no csteps are performed within robpca)
%            csteps.number : the number of csteps that need to be performed (default = 2).
%
% Output:
% res is the result structure. It contains:
%   Pk_min_i  : update of the loadingmatrix for a certain k when observation i is deleted.
%   Lk_min_i  : update of the eigenvalues for a certain k when observation i is deleted.
%   muk_min_i : update of the center for a certain k when observation i is deleted.
%
% This function is part of LIBRA: the Matlab Library for Robust Analysis,
% available at:
%              http://wis.kuleuven.be/stat/robust.html
%
% Written by S. Engelen

rot = [];
center = [];
P1 = [];

n = size(data,1);
p = size(data,2);
h = size(Hsets_min_i,2) + 1;

if nargin < 6
    factor_ind = 0;
    csteps.number = 2;
    csteps.value = 1;
elseif nargin == 6
    csteps.number = 2;
    csteps.value = 1;
end

data_min_i= removal(data,i,0);
mu0 = mean(data);
center = mu0;

H0_min_j = Hsets_min_i(1,:);
H1_min_t = Hsets_min_i(2,:);

if ~same.value
    [PH0_min_i,TH0,LH0_min_i,rH0_min_i,centerX,mu1trafo]=kernelEVD(data_min_i(H0_min_j,:));
    LH0_min_i = diag(LH0_min_i);

    % calculation of the projection
    % res.T2tilde = T2tilde;
    center = mu1trafo;
    rot = PH0_min_i;
    T2tilde = (data_min_i - repmat(mu1trafo,n-1,1))*PH0_min_i;
    T2tilde = T2tilde(:,1:k);
    rot = rot(:,1:k);

    % defining the outputstructure res:
    res.PH0_min_i = PH0_min_i;
    res.LH0_min_i = LH0_min_i;
    res.mu1trafo = mu1trafo;
else
    % defining the input structure input
    res = same.res;
    PH0_min_i = res.PH0_min_i;
    LH0_min_i = res.LH0_min_i;
    mu1trafo = res.mu1trafo;
    T2tilde = (data_min_i - repmat(mu1trafo,n-1,1))*PH0_min_i;
    center = mu1trafo;
    rot = PH0_min_i;
    rot = rot(:,1:k);
    T2tilde = T2tilde(:,1:k);
end

mah = libra_mahalanobis(T2tilde,zeros(1,k),'invcov',1./diag(LH0_min_i(1:k,1:k)));
oldobj = prod(diag(LH0_min_i(1:k,1:k)));P4 = eye(k);

if csteps.value
    oldobj = prod(diag(LH0_min_i(1:k,1:k)));
    for j = 1:csteps.number
        [mahsort, indsort] = sort(mah);
        dataH1 = T2tilde(indsort(1:(h-1)),:);
        [P,T,L,r3,Xm,clmX] = classSVD(dataH1);
        obj = prod(L);
        T2tilde = (T2tilde - repmat(clmX,n-1,1))*P;
        center = center + clmX*rot';
        rot = rot*P;
        mah = libra_mahalanobis(T2tilde,zeros(1,size(T2tilde,2)),'invcov',1./L);
        P4 = P4*P;
        if abs(oldobj - obj) > 1.e-12
            oldobj = obj;
        else
            break
        end
    end
else
    obj = oldobj;
end

% extra reweighting:
if k~=r3
    XRc= data_min_i-repmat(center,n-1,1);
    Xtilde = T2tilde*rot';
    Rdiff = XRc-Xtilde;
    for i=1:n
        odh(i,1)=norm(Rdiff(i,:));
    end
    [m,s]=unimcd(odh.^(2/3),h);
    cutoffodh = sqrt(norminv(0.975,m,s).^3);
    indexset = find(odh<=cutoffodh)';
    [P,Threw,Lrew,rrew,Xmrew,clmX]=kernelEVD(data_min_i(indexset,:));
    center = clmX;
    rot = P(:,1:k);
end
T2tilde = (data_min_i - repmat(center,n-1,1))*rot;

% Perform mcdcov on some H-subsets:
[res_min_i,raw_min_i] = mcdcov(T2tilde,'Hsets',Hsets_min_i,'h',h-1,'ntrial',250,'plots',0,'factor',1);
% perform the last part of ROBPCA:
if raw_min_i.objective < obj
    z = res_min_i;
else
    sortmah = sort(mah);
    if h==n
        factor=1;
    else
        if factor_ind == 1
            factor = sortmah(h-1)/chi2inv((h-1)/size(T2tilde,1),size(T2tilde,2)/2); % adjusted factor.
        else
            factor = sortmah(h-1)/chi2inv((h-1)/size(T2tilde,1),size(T2tilde,2)); % non adjusted factor
        end
    end
    mah = mah/factor;
    weights = mah <= chi2inv(0.975,size(T2tilde,2));
    [center_noMCD,cov_noMCD] = weightmecov(T2tilde,weights);
    mah = libra_mahalanobis(T2tilde,center_noMCD,'cov',cov_noMCD);
    z.flag = (mah <= chi2inv(0.975,size(T2tilde,2)));
    z.center = center_noMCD;
    z.cov = cov_noMCD;
end

covf=z.cov;
centerf=z.center;

% The final PC:
[P6tilde,L6]=eig(covf);
[L6,I]=greatsort(diag(L6));
P6tilde=P6tilde(:,I);
T_min_i=(T2tilde-repmat(centerf,n-1,1))*P6tilde;

Pk_min_i=rot(:,1:k)*P6tilde;
Lk_min_i = L6;

res.Pk_min_i = Pk_min_i;
res.Lk_min_i = Lk_min_i;
res.muk_min_i = center + centerf*rot';


function [ y, j, f, ierror ] = yjf_check_english ( y, j, f )

%*****************************************************************************80
%
%% YJF_CHECK_ENGLISH normalizes an English YJF date.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 March 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input/output, integer Y, J, real F, the YJF date.
%
%    Output, integer IERROR, nonzero if there was an error.
%
  [ y, j, ierror ] = yj_check_english ( y, j );

  if ( ierror ~= 0 )
    return
  end
%
%  Force the fraction to lie between 0 and 1.
%
  while ( f < 0.0 )
    f = f + 1.0
    j = j - 1;
  end

  while ( 1.0 <= f )
    f = f - 1.0;
    j = j + 1;
  end

  return
end


function [y] = ge(x, val)

y = cell(size(x));
for k = 1:numel(x)
  y{k} = x{k}>=val;
end


function c8_uniform_01_test ( )

%*****************************************************************************80
%
%% C8_UNIFORM_01_TEST tests C8_UNIFORM_01.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 June 2006
%
%  Author:
%
%    John Burkardt
%
  seed = 123456789;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'C8_UNIFORM_01_TEST\n' );
  fprintf ( 1, '  C8_UNIFORM_01 computes pseudorandom complex values\n' );
  fprintf ( 1, '  in the unit circle.\n' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The initial seed is %d\n', seed );
  fprintf ( 1, '\n' );

  for i = 1 : 10
    [ x, seed ] = c8_uniform_01 ( seed );
    fprintf ( 1, '  %6d  ( %f, %f )\n', i, real ( x ), imag ( x ) );
  end

  return
end


%% QUAD_FSU uses the fsuClusterMatlab command to run the QUAD computation.
%
%  Discussion:
%
%    The arguments to fsuClusterMatlab mean:
%
%    [] allows us to specify an output directory;
%    [] allows us to specify switches to the MOAB queue handler, such as more time.
%    's' indicates this is a "simple" (task) job;
%    'w' indicates that the MATLAB session should wait for completion;
%    task_num is the number of tasks;
%    @quad_task indicates the function we want to execute;
%    args contains input arguments to each of the tasks.
%
%    The function "quad_task" must correspond to a MATLAB M-file "quad_task.m"
%    and that file must be in MATLAB's path.
%
%    The easiest way to ensure that the file is in MATLAB's path is to
%    create a subdirectory called "matlab" immediately below your home directory,
%    and place the function file there (as well as any other files needed by the job).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 April 2010
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'QUAD_FSU:\n' );
  fprintf ( 1, '  Use MATLAB''s task computing on the FSU HPC cluster.\n' );
  fprintf ( 1, '  Here, we estimate an integral over an interval by\n' );
  fprintf ( 1, '  dividing the interval into subintervals.\n' );

  n = 100001;
  a = 0.0;
  b = 1.0;

  task_num = 4;
  n_task = 1 + floor ( ( n - 1 ) / task_num );

  args = {};
  for task = 1 : task_num
    a_task = ( task - 1 ) / task_num;
    b_task =   task       / task_num;
    args{task} = { n_task, a_task, b_task };
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Call fsuClusterMatlab:\n' );

  results = fsuClusterMatlab ( [], [], 's', 'w', task_num, @quad_task, args )
%
%  Convert RESULTS, which is a TASK_NUMx1 cell array, to
%  an ordinary MATLAB numeric array.
%
  results = cell2mat ( results );
%
%  Now we can use the SUM command to get our result.
%
  q = sum ( results );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Quadrature result is %f\n', q );


function C=searchintial(X,method,varargin)
switch lower(method(1))
    case 's'
        K=varargin{1};
        C=X(randsample(size(X,1),K),:);
    case 'u'
        Xmins=min(X,[],1);
        Xmaxs=max(X,[],1);
        K=varargin{1};
        C=unifrnd(Xmins(ones(K,1),:), Xmaxs(ones(K,1),:));
end

github-repos/MATLAB/decouples-Matlab_deep_learning/Matlab_deep_learning-1b823b82686080e32b03e1f1a4648896bd6e3c44/第 22 章 基于 K-means 聚类算法的图像区域分割/searchintial.m


function f = abs(f)
%ABS   Absolute value of a CHEBFUN3.
%   ABS(F) returns the absolute value of a CHEBFUN3 object F. This function
%   gives an error if the function passes through or becomes numerically
%   close to zero.
%
% See also CHEBFUN3/COMPOSE.

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

if ( isempty(f) ) % check for empty CHEBFUN3.
    return
end

if ( isreal(f) )
    % Positive/negative test.
    [ss, ~, ispos] = singleSignTest(f); % Returns TRUE if there is no sign change.
    if ( ss )
        if (ispos)
            return
        else
            f = uminus(f);
            return
        end
    elseif( ~ss )
        error('CHEBFUN:CHEBFUN3:abs:notSmooth', ...
            'Sign change detected. Unable to represent the result.');
    end
else
    % Call the constructor for complex f:
    f = compose(f, @abs);
end

end


% MCMCACF - autocorrelation plots
% Copyright (c) 1998, Harvard University. Full copyright in the file Copyright
%
% This is not a function, but a way to get acf plots for MCMC runs.
%
% S = mcmcsumm(A) contains S.acf, a matrix of the autocorrelations.
%
% So, mcmctrace(S.acf) will plot the autocorrelations.
%
% See also: MCMCSUMM, MCMCTRACE


function featureReducedS = reduceDirFeatures(featuresAllDirS, reduceType)
% function featureReducedS = reduceDirFeatures(featuresAllDirS, reduceType)
%
% This function combines the directional feature values into a single
% value. The reduceType specifies how the different directions should be
% combined. The supported reduceTypes are 'avg', 'max', 'min', 'std',
% 'mad', 'iqr'
%
% APA, 4/11/2017

filedNamC = fieldnames(featuresAllDirS);

for iField = 1:length(filedNamC)
    fieldName = filedNamC{iField};
    switch lower(reduceType)
        case 'avg'
            featureReducedS.(fieldName) = mean([featuresAllDirS.(fieldName)]);
        case 'min'
            featureReducedS.(fieldName) = min([featuresAllDirS.(fieldName)]);
        case 'max'
            featureReducedS.(fieldName) = max([featuresAllDirS.(fieldName)]);
        case 'std'
            featureReducedS.(fieldName) = std([featuresAllDirS.(fieldName)]);
        case 'mad'
            featureReducedS.(fieldName) = mad([featuresAllDirS.(fieldName)]);
        case 'iqr'
            featureReducedS.(fieldName) = mad([featuresAllDirS.(fieldName)]);
    end
end


function [sta_index, orid_index, eqtimes, eqindices, nstations, norigins] = arrivals_rearrange(arrivals, stations)
%% Arrange info from earthquake catalogue into a more useful format

% We want a column for each station and a row for each earthquake (origin).
% Store arrival times in this format for now, so we can later replace them
% with loaded waveforms.

% Number of stations.  Use user-specified list and order (rather than
% unique values from arrivals table) for greater flexibility.
nstations = length(stations);

% Number of earthquakes
norigins = length(arrivals.unique_orids);

% Allocate an array to store arrival times
eqtimes = zeros(norigins,nstations);

% Allocate an additional array to store the indices, so we can retrieve
% other data (e.g. event type) later
eqindices = zeros(norigins,nstations);

% Now go through each arrival and place it in the array
for n = 1:length(arrivals.orid)
	sta_index = find(strcmp(arrivals.sta{n},stations),1);
	orid_index = find(unique_orids == arrivals.orid(n),1); % Could do something more efficient here; orid is sorted in ascending order so a find is not really necessary
	eqtimes(orid_index,sta_index) = arrivals.atime(n);
	eqindices(orid_index,sta_index) = n;
end


% LIONSIMBA example script
% Multiple cells scenario: simulates three cells in serial connection.

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

% Clear the workspace
clear

% Define the integration times.
t0 = 0;
tf = 10^4;
% Define the parameters structure.
param{1} = Parameters_init;
param{2} = Parameters_init;
param{3} = Parameters_init;

% Modify the initial SOC of cell #1
param{1}.cs_n_init = 0.95*param{1}.cs_n_init;

% Double the length of the positive electrode of cell #2
param{2}.len_p=2*param{2}.len_p;

% Simulate the battery of 3 cells
results = startSimulation(t0,tf,[],-30,param);

ncells = length(param);

v_tot = 0;
for i=1:ncells
    v_tot = v_tot + results.Phis{i}(:,1)-results.Phis{i}(:,end);
end
%% Plot the results

figure(1)
subplot(2,ncells,(1:ncells))
plot(results.time{1},v_tot,'LineWidth',6)
grid on
box on
xlabel('Time [s]')
ylabel('Pack Voltage [V]')
hold on
xlim([0 results.time{1}(end)])
ylim([2.5*length(param) 4.2*length(param)])

figure_index = ncells+1;
for i=1:ncells
    subplot(2,ncells,figure_index)
    plot(results.time{i},results.Voltage{i},'--','LineWidth',3)
    grid on
    box on
    xlabel('Time [s]')
    ylabel(['Cell #',num2str(i),' Voltage [V]'])
    figure_index = figure_index+1;
    ylim([2.5 4.2])
    xlim([0 results.time{1}(end)])
end

n_plots = 1;
figure_index = 1;
figure(2)
for i=1:ncells
    subplot(ncells,n_plots,figure_index)
    ce_indices = [1 results.parameters{i}.Np+1 results.parameters{i}.Np+results.parameters{i}.Ns results.parameters{i}.Np+results.parameters{i}.Ns+results.parameters{i}.Nn];
    plot(results.time{i},results.ce{i}(:,ce_indices),'LineWidth',3)
    grid on
    box on
    if(figure_index==ncells)
        xlabel('Time [s]')
    else
%         set(gca,'xtick',[])
        set(gca,'xticklabel',[])
    end
    ylabel(['Cell #',num2str(i),' - c_{e} [mol/m^3}'])
    xlim([0 results.time{1}(end)])
    ylim([0 2200])
    figure_index = figure_index+1;
end

n_plots = 1;
figure_index = 1;
figure(3)
for i=1:ncells
    subplot(ncells,n_plots,figure_index)
    phie_indices = [1 results.parameters{i}.Np+1 results.parameters{i}.Np+results.parameters{i}.Ns results.parameters{i}.Np+results.parameters{i}.Ns+results.parameters{i}.Nn];
    plot(results.time{i},results.Phie{i}(:,phie_indices),'LineWidth',3)
    grid on
    box on
    if(figure_index==ncells)
        xlabel('Time [s]')
    else
%         set(gca,'xtick',[])
        set(gca,'xticklabel',[])
    end
    ylabel(['Cell #',num2str(i)])
    xlim([0 results.time{1}(end)])
    ylim([-0.3 0])
    figure_index = figure_index+1;
end

n_plots = 1;
figure_index = 1;
figure(4)
for i=1:ncells
    subplot(ncells,n_plots,figure_index)
    cs_indices = [1 results.parameters{i}.Np results.parameters{i}.Np+1 results.parameters{i}.Np+results.parameters{i}.Nn];
    plot(results.time{i},results.cs_surface{i}(:,cs_indices),'LineWidth',3)
    grid on
    box on
    if(figure_index==ncells)
        xlabel('Time [s]')
    else
%         set(gca,'xtick',[])
        set(gca,'xticklabel',[])
    end
    ylabel(['Cell #',num2str(i)])
    xlim([0 results.time{1}(end)])
    ylim([100 51554])
    figure_index = figure_index+1;
end

n_plots = 1;
figure_index = 1;
figure(5)
for i=1:ncells
    subplot(ncells,n_plots,figure_index)
    cs_indices = [1 results.parameters{i}.Np results.parameters{i}.Np+1 results.parameters{i}.Np+results.parameters{i}.Nn];
    plot(results.time{i},results.Temperature{i}(:,end),'LineWidth',3)
    grid on
    box on
    if(figure_index==ncells)
        xlabel('Time [s]')
    else
%         set(gca,'xtick',[])
        set(gca,'xticklabel',[])
    end
    ylabel(['Cell #',num2str(i),' - Temp [K]'])
    xlim([0 results.time{1}(end)])
    ylim([296 315])
    figure_index = figure_index+1;
end


function relaxPreprocess(dataDir, outDir, mtOffsetFreqs, excludeScans)
%
% relaxPreprocess(dataDir, outDir, mtOffsetFreqs, excludeScans)
%
% This file computes the T1 map (in seconds) of data obtained using
% the TOF sequence. Also saved are:
%   S0: unsaturated reference map
%   PD: a map that includes spin-density (M0), scanner scaling constant
%       (G), and T2*: PD = M0 * G * exp(-TE / T2*).
%
% SEE ALSO:
%
% relaxAlignRefToAnat.m to align the reference image output by this
% function to a structural anatomy template image.
%
% relaxMtFit.m to fit the f and k maps to the output of this function.
%
% HISTORY:
% 2007.02.?? Nikola Stikov wrote it.
% 2007.03.01 RFD: restructured the code and added auto-detection of
% most scan params.

if(~exist('dataDir','var')||isempty(dataDir))
  dataDir = fullfile(pwd,'raw');
end
if(~exist('outDir','var')||isempty(outDir))
  outDir = fileparts(dataDir);
  if(isempty(outDir)) outDir = pwd; end
end
if(~exist('mtOffsetFreqs','var')||isempty(mtOffsetFreqs))
  mtOffsetFreqs = [];
  error('Auto-detection of the mtOffsetFreqs is not implemented yet!');
end
if(~exist('excludeScans','var')||isempty(excludeScans))
  excludeScans = [];
end

showFigs = false;

s = dicomLoadAllSeries(dataDir);

% Exclude scans that don't match most scans imSize
for(ii=1:length(s))
  sz(ii) = prod(size(s(ii).imData));
end
badScans = find(sz~=median(sz));
if(~isempty(badScans))
  disp(['Adding ' num2str(badScans) ' to exclude list due to size mis-match.']);
  excludeScans = [excludeScans badScans];
end

%% Apply exclusion list
%
if(~isempty(excludeScans))
  s(excludeScans) = [];
end

if(showFigs)
    for(ii=1:length(s))
        showMontage(s(ii).imData);
        set(gcf,'name',[s(ii).desc '(' num2str(s(ii).seriesNum) ')']);
    end
end

% Align all the images
disp('Aligning all series to the first...');
bb = [1 1 1; size(s(1).imData)];
for(ii=2:length(s))
    xform = mrAnatRegister(s(ii).imData,s(1).imData);
    s(ii).imData =  mrAnatResliceSpm(s(ii).imData, xform, bb, [1 1 1], [7 7 7 0 0 0], 0);
    s(ii).imData(isnan(s(ii).imData)|s(ii).imData<0) = 0;
end

%% Process the T1 relaxometry scans
%
t1Inds = find([s.mtOffset]==0);
nT1 = length(t1Inds);

meanOfT1s = mean(cat(4,s(t1Inds).imData),4);
%showMontage(mn);
[brainMask,checkSlices] = mrAnatExtractBrain(meanOfT1s,[],0.25);
%figure;image(checkSlices);

% We save as we go
xform = s(t1Inds(1)).imToScanXform;
dtiWriteNiftiWrapper(uint8(brainMask), xform, fullfile(outDir,'brainMask'));
dtiWriteNiftiWrapper(meanOfT1s, xform, fullfile(outDir,'ref'));
clear meanOfT1s;

brainInds = find(brainMask);
nVox = length(brainInds);

%% Process MT scans
%
% For these, we average multiple repeats/
mtInds = find([s.mtOffset]~=0);
nMt = length(mtInds);

% for(ii=1:length(mtInds)), for(jj=1:length(mtInds))
% 	rms(ii,jj) = sqrt(mean((s(mtInds(ii)).imData(brainInds)-s(mtInds(jj)).imData(brainInds)).^2));
% end, end
mtOffsets = unique(mtOffsetFreqs);
for(ii=1:length(mtOffsets))
    mt = mean(cat(4,s(mtInds(mtOffsetFreqs==mtOffsets(ii))).imData),4);
    dtiWriteNiftiWrapper(mt, xform, fullfile(outDir,sprintf('MT_%02dkHz',mtOffsets(ii))));
end
clear mt;

theta = [s(t1Inds).flipAngle]*pi/180;
x = zeros(nVox,nT1);
y = zeros(nVox,nT1);
for(ii=1:nT1)
  y(:,ii) = abs(s(t1Inds(ii)).imData(brainInds)./sin(theta(ii)));
  x(:,ii) = abs(s(t1Inds(ii)).imData(brainInds)./tan(theta(ii)));
end

% Following is a slow loop. Can it be vectorized?
disp('Fitting T1 estimates for each voxel (SLOW!)');
t1 = zeros(nVox,1);
tic;
for(ii=1:nVox)
  if(mod(ii,20000)==0)
    fprintf('  Processed %d of %d voxels (%0.1f %%) in %0.1f secs...\n',ii,nVox,ii/nVox*100,toc);
  end
  if(max(y(ii,:)>0.001))
    d = polyfit (x(ii,:), y(ii,:), 1);
    t1(ii) = d(1);
  end
end

% Why do an abs here? All the negative values seem to be junk.
%t1 = abs(t1);
t1(t1<0) = NaN;
T1 = (-log(t1)/20e-3).^-1;
% Clip to plausible values
T1(isnan(T1)|T1<0.2) = 0.2;
T1(T1>20) = 20;
% Get a PD map for each flip angle
PDmap = zeros(nVox,nT1);
for(ii=1:nT1)
  PDmap(:,ii) = s(t1Inds(ii)).imData(brainInds)./sin(theta(ii)).*((1-cos(theta(ii)).*t1)./(1-t1));
end
% Could do least squares for better PDmap?
PD = mean(PDmap,2);
% WARNING: following clip values are empirically determined with no
% theoretical basis!
PD(PD<0) = 0;
PD(PD>12000) = 12000;

% compute the S0 for the flip angle used in the MT scans
theta = s(mtInds(1)).flipAngle*pi/180;
S0 = PD.*sin(theta).*(1-exp(-32e-3./T1))./(1-cos(theta).*exp(-32e-3./T1));

im=zeros(size(brainMask)); im(brainInds) = T1; T1 = im;
im=zeros(size(brainMask)); im(brainInds) = PD; PD = im;
im=zeros(size(brainMask)); im(brainInds) = S0; S0 = im;

dtiWriteNiftiWrapper(T1, xform, fullfile(outDir,'T1'));
dtiWriteNiftiWrapper(PD, xform, fullfile(outDir,'PD'));
dtiWriteNiftiWrapper(S0, xform, fullfile(outDir,'S0'));

return;


% The COBRAToolbox: testDeletionStudy.m
%
% Purpose:
%     - tests the basic functionality of singleGeneDeletion/doubleGeneDeletion/singleRxnDeletion
%       Makes sure that these resultant values are correct:
%       singleGeneDeletion - hasEffect, delRxns, grRateKO, grRateWT
%       doubleGeneDeletion - grRatioDble, grRateKO, grRateWT
%       singleRXDeletion - hasEffect, delRxn, grRateKO, grRateWT
%       returns 1 if all are correct, else 0
%
% Author:
%     - Original file: Joseph Kang 11/16/09
%     - CI integration: Laurent Heirendt

global CBTDIR

% save the current path
currentDir = pwd;

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

tol = 1e-6;

%load model
model = getDistributedModel('ecoli_core_model.mat');

% list of solver packages
solverPkgs = {'tomlab_cplex', 'gurobi', 'glpk'};
%Load reference data.
load('rxnDeletionData.mat');

for k = 1:length(solverPkgs)

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

    solverLPOK = changeCobraSolver(solverPkgs{k}, 'LP', 0);

    if solverLPOK

        fprintf('\n*** Test basic single gene deletion: ***\n\n');

        %deleting gene for 'ENO')
        [grRatio, grRateKO, grRateWT, hasEffect, delRxns, fluxSolution] = singleGeneDeletion(model, 'FBA', {model.genes{1:4},'b2779'});

        % check if correct hasEffect value
        assert(isequal(hasEffect,hasEffectSD))

        % check if correctly deleted reactions
        assert(isequal(delRxns,delRxnsSD))

        % check if correct grRateKO value
        assert(all(abs(grRateKO-grRateSdKO) < tol))

        % check if correct grRateWT value
        assert(abs(grRateWT-grRateWTRef) < tol)

        %Now, we combine gene 1 and two. 1 has no effect, so 1 and 2 should
        %yield the same as 2.
        modelForUTest = model;
        modelForUTest.genes([1,5]) = strcat(model.genes(1),{'.1','.2'});
        targetValues = [1 2 3 4 ];
        %Check functionality of uniqueGene Flag
        [grRatio, grRateKO, grRateWT, hasEffect, delRxns] = singleGeneDeletion(modelForUTest,'FBA',modelForUTest.genes([1 2 3 4]),true,true);
                % check if correct hasEffect value
        assert(isequal(hasEffect,hasEffectSD(targetValues)))

        % check if correctly deleted reactions
        assert(isequal(delRxns,delRxnsSD(targetValues)))

        % check if correct grRateKO value
        assert(all(abs(grRateKO-grRateSdKO(targetValues)) < tol))

        % check if correct grRateWT value
        assert(abs(grRateWT-grRateWTRef) < tol)

        [grRatioDble, grRateKO, grRateWT] = doubleGeneDeletion(model, 'FBA', model.genes(1:4), {'b2779','b2287'});
        %Check against reference
        assert(all(all(abs(grRatioDble-grRatioDbRef) < tol)));

        % check if correct grRateDble value
        assert(all(all(abs(grRateKO-grRateDbKO) < tol)));

        % check if correct grRateWT value
        assert(abs(grRateWT - grRateWTRef) < tol);

        %% singleRxnDeletion Test
        fprintf('\n\nStarting singleRxnDeletion test:\n');

        [test_grRatio, test_grRateKO, test_grRateWT, test_hasEffect, test_delRxn]= singleRxnDeletion(model, 'FBA');

        grRatio_Rxn_Ref(isnan(grRatio_Rxn_Ref)) = -1;
        test_grRatio(isnan(test_grRatio)) = -1;

        % check if correct grRatio values
        for i = 1:length(grRatio_Rxn_Ref)
            assert(abs(grRatio_Rxn_Ref(i) - test_grRatio(i)) < tol)
        end

        grRateKO_Rxn_Ref(isnan(grRateKO_Rxn_Ref)) = -1;
        test_grRateKO(isnan(test_grRateKO)) = -1;

        % check if correct grRateKO values
        for i = 1:length(grRateKO_Rxn_Ref)
            assert(abs(grRateKO_Rxn_Ref(i) - test_grRateKO(i)) < tol)
        end

        % check if correct grRateWT values
        assert(abs(grRateWTRef - test_grRateWT) < tol)

        % check if correct delRxn values
        assert(isequal(delRxn_Rxn_Ref, test_delRxn))
    end

    % output a success message
    fprintf('Done.\n');
end

% change back to root folder
cd(currentDir)


report_this_filefun(mfilename('fullpath'));

[lat,lon] = meshgrat(tmap,tmapleg);

ren = interp2(X2,Y2,Z,lon,lat);

l = ren < 0.01;
ren(l) = 0.01;
mi = min(min(ren));

l = isnan(ren);
ren(l) = mi-2;

figure_w_normalized_uicontrolunits('pos',[150 500 1000 700])

hold on; axis off
axesm('MapProjection','eqaconic','MapParallels',[],...
    'MapLatLimit',[33.5 35 ],'MapLonLimit',[-117.3 -116])

meshm(ren,tmapleg,size(tmap),tmap);

daspectm('m',8);
tightmap
view([0 90])
% hl = lightangle(45,25);
hl = camlight
lighting phong
set(gca,'projection','perspective');

load worldlo
%h = displaym(POline); set(h(1),'color',[0.9 0.9 0.9],'Linewidth',1.7)
% h2 = displaym(PPpoint);
%   h = displaym(PPtext); trimcart(h);

plotm(faults(:,2), faults(:,1),'k','Linewidth',1.4);
% plotm(mainfault(:,2), mainfault(:,1),'m','Linewidth',3);

pl = plotm(a.Latitude,a.Longitude,'ok');
set(pl,'LineWidth',0.3,'MarkerSize',2,...
    'MarkerFaceColor','k','MarkerEdgeColor','k')
pl = plotm(main(:,2),main(:,1),'hw');
set(pl,'LineWidth',1,'MarkerSize',20,...
    'MarkerFaceColor','w','MarkerEdgeColor','k')

zdatam(handlem('allline'),10000) % keep line on surface
%zdatam(handlem('alltext'),10000) % keep line on surface
caxis([0.008 0.09])
j = jet;
%j = j(64:-1:1,:);
j = [ [ 0.85 0.9 0.9] ; j];

colormap(j); brighten(0.3);

axis off; set(gcf,'color','w')

setm(gca,'ffacecolor','w')
setm(gca,'fedgecolor','k','flinewidth',3);

setm(gca,'mlabellocation',0.5)
setm(gca,'meridianlabel','on')
setm(gca,'plabellocation',0.5)
setm(gca,'parallellabel','on')
setm(gca,'Fontcolor','k','Fontweight','bold','FontSize',14,'Labelunits','dm')

h5 = colorbar;
set(h5,'position',[0.7 0.15 0.01 0.3],'TickDir','out','Ycolor','k','Xcolor','k',...
    'Fontweight','bold','FontSize',14);
set(gcf,'Inverthardcopy','off');


function [Flux, FBAsolution, model] = testPathway(model, MetIn, MetOut, AdditionalMetsInorOut, ObjectiveOption)
% Allows the user to see if given one metabolite `A`,
% downstream metabolite `B` can be made made. Additional sinks can be added
% for co-factors if needed
% `A -->-->-->-->--> B`
%
% USAGE:
%
%    [Flux, FBAsolution, model] = testPathway(model, MetIn, MetOut, AdditionalMetsInorOut, ObjectiveOption)
%
% INPUTS:
%    model:                    COBRA model structure
%    MetIn:                    The input metabolite(s) (`A`)
%    MetOut:                   The output metabolite (`B`)
%
% OPTIONAL INPUTS:
%    AdditionalMetsInorOut:    Additional metabolites for which sinks will be added
%    ObjectiveOption:          Boolean:
%
%                                * 1 = objective will be production of `B` (default)
%                                * 0 = use objective in model
%
% OUTPUTS:
%    Flux:                     The rate of `B` production
%    FBAsolution:              Solution to the FBA problem
%    model:                    COBRA model with sinks in it
%
% .. Author: Nathan Lewis, Feb 16 2009

if ~iscell(MetIn)
    Met = MetIn; clear MetIn; MetIn{1} = Met;
end
if ~iscell(MetOut)
    Met = MetOut; clear MetOut; MetOut{1} = Met;
end
if nargin > 3
    if ~iscell(AdditionalMetsInorOut)
        Met = AdditionalMetsInorOut; clear AdditionalMetsInorOut; AdditionalMetsInorOut{1} = Met;
    end
    % add sink rxns for all AdditionalMetsInorOut
    for i = 1:length(AdditionalMetsInorOut)
        model = addReaction(model,cat(2,'Tempsink_',AdditionalMetsInorOut{i}),{AdditionalMetsInorOut{i} },-1 ,true);
    end
end
if nargin <5,ObjectiveOption=1;end

for i = 1:length(MetIn) % add inputs
    model = addReaction(model,cat(2,'TempInput_',MetIn{i}),{MetIn{i} },1 ,false);
end
[model, rxnExists] = addReaction(model,cat(2,'TempOutput_',MetOut{1}),{MetOut{1} },-1 ,false);
if (ObjectiveOption==1 && isempty(rxnExists))
	model = changeObjective(model,cat(2,'TempOutput_',MetOut{1}));
elseif (ObjectiveOption == 1 && ~isempty(rxnExists))
	model = changeObjective(model,model.rxns(rxnExists));
end
FBAsolution = optimizeCbModel(model,'max');
Flux = FBAsolution.f;
if ~isempty(FBAsolution.x)
%printFluxVector(model,FBAsolution.x);
else display('zero flux in network')
end


function [vacc, hacc, vcm, hcm, pg] = crfTestCV3(imsegs, pvSP, phSP, adjlist, pE, crfw, param, edgelen, priors)

ncv = numel(crfw);
nimages = numel(imsegs);

for f = 1:nimages
    disp(num2str(f))
    c = ceil(f/nimages*ncv);
    pg{f} = crfTestImage(pvSP{f}, phSP{f}, adjlist{f}, pE{f}, crfw{c}, param{c}, edgelen{f}, priors{c});
    [tmpvacc2, tmphacc2] = mcmcProcessResult(imsegs(f), pg(f));
    [tmpvacc1, tmphacc1] = mcmcProcessResult(imsegs(f), {[pvSP{f}(:, 1) repmat(pvSP{f}(:, 2), 1, 5).*phSP{f} pvSP{f}(:, 3)]});
    disp([num2str(tmpvacc1) '-->' num2str(tmpvacc2) '   ' num2str(tmphacc1) '-->' num2str(tmphacc2)])
    im = rgb2gray(im2double(imread(['../images/all_images/' imsegs(f).imname])));
    figure(1), displayLabels(imsegs(f), pvSP{f}, im);
    figure(2), displayLabels(imsegs(f), pg{f}, im);
    drawnow;
    pause(1)
end
[vacc, hacc, vcm, hcm] = mcmcProcessResult(imsegs, pg);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function displayLabels(imsegs, pg, im)
if size(pg, 2)==7
    v2 = pg(:, 1);
    v1 = sum(pg(:, 2:6), 2);
    v3 = pg(:, 7);
else
    v2 = pg(:, 1);
    v1 = pg(:, 2);
    v3 = pg(:, 3);
end
lim = cat(3, v1(imsegs.segimage), v2(imsegs.segimage), v3(imsegs.segimage));
imagesc(lim*0.5 + repmat(im, [1 1 3])*0.5), axis image

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function pg = crfTestImage(pvSP, phSP, adjlist, pE, crfw, param, edgelen, crfpriors)

% get f1(y1, y2) = log(P(y1|x)) + log(P(y2|x))
% and f2(y1, y2) = I(y1=y2)*log(P(y1=y2|x)) + I(y1~=y2)*log(P(y1~=y2|x))

npair = size(adjlist, 1);

f1 = zeros(npair, 7, 7);
f2 = zeros(npair, 7, 7);
f3 = zeros(npair, 7, 7);

pg = [pvSP(:, 1)  repmat(pvSP(:, 2), 1, 5).*phSP  pvSP(:, 3)];
s1 = adjlist(:, 1);
s2 = adjlist(:, 2);

nb = zeros(size(pg, 1), 1);
edgeperc = zeros(numel(s1), 2);
nb = zeros(size(pg, 1), 1);
for k = 1:numel(s1)
    nb(s1(k)) = nb(s1(k))+1;
    nb(s2(k)) = nb(s2(k))+1;
    edgeperc(k, 1) = edgelen(s1(k), s2(k)) / (sum(edgelen(s1(k), :))+sum(edgelen(:, s1(k))));
    edgeperc(k, 2) = edgelen(s1(k), s2(k)) / (sum(edgelen(s2(k), :))+sum(edgelen(:, s2(k))));
end

for k1 = 1:7
    for k2 = 1:7
        kp = param(k1 + (k2-1)*7, :);
        f1(:, k1, k2) = log(pg(s1, k1))./nb(s1) + log(pg(s2, k2))./nb(s2);
        if k1==k2
            f2(:, k1, k2) = ...
                log(kp(3)./(1+exp(-kp(1)-kp(2)*(log(pE)-log(1-pE))))).*...
                (edgeperc(:, 1) + edgeperc(:, 2));
            %f2(:, k1, k2) = log(1);
        else
            f3(:, k1, k2) = ...
                log(kp(3)./(1+exp(-kp(1)-kp(2)*(log(pE)-log(1-pE))))).*...
                (edgeperc(:, 1) + edgeperc(:, 2));
            %f2(:, k1, k2) = log(0.000001);
        end
    end
end

nsp = size(pvSP, 1);
adjmat = zeros(nsp, nsp);
potentials = cell(nsp, nsp);

evidences = 1/7*ones(7, nsp); % exp(crfw(1)*log(pg'));
%evidences = exp(log(pg'));

%f2 = f2./nb(:, 1).^crfw(end) + f2./nb(:, 2).^crfw(end);
%f3 = f3./nb(:, 1).^crfw(end) + f3./nb(:, 2).^crfw(end);

for k = 1:numel(s1)
    adjmat(s1(k), s2(k)) = 1;
    adjmat(s2(k), s1(k)) = 1;
    potentials{s1(k), s2(k)} = 0.5*squeeze(exp(crfw(1)*f1(k, :, :) + crfw(2)*f2(k, :, :) + crfw(3)*f3(k, :, :) + reshape(crfpriors, [1 7 7])));
    potentials{s2(k), s1(k)} = potentials{s1(k), s2(k)}';
end

% mrf2 = mk_mrf2(adjmat, potentials);
% engine = belprop_mrf2_inf_engine(mrf2);
% engine = enter_soft_evidence(engine, evidences);
%
% pg = zeros(nsp, 7);
% for s = 1:nsp
%     disp(marginal_nodes(engine, s))
%     pg(s, :) = marginal_nodes(engine, s)';
% end

[pg, niter] = bp_mrf2_old(adjmat, potentials, evidences, 'max_iter', 50);
pg = pg';


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

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defmethod @@sym numel (@var{x})
%% Return number of elements in symbolic array.
%%
%% Example:
%% @example
%% @group
%% syms x
%% A = [1 2 x; x 3 4];
%% numel(A)
%%   @result{} 6
%% @end group
%% @end example
%%
%% @seealso{@@sym/length, @@sym/size}
%% @end defmethod

function n = numel(x)

  %disp('numel call')
  d = size(x);
  n = prod(d);

end

%!test
%! a = sym([1 2 3]);
%! assert(numel(a) == 3);

%!test
%! % 2D array
%! a = sym([1 2 3; 4 5 6]);
%! assert(numel(a) == 6);

%!test
%! % empty
%! a = sym([]);
%! assert(numel(a) == 0);


function sclMask3M = perturbImageVolume(mask3M,scale)
% function sclMask3M = perturbImageVolume(mask3M,scale)
%
% Scales mask3M by amount scale.
%
% APA, 2/25/2019

sclMask3M = zeros(size(mask3M),'like',mask3M);
sizV = size(mask3M);
iCtr = round(sizV(1)/2);
jCtr = round(sizV(2)/2);
% scale = normrnd(0,2,1);
for slc = 1:size(mask3M,3)
%     sizV = size(mask3M(:,:,slc));
%     [iV,jV] = find3d(mask3M(:,:,slc));
%     maskM = mask3M(min(iV):max(iV),min(jV):max(jV),slc);
    maskM = mask3M(:,:,slc);
%     di = max(iV) - min(iV);
%     dj = max(jV) - min(jV);
%     iCtr = ceil((max(iV) + min(iV))/2);
%     jCtr = ceil((max(jV) + min(jV))/2);
%     minRow = -di*pctJitter/100;
%     maxRow = di*pctJitter/100;
%     minCol = -dj*pctJitter/100;
%     maxCol = dj*pctJitter/100;
%     numRows = minRow + (maxRow-minRow)*rand(1);
%     numCols = minCol + (maxCol-minCol)*rand(1);
%     minAng = -pctJitter/100*180;
%     maxAng = pctJitter/100*180;
%     angl = minAng + (maxAng-minAng)*rand(1);
%     scl = (100-pctJitter)/100 + 2*pctJitter/100*rand(1);
%     maskM = imtranslate(maskM,[numRows,numCols],'nearest','FillValues',0);
%     maskM = imrotate(maskM,angl,'bilinear');
    maskM = imresize(maskM, scale, 'nearest');
    newSiz = size(maskM);
    iStart = 1;
    jStart = 1;
    iEnd = 0;
    jEnd = 0;
    iMin = iCtr - ceil(newSiz(1)/2);
    if iMin < 0
        iStart = 1-iMin;
        iMin = 1;
    else
        iMin = iMin + 1;
    end
    iMax = iCtr + floor(newSiz(1)/2);
    if iMax > sizV(1)
        iEnd = iMax - sizV(1);
        iMax = sizV(1);
    end
    jMin = jCtr - ceil(newSiz(2)/2);
    if jMin < 0
        jStart = 1-jMin;
        jMin = 1;
    else
        jMin = jMin + 1;
    end
    jMax = jCtr + floor(newSiz(2)/2);
    if jMax > sizV(2)
        jEnd = jMax - sizV(2);
        jMax = sizV(2);
    end
    %mask3M(:,:,slc) = 0;
    sclMask3M(iMin:iMax,jMin:jMax,slc) = maskM(iStart:end-iEnd,jStart:end-jEnd);
end


function id = mapWindowIndices(map,mapWindow)
%
% id = mapWindowIndices(map,mapWindow)
%
% Returns indices of vector map within mapWindow
%
% if mapWindow(1)<mapWindow(2) returns mapWindow(1) <= map <= mapWindow(2)
% if mapWindow(1)>mapWindow(2) returns map >= mapWindow(1) or map <= mapWindow(2)
%
% djh, 7/98

if diff(mapWindow)>0
  id = find(map>=mapWindow(1) & map<=mapWindow(2));
else
  id = find(map>=mapWindow(1) | map<=mapWindow(2));
end