function x = subsasgn( x, S, y )

%   Disciplined convex/geometric programming information for SUBSASGN:
%      Subscripting can be used to change values of elements or slices
%      of CVX variables in the same manner as with numeric arrays. All
%      conventions are preserved, including the colon ':' and 'end'
%      notation, as well as the ability to "expand" a CVX variable by
%      assigning a value to a location outside of its current dimensions
%      (e.g., X(end+1)=0).
%
%      One notable exception is this: if the right-hand side is a CVX
%      expression, then the left-hand side must be as well. So, for
%      example, the following will fail:
%         variable x;
%         y = ones(3,1);
%         y(2) = x;
%      This is because MATLAB does not know how to automatically promote
%      'y' to a CVX variable so that it can accept 'x' as an element. If
%     you want
%      to accomplish something like this, you must manually convert y into a
%      CVX variable first, as follows:
%         variable x;
%         y = cvx(ones(3,1));
%         y(2) = x;

error( nargchk( 3, 3, nargin ) );

%
% Test subscripts
%

szx = size( x );
szy = size( y );
nlx = prod( szx );
try
    temp = reshape( 1 : nlx, szx );
    ndx_x = builtin( 'subsasgn', temp, S, zeros( szy ) );
catch
    error( lasterr );
end
szx_n = size( ndx_x );

%
% Assign data
%

x = cvx( x );
bx = x.basis_;
if any( szx_n < szx ),
    bx = bx( :, ndx_x );
else
    if any( szx_n > szx ),
        bx( :, end + 1 ) = 0;
        ndx_x( ndx_x == 0 ) = size( bx, 2 );
        bx = bx( :, ndx_x );
        temp = reshape( 1 : prod( szx_n ), szx_n );
    end
    ndx_x = builtin( 'subsref', temp, S );
    ndx_x = ndx_x( : );
    nlz = length( ndx_x );
    y = cvx( y );
    by = y.basis_;
    nx = size( bx, 1 );
    [ ny, my ] = size( by );
    if nx < ny,
        if issparse( by ) && ~issparse( bx ), bx = sparse( bx ); end
        bx( ny, : ) = 0;
    elseif nx > ny,
        if issparse( bx ) && ~issparse( by ), by = sparse( by ); end
        by( nx, : ) = 0;
    end
    if my < nlz,
        by = by( :, ones( 1, nlz ) );
    end
    bx( :, ndx_x ) = by;
end

%
% Create the new object
%

x = cvx( szx_n, bx );

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


% Test file for chebfun constructor (splitting).

function pass = test_constructor_splitting(pref)

% Grab some preferences:
if ( nargin == 0 )
    pref = chebfunpref();
end

seedRNG(6178);
tol = 1e9;

% Test SQRT(X) on [0 1]:
F1 = @sqrt;
f1 = chebfun(F1, [0, 1], pref, 'splitting', 'on', 'blowup', 'off');
xx1 = linspace(f1.domain(1)+eps, f1.domain(end)-eps, 100);
pass(1) = norm(feval(f1, xx1) - feval(F1, xx1), inf) < ...
    tol*max(eps*vscale(f1));

% Test SQRT(1-X) on [0 1]:
F2 = @(x) sqrt(1-x);
f2 = chebfun(F2, [0, 1], pref, 'splitting', 'on', 'blowup', 'off');
xx2 = linspace(f2.domain(1)+eps, f2.domain(end)-eps, 100);
pass(2) = norm(feval(f2, xx2) - feval(F2, xx2), inf) < ...
    tol*max(eps*vscale(f2));

% Test SQRT(1-X^2) on [-1 1]:
F3 = @(x) sqrt(1-x.^2);
f3 = chebfun(F3, [-1, 1], pref, 'splitting', 'on', 'blowup', 'off');
xx3 = linspace(f3.domain(1)+eps, f3.domain(end)-eps, 100);
pass(3) = norm(feval(f3, xx3) - feval(F3, xx3), inf) < ...
    tol*max(eps*vscale(f3));

% Test array-valued construction.  (Check for GitHub Issue #4.)
F4 = @(x) [sin(x) sign(x)];
f4 = chebfun(F4, [-1 1], pref, 'splitting', 'on', 'blowup', 'off');
xx4 = linspace(f4.domain(1)+eps, f4.domain(end)-eps, 100);
pass(4) = (norm(f4.domain - [-1 0 1], inf) < 10*eps) && ...
    (norm(feval(f4, xx4) - feval(F4, xx4), inf) < ...
    tol*max(eps*vscale(f4)));

% Check for issue with call to merge on a function with multiple breakpoints.
F5 = @(x) sign(x - 0.1).*abs(x + 0.2).*sin(3*x);
f5 = chebfun(F5, [-1 1], pref, 'splitting', 'on', 'blowup', 'off');
xx5 = linspace(f5.domain(1)+eps, f5.domain(end)-eps, 100);
pass(5) = (norm(f5.domain - [-1 -0.2 0.1 1], inf) < 10*eps) && ...
    (norm(feval(f5, xx5) - feval(F5, xx5), inf) < ...
    tol*max(eps*vscale(f5)));

%% Test a logical function:
f = chebfun(@(x) x > 0, [-1 1], 'splitting', 'on', pref);
x = chebfun('x', [-1 1], pref);
h = heaviside(x);
pass(6) = norm(f - h) < 10*eps;

% Test use of breakpoint detection in conjunction with construction from a cell
% array of function handles. (See issue #1151 on GitHub.)
f = chebfun({@(x) abs(x - 0.25), 0}, [0 0.5 1], 'splitting', 'on');
xx1 = linspace(0 + eps, 0.5 - eps, 20).';
err1 = norm(feval(f, xx1) - abs(xx1 - 0.25), inf);
xx2 = linspace(0.5 + eps, 1 - eps, 20).';
err2 = norm(feval(f, xx2), inf);
tol = 10*vscale(f)*eps;
pass(7) = max(err1, err2) < tol;

%% Test for function defined on unbounded domain:

% Function defined on [0 Inf]:

% Specify the domain:
dom = [0 Inf];
domCheck = [0 100];

% Generate a few random points to use as test values:
x = diff(domCheck) * rand(100, 1) + domCheck(1);

op = @(x) 0.75+sin(10*x)./exp(x);
f = chebfun(op, dom, 'splitting', 'on');
x = sort(x);
fVals = feval(f, x);
fExact = op(x);
err = fVals - fExact;
pass(8) = norm(err, inf) < 1e6*eps*vscale(f);

%% Test SPLITTING ON with BLOWUP == 1:
op = @(x)tan(x);
f = chebfun(op, [-4 4], 'splitting', 'on', 'blowup', 1);

% Specify the domain:
dom = [-4 -pi/2 pi/2 4];

% Generate random points to use as test values:
x1 = diff(dom(1:2)) * rand(100, 1) + dom(1);
x2 = diff(dom(2:3)) * rand(100, 1) + dom(2);
x3 = diff(dom(3:4)) * rand(100, 1) + dom(3);

err1 = op(x1)-f(x1);
err2 = op(x2)-f(x2);
err3 = op(x3)-f(x3);

err = [err1; err2; err3];
pass(9) = ( norm(err, inf) < 1e5*eps*vscale(f) );

%% Test for splitting on + unbndfun:

op = @(x)(sin(100*x)./exp(x.^2)+1).*(x.^2);
dom = [-inf inf];
dom_test = [-200 200];
x = diff(dom_test) * rand(100, 1) + dom_test(1);
f = chebfun (op, dom, 'exps', [2 2], 'splitting', 'on');
vals = f(x);
exact = op(x);
pass(10) = ( norm(vals-exact, inf) < 1e5*eps*vscale(f) );

% % Test X*LOG(X) on [0 1]:
% F4 = @(x) x.*log(x);
% f4 = chebfun(F4, [0, 1], pref, 'splitting', 'on', 'blowup', 'off');
% xx4 = linspace(f4.domain(1)+eps, f4.domain(end)-eps, 100);
% pass(4) = norm(feval(f4, xx4) - feval(F4, xx4), inf) < ...
%     tol*max(eps*vscale(f4));
%
% % Test (-X)*LOG(-X) on [-1 0]:
% F5 = @(x) (-x).*log(-x);
% f5 = chebfun(F5, [-1, 0], pref, 'splitting', 'on', 'blowup', 'off');
% xx5 = linspace(f5.domain(1)+eps, f5.domain(end)-eps, 100);
% pass(5) = norm(feval(f5, xx5) - feval(F5, xx5), inf) < ...
%     tol*max(eps*vscale(f5));
%
% % Test (1-X)*LOG(1-X) on [0 1]:
% F6 = @(x) (1-x).*log(1-x);
% f6 = chebfun(F6, [0, 1], pref, 'splitting', 'on', 'blowup', 'off');
% xx6 = linspace(f6.domain(1)+eps, f6.domain(end)-eps, 100);
% pass(6) = norm(feval(f6, xx6) - feval(F6, xx6), inf) < ...
%     tol*max(eps*vscale(f6));
% pass(6) = pass(6) && numel(f6.funs) < 50;
%
% % Test (1-X^2)*LOG(1-X^2) on [-1 1]:
% F7 = @(x) (1-x.^2).*log(1-x.^2);
% f7 = chebfun(F7, [-1, 1], pref, 'splitting', 'on', 'blowup', 'off');
% xx7 = linspace(f7.domain(1)+eps, f7.domain(end)-eps, 100);
% pass(7) = norm(feval(f7, xx7) - feval(F7, xx7), inf) < ...
%     tol*max(eps*vscale(f7));

end


% Plane Wave Absorption Example
%
% This example illustrates the characteristics of the Kelvin-Voigt
% absorption model used in the k-Wave simulation functions pstdElastic2D,
% pstdElastic3D. It builds on the Explosive Source In A Layered Medium
% Example.
%
% author: Bradley Treeby
% date: 17th January 2014
% last update: 14th February 2014
%
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009-2014 Bradley Treeby and Ben Cox

% 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/>.

clear all;

% =========================================================================
% SET GRID PARAMETERS
% =========================================================================

% create the computational grid
Nx = 128;           % number of grid points in the x (row) direction
Ny = 32;            % number of grid points in the y (column) direction
dx = 0.1e-3;        % grid point spacing in the x direction [m]
dy = 0.1e-3;        % grid point spacing in the y direction [m]
kgrid = makeGrid(Nx, dx, Ny, dy);

% define the properties of the propagation medium
medium.sound_speed_compression = 1800;  % [m/s]
medium.sound_speed_shear       = 1200;  % [m/s]
medium.density                 = 1000;  % [kg/m^3]

% set the absorption properties
medium.alpha_coeff_compression = 1;     % [dB/(MHz^2 cm)]
medium.alpha_coeff_shear       = 1;     % [dB/(MHz^2 cm)]

% define binary sensor mask with two sensor positions
sensor.mask = zeros(Nx, Ny);
pos1 = 45;                              % [grid points]
pos2 = 65;                              % [grid points]
sensor.mask(pos1, Ny/2) = 1;
sensor.mask(pos2, Ny/2) = 1;

% calculate the distance between the sensor positions
d_cm = (pos2 - pos1)*dx*100;            % [cm]

% set sensor to record to particle velocity
sensor.record = {'u'};

% define source mask
source_mask = ones(Nx, Ny);
source_pos = 35;                        % [grid points]

% set the CFL
cfl = 0.05;

% define the properties of the PML to allow plane wave propagation
pml_alpha = 0;
pml_size  = [30, 2];

% set the input arguments
input_args = {'PlotScale', 'auto', 'PMLSize', pml_size,...
    'PMLAlpha', pml_alpha, 'PlotPML', false};

% =========================================================================
% COMPRESSIONAL PLANE WAVE SIMULATION
% =========================================================================

% define source
source.u_mask = source_mask;
source.ux = zeros(Nx, Ny);
source.ux(source_pos, :) = 1;
source.ux = smooth(kgrid, source.ux, true);
source.ux = 1e-6.*reshape(source.ux, [], 1);

% set end time
t_end = 3.5e-6;

% create the time array
kgrid.t_array = makeTime(kgrid, max(medium.sound_speed_compression, medium.sound_speed_shear), cfl, t_end);

% run the simulation
sensor_data_comp = pstdElastic2D(kgrid, medium, source, sensor, input_args{:});

% calculate the amplitude spectrum at the two sensor positions
[~, as1] = spect(sensor_data_comp.ux(1, :), 1/kgrid.dt);
[f_comp, as2] = spect(sensor_data_comp.ux(2, :), 1/kgrid.dt);

% calculate the attenuation from the amplitude spectrums
attenuation_comp = -20*log10(as2./as1)./d_cm;

% calculate the corresponding theoretical attenuation in dB/cm
attenuation_th_comp = medium.alpha_coeff_compression .* (f_comp./1e6).^2;

% calculate the maximum supported frequency
f_max_comp = medium.sound_speed_compression / (2*dx);

% find the maximum frequency in the frequency vector
[~, f_max_comp_index] = findClosest(f_comp, f_max_comp);

% =========================================================================
% SHEAR PLANE WAVE SIMULATION
% =========================================================================

% define source
clear source
source.u_mask = source_mask;
source.uy = zeros(Nx, Ny);
source.uy(source_pos, :) = 1;
source.uy = smooth(kgrid, source.uy, true);
source.uy = 1e-6.*reshape(source.uy, [], 1);

% set end time
t_end = 4e-6;

% create the time array
kgrid.t_array = makeTime(kgrid, max(medium.sound_speed_compression, medium.sound_speed_shear), cfl, t_end);

% run the simulation
sensor_data_shear = pstdElastic2D(kgrid, medium, source, sensor, input_args{:});

% calculate the amplitude at the two sensor positions
[~, as1] = spect(sensor_data_shear.uy(1, :), 1/kgrid.dt);
[f_shear, as2] = spect(sensor_data_shear.uy(2, :), 1/kgrid.dt);

% calculate the attenuation from the amplitude spectrums
attenuation_shear = -20*log10(as2./as1)./d_cm;

% calculate the corresponding theoretical attenuation in dB/cm
attenuation_th_shear = medium.alpha_coeff_shear .* (f_shear./1e6).^2;

% calculate the maximum supported frequency
f_max_shear = medium.sound_speed_shear / (2*dx);

% find the maximum frequency in the frequency vector
[~, f_max_shear_index] = findClosest(f_shear, f_max_shear);

% =========================================================================
% VISUALISATION
% =========================================================================

% plot compressional wave traces
figure;
subplot(4, 1, 1)
t_axis = (0:length(sensor_data_comp.ux)-1)*kgrid.dt*1e6;
plot(t_axis, sensor_data_comp.ux.', 'k-');
axis tight;
xlabel('Time [\mus]');
ylabel('Particle Velocity');
title('Compressional Wave');

% plot compressional wave absorption
subplot(4, 1, 2)
plot(f_comp./1e6, attenuation_comp, 'ko', f_comp./1e6, attenuation_th_comp, 'k-');
set(gca, 'XLim', [0 f_max_comp/1e6], 'YLim', [0 attenuation_th_comp(f_max_comp_index)*1.1]);
box on;
xlabel('Frequency [MHz]');
ylabel('\alpha [dB/cm]');

% plot shear wave traces
subplot(4, 1, 3)
t_axis = (0:length(sensor_data_shear.uy)-1)*kgrid.dt*1e6;
plot(t_axis, sensor_data_shear.uy.', 'k-');
axis tight;
xlabel('Time [\mus]');
ylabel('Particle Velocity');
title('Shear Wave');

% plot shear wave absorption
subplot(4, 1, 4)
plot(f_shear./1e6, attenuation_shear, 'ko', f_shear./1e6, attenuation_th_shear, 'k-');
set(gca, 'XLim', [0 f_max_shear/1e6], 'YLim', [0 attenuation_th_shear(f_max_shear_index)*1.1]);
box on;
xlabel('Frequency [MHz]');
ylabel('\alpha [dB/cm]');

scaleFig(1, 1.5);


function vol = pr_blobs2vol(xyz,vals,mat)
% Take XYZ matrix and values and return SPM matrix vol struct
% FORMAT vol = pr_blobs2vol(xyz,vals,mat)
%
% Inputs
% xyz      - 3xN X Y Z coordinate matrix (in voxels)
% vals     - 1xN values, one per coordinate
% mat      - 4x4 voxel->world space transformation
%
% Outputs
% vol      - vol struct, with matrix data 'imgdata' field
%__________________________________________________________________________

% Matthew Brett
% $Id: pr_blobs2vol.m 6623 2015-12-03 18:38:08Z guillaume $

vol = [];
if ~isempty(xyz),
    rcp      = round(xyz);
    vol.dim  = max(rcp,[],2)';
    off      = rcp(1,:) + vol.dim(1)*(rcp(2,:)-1+vol.dim(2)*(rcp(3,:)-1));
    vol.imgdata = zeros(vol.dim)+NaN;
    vol.imgdata(off) = vals;
    vol.imgdata      = reshape(vol.imgdata,vol.dim);
    vol.mat = mat;
end


function h = times(f,g)
%.*   Pointwise multiplication for DISKFUN objects.
%   F.*G multiplies DISKFUN objects F and G. Alternatively F or G could be
%   a double.

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

if ( isa(f, 'diskfun') && isa(g, 'diskfun') )
    % Grady's faster times for rank 1 functions:
    if ( length( f ) == 1 )
        [C, D, R] = cdr(f);
        h = g;
        onesForC = sqrt(abs(D)) * ones(1, length(g));
        onesForR = sign(D) * onesForC;
        h.cols = (C * onesForC) .* g.cols;
        h.rows = (R * onesForR) .* g.rows;
        % Switch the parity terms if needed:
        % plus*plus = plus -> do nothing
        % plus*minus = minus -> do nothing
        % minus*minus = plus -> switch minus to plus
        % minus*plus = minus -> switch plus to minus
        if ( isempty(f.idxPlus) )  % f is a minus
            h.idxMinus = g.idxPlus;
            h.idxPlus = g.idxMinus;
        end
        % Both terms have to be non-zero at the poles for the product to be
        % non-zero at the poles.
        h.nonZeroPoles = f.nonZeroPoles & g.nonZeroPoles;
    elseif ( length( g ) == 1 )
         h = times(g, f);
    else
        % Let separableApprox deal with the multiplication
        h = times@separableApprox(f, g);
    end
else
    % Let separableApprox deal with the multiplication
    h = times@separableApprox(f, g);
end

end


function obj = Make_f11(obj,D_filename,file_suffixes,bathyfile)
% obj = Make_f11(obj,D_filename,file_suffixes)
% Input a msh class object get the values of the density over the depth
% based on D_filename, and computes the depth-averaged value which
% populates the f11 struct in the msh class object.
%
%  Author:      William Pringle
%  Created:     March 19 2018
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if isempty(obj.b)
    error('No bathymetry data in grid to calculate the depth-averaged value')
end
rho0 = 1000;
%g = 9.807;

% %% Do some projection for obj.p
% proj = 'Mercator';
% R = 6378206.4; %[m]
% m_proj(proj,'lon',[ min(obj.p(:,1)) max(obj.p(:,1)) ],...
%             'lat',[ min(obj.p(:,2)) max(obj.p(:,2))])
% [xx,yy] = m_ll2xy(obj.p(:,1),obj.p(:,2));
% xx = R*xx; yy= R*yy;
%
% %% Get the element areas and slopes, connectivity table
% A = polyarea(xx(obj.t(:,1:3))',yy(obj.t(:,1:3))')';
% % Get x differences
% a = [ xx(obj.t(:,3)) - xx(obj.t(:,2))
%       xx(obj.t(:,1)) - xx(obj.t(:,3))
%       xx(obj.t(:,2)) - xx(obj.t(:,1)) ] ;
% a = reshape(a,[],3);
%
% % Get y differences
% b = [ yy(obj.t(:,2)) - yy(obj.t(:,3))
%       yy(obj.t(:,3)) - yy(obj.t(:,1))
%       yy(obj.t(:,1)) - yy(obj.t(:,2)) ];
% b = reshape(b,[],3);
%
% % Get the vertex to element table
% vtoe = VertToEle(obj.t);
% vtoe(vtoe == 0) = length(obj.t) + 1;
% A(end+1) = 0;
% An = sum(A(vtoe))';

% nearest neighbour extrapolation of T and S (0 for no extrapolation)?
FillNaN = 0;

[direc , title , ext ] = fileparts( D_filename);

if isempty(title)
    D_filename = dir(direc);
    D_filename(1:2) = [];
    idx = zeros(length(D_filename),1);
    for jj = 1:size(file_suffixes,1)
        for ii = 1:length(D_filename)
            if idx(ii) == 0
                idx(ii) = contains(D_filename(ii).name,file_suffixes(jj,:));
            end
        end
    end
    D_filename = D_filename(find(idx));
else
   name = D_filename; D_filename = [];
   D_filename.folder = direc;
   D_filename.name = [title ext];
end

Bx = NaN(length(obj.b),size(D_filename,1));
By = NaN(length(obj.b),size(D_filename,1));
tic
for ii = 1:size(D_filename,1)
    Dn = [D_filename(ii).folder '/' D_filename(ii).name];
    [~ , ~ , ext ] = fileparts( Dn);
    %% Read the grid and density data
    if strcmp(ext,'.nc')
        try
            title = ncreadatt(Dn,'/','title'); % Reading some
            lon = ncread(Dn,'lon');
            lat = ncread(Dn,'lat');
            z   = ncread(Dn,'depth');
            sigma_t = ncread(Dn,'I_an');
            time_all = 0;
        catch
            title = ncreadatt(Dn,'/','History'); % Reading some
            [time_all(ii),lon,lat,z,~,~,dpx,dpy] = Make_Gridded_rho(Dn,...
         {'time','depth','lon','lat','salinity','water_temp','surf_el'}); %,...
                                                                %bathyfile);
            disp(['Read time ' datestr(time_all(ii))])
            %if ii == 1
            %    sigma_t = zeros([size(rho) size(D_filename,1)]);
            %end
            %sigma_t(:,:,:,ii) = rho - 1000; clear rho
        end
    elseif strcmp(ext,'.mat')
        load(Dn);
        %sigma_t = rho - 1000; clear rho
    else
        error('does not understand file extension')
    end
%     % zeta on the finite-element mesh
%     [Lon,Lat] = ndgrid(lon,lat);
%     F = griddedInterpolant(Lon,Lat,zeta,'linear','none');
%     zeta = F(obj.p);
%     % Get rho on the finite-element mesh
%     [~,~,~,rho] = Gridded_to_Mesh_SeaBed_DepthAveraged(...
%             obj.p(:,1),obj.p(:,2),obj.b,z,rho,lon,lat,FillNaN);
%
%     % Compute bx, by for each element (loop over to reduce memory issues)
%     bxe = zeros(length(obj.t),length(z));
%     bye = zeros(length(obj.t),length(z));
%     for k = 1:length(z)
%         if k == 1
%             BCPe = zeta.*rho{k};
%         else
%             BCPe = rho{k} - rho0;
%         end
%         BCPe = BCPe(obj.t);
%         bxe(:,k) = 0.5 * sum(BCPe.*b,2);
%         bye(:,k) = 0.5 * sum(BCPe.*a,2);
%     end
%     bxe(end+1,:) = 0; bye(end+1,:) = 0;
%     bx = zeros(length(obj.b),length(z));
%     by = zeros(length(obj.b),length(z));
%     for k = length(z):-1:1
%         if k > 1
%             bxe(:,k) = trapz(z(1:k),bxe(:,1:k),2);
%             bye(:,k) = trapz(z(1:k),bye(:,1:k),2);
%         end
%         temp = sum(reshape(bxe(vtoe,k),size(vtoe,1),[]),'omitnan')';
%         bx(:,k) = temp./An;
%         by(:,k) = temp./An;
%     end

    % Interpolate the gradient at each depth
    dpx(isnan(dpy)) = NaN; dpy(isnan(dpx)) = NaN;
    [lonN,latN] = ndgrid(lon,lat);
    bx = NaN(length(obj.p),length(z));
    by = NaN(length(obj.p),length(z));
    for kk = 1:length(z)
        if kk == 1
            Fx = griddedInterpolant(lonN,latN,dpx(:,:,kk),'linear','none');
            Fy = griddedInterpolant(lonN,latN,dpy(:,:,kk),'linear','none');
        else
            Fx.Values = dpx(:,:,kk);
            Fy.Values = dpy(:,:,kk);
        end
        bb = obj.b >= z(kk);
        pt = obj.p(bb,:);
        bxt = Fx(obj.p(bb,:));
        byt = Fy(obj.p(bb,:));
        if ~isempty(find(isnan(bxt), 1))
            idn = find(isnan(bxt));
            idg = find(~isnan(bxt));
            idx = knnsearch(pt(idg,:),pt(idn,:));
            bxt(idn) = bxt(idg(idx));
        end
        if ~isempty(find(isnan(byt), 1))
            idn1 = find(isnan(byt));
            idg = find(~isnan(byt));
            if sum(idn - idn1) ~= 0
                idx = knnsearch(pt(idg,:),pt(idn1,:));
            end
            byt(idn1) = byt(idg(idx));
        end
        bx(bb,kk) = bxt;
        by(bb,kk) = byt;
    end
    % Now do the integration over the depth taking into account actual
    % depth on the computational mesh
    for kk = length(z):-1:1
        bb = isnan(Bx(:,ii)) & obj.b > z(kk) & ...
            ~isnan(bx(:,kk)) & ~isnan(by(:,kk));
        Bx(bb,ii) = trapz(z(1:kk),bx(bb,1:kk),2) + ...
                          bx(bb,kk).*(obj.b(bb) - z(kk));
        By(bb,ii) = trapz(z(1:kk),by(bb,1:kk),2) + ...
                          by(bb,kk).*(obj.b(bb) - z(kk));
    end
    % Get the depth averaged
    Bx(:,ii) = Bx(:,ii)./obj.b/rho0;
    By(:,ii) = By(:,ii)./obj.b/rho0;

%     figure;
%     fastscatter(obj.p(:,1),obj.p(:,2),9.807*hypot(Bx,By))
%     colormap(cmocean('speed'))
%     caxis([0 1e-4])
%     colorbar;
end
toc
disp(time_all)
DTIMINC = round(seconds(median(diff(time_all))));

%
% tic
% Bx = zeros(length(obj.b),size(sigma_t,4));
% By = zeros(length(obj.b),size(sigma_t,4));
% for t = 1:size(sigma_t,4)
%     disp(['Computing ' datestr(time_all(t))])
%     %% Calculate the depth-averaged density
%     [~,Sigma_tm,~,Sigma_3D] = Gridded_to_Mesh_SeaBed_DepthAveraged(...
%             obj.p(:,1),obj.p(:,2),obj.b,z,sigma_t(:,:,:,t),lon,lat,FillNaN);
%
%     %% Calculate the integrated barcolinic pressure's
%     Sigma_3D = reshape(cell2mat(Sigma_3D),[],length(Sigma_3D));
%     % Make sure derivative with "ground" returns NaN;
%     BCP = NaN(length(obj.b),length(z));
%     for k = 1:length(z)
%         bb = obj.b >= z(k);
%         BCP(bb,k) = trapz(z(1:k),Sigma_3D(bb,1:k),2);
%     end
%     BCP = BCP/rho0;
%
%     %% Calculate the bx/by's for each element
%     % Compute bx, by for each element (loop over to reduce memory issues)
%     bxe = zeros(length(obj.t),length(z));
%     bye = zeros(length(obj.t),length(z));
%     for k = 1:length(z)
%         BCPe = BCP(:,k);
%         BCPe = BCPe(obj.t);
%         bxe(:,k) = 0.5 * sum(BCPe.*b,2);
%         bye(:,k) = 0.5 * sum(BCPe.*a,2);
%     end
%     %% Sum the contributions of each element connected to a node
%     % Add in a zero ghost element and refer to the zero indices of vtoe to this
%     bxe(end+1,:) = 0; bye(end+1,:) = 0;
%
%     % Sum up all element contributions to each node and take the integral
%     bx = zeros(length(obj.b),length(z));
%     by = zeros(length(obj.b),length(z));
%     for k = 1:length(z)
%         bb = obj.b >= z(k);
%         temp = sum(reshape(bxe(vtoe,k),size(vtoe,1),[]),'omitnan')';
%         bx(bb,k) = temp(bb)./An(bb);
%         temp = sum(reshape(bye(vtoe,k),size(vtoe,1),[]),'omitnan')';
%         by(bb,k) = temp(bb)./An(bb);
%     end
%     Bx(:,t) = trapz(z,bx,2)./obj.b;
%     By(:,t) = trapz(z,by,2)./obj.b;
%     Bx(obj.b == 0,t) = NaN; By(obj.b == 0,t) = NaN;
% %     % On the structured grid
%     %% Calculate the integrated barcolinic pressure's
%     Sigma_3D = sigma_t(:,:,:,t);
%     % Make sure derivative with "ground" returns NaN;
%     BCP = NaN(size(Sigma_3D));
%     for k = 1:length(z)
%         BCP(:,:,k) = trapz(z(1:k),Sigma_3D(:,:,1:k),3);
%     end
%     BCP = BCP/rho0;
%
%     bx = zeros(size(Sigma_3D));
%     by = zeros(size(Sigma_3D));
%     for k = 1:length(z)
%         [bx(:,:,k),by(:,:,k)] = gradient(BCP(:,:,k),(lon(2)-lon(1))*111e3,(lat(2)-lat(1))*111e3);
%     end
%     bxv = reshape(bx,[],length(z));
%     byv = reshape(by,[],length(z));
%     Bx_struc = NaN(size(bxv,1),1);
%     By_struc = NaN(size(bxv,1),1);
%     for k = 1:length(z)
%         bb = ~isnan(bxv(:,k));
%         Bx_struc(bb) = trapz(z(1:k),bxv(bb,1:k),2)./z(k);
%         bb = ~isnan(byv(:,k));
%         By_struc(bb) = trapz(z(1:k),byv(bb,1:k),2)./z(k);
%     end
%     Bx_struc(Bx_struc == 0) = NaN;
%     By_struc(By_struc == 0) = NaN;
%     Bx_struc = reshape(Bx_struc,size(Sigma_3D,1),[])';
%     By_struc = reshape(By_struc,size(Sigma_3D,1),[])';
%     figure;
%     pcolor(hypot(Bx_struc,By_struc))
%     shading interp
%     colormap(cmocean('ice'))
%     caxis([0 2e-6])
%     colorbar;
%end
%toc
% Calculate the depth-averaged
% rhoxe = sum(Sigma_tm(obj.t).*b,2)/rho0;
% rhoye = sum(Sigma_tm(obj.t).*a,2)/rho0;
% rhoxe(end+1,:) = 0; rhoye(end+1,:) = 0;
% rhox = sum(rhoxe(vtoe))'./An;
% rhoy = sum(rhoye(vtoe))'./An;
% Bx2D = 0.5*obj.b.^2.*rhox;
% By2D = 0.5*obj.b.^2.*rhoy;

%% Make into f11 struct
%summary = ncreadatt(D_filename,'/','summary'); % global attributes
obj.f11.DataTitle = title;
%[~,name,~] = fileparts(D_filename);
%obj.f11.DataSubTitle = [summary ': ' name];
obj.f11.DTIMINC = DTIMINC;
obj.f11.TimeVec = time_all;
obj.f11.NumOfNodes = length(obj.b);
obj.f11.Val = cell(size(Bx,2),1); %zeros(3,length(obj.b),size(sigma_t,4));
for t = 1:size(Bx,2)
    idx = find(~isnan(Bx(:,t)) & ~isnan(By(:,t)));
    obj.f11.Val{t} = [idx'; Bx(idx,t)'; By(idx,t)']; % Sigma_tm';
end
%EOF
end


%% Copyright (C) 2014, 2016-2017, 2019, 2022 Colin B. Macdonald
%% Copyright (C) 2020 Mike Miller
%% Copyright (C) 2020 Fernando Alvarruiz
%%
%% 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 -*-
%% @defun mat_rclist_asgn (@var{A}, @var{r}, @var{c}, @var{B})
%% Private helper routine for sym array assigment using lists.
%%
%% @code{(R(i),C(i))} specify entries of the matrix @var{A}.
%% We execute @code{A(R(i),C(i)) = B(i)}.
%%
%% Notes:
%% @itemize
%% @item  @var{B} is accessed with linear indexing.
%% @item  @var{B} might be a scalar, used many times.
%% @item  @var{A} might need to get bigger, if so it will be padded
%%        with zeros.
%% @end itemize
%%
%% @end defun

function z = mat_rclist_asgn(A, r, c, B)

  if (isempty (r) && isempty (c) && (isempty (B) || isscalar (B)))
    z = A;
    return
  end

  if ~( isvector(r) && isvector(c) && (length(r) == length(c)) )
    error('this routine is for a list of rows and cols');
  end

  if ((numel(B) == 1) && (numel(r) > 1))
    B = repmat(B, size(r));
  end
  if (length(r) ~= numel(B))
    error('not enough/too much in B')
  end

  % Easy trick to copy A into larger matrix AA:
  %    AA = sp.Matrix.zeros(n, m)
  %    AA[0, 0] = A
  % Also usefil: .copyin_matrix

  cmd = { '(A, r, c, B) = _ins'
          '# B linear access fix, transpose for sympy row-based'
          'if B is None or not B.is_Matrix:'
          '    B = sp.Matrix([[B]])'
          'BT = B.T'
          '# make a resized copy of A, and copy existing stuff in'
          'if isinstance(A, list):'
          '    assert len(A) == 0, "unexpectedly non-empty list: report bug!"'
          '    n = max(max(r) + 1, 1)'
          '    m = max(max(c) + 1, 1)'
          '    AA = [[0]*m for i in range(n)]'
          'elif A is None or not isinstance(A, MatrixBase):'
          '    # we have non-matrix, put in top-left'
          '    n = max(max(r) + 1, 1)'
          '    m = max(max(c) + 1, 1)'
          '    AA = [[0]*m for i in range(n)]'
          '    AA[0][0] = A'
          'else:'
          '    # build bigger matrix'
          '    n = max(max(r) + 1, A.rows)'
          '    m = max(max(c) + 1, A.cols)'
          '    AA = [[0]*m for i in range(n)]'
          '    # copy current matrix in'
          '    for i in range(A.rows):'
          '        for j in range(A.cols):'
          '            AA[i][j] = A[i, j]'
          '# now insert the new bits from B'
          'for i, (r, c) in enumerate(zip(r, c)):'
          '    AA[r][c] = BT[i]'
          'return sp.Matrix(AA),' };

  rr = num2cell(int32(r-1));
  cc = num2cell(int32(c-1));
  z = pycall_sympy__ (cmd, A, rr, cc, B);

  % a simpler earlier version, but only for scalar r,c
  %cmd = { '(A, r, c, b) = _ins'
  %        'if not A.is_Matrix:'
  %        '    A = sp.Matrix([[A]])'
  %        'AA = sp.Matrix.zeros(max(r+1, A.rows), max(c+1, A.cols))'
  %        'AA[0, 0] = A'
  %        'AA[r, c] = b'
  %        'return AA,' };
end


function [oz] = mi32oz(mi3)
% Convert volume from cubic miles to US liquid ounces.
% Chad Greene 2012
oz = mi3*140942994870000;


function nmt_peaksearch_helper
% simplifies Callback for peak search functionality in GUI
global st

cfg=[];
cfg.searchradius = [str2num(get(st.nmt.gui.searchradius1,'String')) str2num(get(st.nmt.gui.searchradius2,'String'))];

cfg.peaktype=get(st.nmt.gui.peaktype,'string');
cfg.peaktype=cfg.peaktype{get(st.nmt.gui.peaktype,'Value')};

peakdomain=get(st.nmt.gui.peakdomain,'string');
peakdomain=peakdomain{get(st.nmt.gui.peakdomain,'Value')};

switch(peakdomain)
    case 'spatial'
        cfg.time = st.nmt.cfg.time_idx;
    case 'temporal'
        cfg.vox = st.nmt.cfg.vox_idx;
    case 'spatiotemporal'
        % nothing to do, this is default behavior
    otherwise
        error('well this is unexpected...')
end

[v,t]=nmt_peaksearch(cfg);

nmt_repos(v,t);


function model = multimodelCreate(inputDim, outputDim, varargin)

% MULTIMODELCREATE Create a MULTIMODEL model.
% The MULTIMODEL is a way of performing multi-task learning by sharing
% model parameters across a range of models. The default (simple)
% assumption is that the data is conditionally independent given the
% parameters, i.e. the log likelihood is the sum of the log likelihood of
% the models.
%
% SEEALSO : modelCreate
%
% FORMAT
% DESC creates a multi-task learning wrapper
% model structure given an options structure.
% ARG inputDim : the input dimension of the model.
% ARG outputDim : the output dimension of the model.
% ARG options : an options structure that determines the form of the model.
% RETURN model : the model structure with the default parameters placed in.
%
% SEEALSO : multimodelOptions, multimodelParamInit, modelCreate
%
% COPYRIGHT : Neil D. Lawrence, 2007
%
% MODIFICATIONS : Mauricio A. Alvarez, 2009

% MLTOOLS

options = varargin{end};
model.numModels = options.numModels;
model.type = 'multimodel';
model.compType = options.type;
model.inputDim = inputDim;
model.outputDim = outputDim;

if numel(outputDim) == 1
    % Indices of parameters to be trained separately for each model.
    model.separateIndices = options.separate;
    model.numSep = length(model.separateIndices);
    for i = 1:model.numModels
        varargput = cell(1, length(varargin)-1);
        for j = 1:length(varargput)
            varargput{j} = varargin{j}{i};
        end
        % MAURICIO : temporarily changed to allow different options for each model
        if ~iscell(options.compOptions)
            model.comp{i} = modelCreate(model.compType, inputDim, outputDim, ...
                varargput{:}, options.compOptions);
        else
            model.comp{i} = modelCreate(model.compType, inputDim, outputDim, ...
                varargput{:}, options.compOptions{i});
        end
    end
    if isfield(model.comp{i}, 'numParams');
        model.numParams = model.comp{1}.numParams;
    else
        model.numParams = length(modelExtractParam(model.comp{1}));
    end
    model.sharedIndices = 1:model.numParams;
    model.sharedIndices(model.separateIndices) = [];
    model.numParams = model.numParams + (model.numModels-1)*model.numSep;
else
    model.separateIndices = options.separate;
    model.numSep = length(model.separateIndices);
    for i = 1:model.numModels
        varargput = cell(1, length(varargin)-1);
        for j = 1:length(varargput)
            varargput{j} = varargin{j}{i};
        end
        fprintf('Creating model number: %d\n', i)
        model.comp{i} = modelCreate(model.compType, inputDim, outputDim(i), ...
            varargput{:}, options.compOptions{i});

    end
    if isfield(model.comp{1}, 'nParams');
        model.numParams = 0;
        for i =1:model.numModels,
            model.numParams = model.numParams + model.comp{i}.nParams;
        end
    else
        model.numParams = length(modelExtractParam(model.comp{1}));
    end
    model.numParams = model.numParams + (model.numModels-1)*model.numSep;
end

if isfield(options, 'optimiser') && ~isempty(options.optimiser)
    model.optimiser = options.optimiser;
end


function writeTensors(filename, tensors)

% use this function to write .tensor files (features or weights) into Matlab

fin = fopen(filename, 'wb');

for i=1:length(tensors)

    switch tensors(i).type
        case 'half'
            type_id = 0;
            precision = 'uint16';
        case 'float'
            type_id = 1;
            precision = 'single';
        case 'double'
            type_id = 2;
            precision = 'double';
        case 'uint8'
            type_id = 3;
            precision = 'uint8';
        case 'uint16'
            type_id = 4;
            precision = 'uint16';
        case 'uint32'
            type_id = 5;
            precision = 'uint32';
        case 'uint64'
            type_id = 6;
            precision = 'uint64';
        case 'int8'
            type_id = 7;
            precision = 'int8';
        case 'int16'
            type_id = 8;
            precision = 'int16';
        case 'int32'
            type_id = 9;
            precision = 'int32';
        case 'int64'
            type_id = 10;
            precision = 'int64';
        case 'char'
            type_id = 11;
            precision = 'char';
        case 'bool'
            type_id = 12;
            precision = 'uint8';
        otherwise
            throw(MException('writeTensor:UnsupportedFormat','Unsupported Format'))
    end

    if strcmp(tensors(i).type,'half')
        values = float2half(tensors(i).value);
        tensors(i).value = values;
    end

    fwrite(fin, uint8(type_id), 'uint8');
    fwrite(fin, uint32(tensors(i).sizeof), 'uint32');

    str = tensors(i).name;
    fwrite(fin, int32(length(str)), 'int32');
    fwrite(fin, str, 'char*1');

    dim = size(tensors(i).value);

    % matlab is column first, marvin/c++ is row first
    if length(dim)>1
        pvec = 1:length(dim);
        pvec([1 2]) = pvec([2 1]);
        tensors(i).value = permute(tensors(i).value, pvec);
        dim = dim(pvec);
    end

    dim = dim(end:-1:1);
    while tensors(i).dim > numel(dim)
        dim(end+1) = 1;
    end

    fwrite(fin, int32(length(dim)), 'int32');
    for d=1:length(dim)
        fwrite(fin, int32(dim(d)), 'int32');
    end
    fwrite(fin, tensors(i).value, precision);
end

fclose(fin);


function id_searchwindows( ref_VAD, ref_Nsamples, deg_VAD, deg_Nsamples);

global MINUTTLENGTH Downsample MINUTTLENGTH SEARCHBUFFER
global Crude_DelayEst Nutterances UttSearch_Start UttSearch_End

Utt_num = 1;
speech_flag = 0;

VAD_length= floor( ref_Nsamples/ Downsample);
del_deg_start= MINUTTLENGTH- Crude_DelayEst/ Downsample;
del_deg_end= floor((deg_Nsamples- Crude_DelayEst)/ Downsample)-...
    MINUTTLENGTH;

for count= 1: VAD_length
    VAD_value= ref_VAD(count);
    if( (VAD_value> 0) && (speech_flag== 0) )
        speech_flag= 1;
        this_start= count;
        UttSearch_Start(Utt_num)= count- SEARCHBUFFER;
        if( UttSearch_Start(Utt_num)< 0 )
            UttSearch_Start(Utt_num)= 0;
        end
    end

    if( ((VAD_value== 0) || (count == (VAD_length-1))) && ...
            (speech_flag == 1) )
        speech_flag = 0;
        UttSearch_End(Utt_num) = count + SEARCHBUFFER;
        if( UttSearch_End(Utt_num) > VAD_length - 1 )
            UttSearch_End(Utt_num) = VAD_length -1;
        end

        if( ((count - this_start) >= MINUTTLENGTH) &&...
                (this_start < del_deg_end) &&...
                (count > del_deg_start) )
            Utt_num= Utt_num + 1;
        end
    end
end
Utt_num= Utt_num- 1;
Nutterances = Utt_num;

% fprintf( 1, 'Nutterances is %d\n', Nutterances);

% fid= fopen( 'mat_utt.txt', 'wt');
% fprintf( fid, '%d\n', UttSearch_Start( 1: Nutterances));
% fprintf( fid, '\n');
% fprintf( fid, '%d\n', UttSearch_End( 1: Nutterances));
% fclose(fid);


function volcrop = crop_volume(vol, crp)
if ndims(vol) == 3
    volcrop = vol(crp(1,1):crp(1,2), crp(2,1):crp(2,2), crp(3,1):crp(3,2));
elseif ndims(vol) == 2
    volcrop = vol(crp(1,1):crp(1,2), crp(2,1):crp(2,2));
end
end


function info = get_performance_bqp(Xopt,yopt,Sopt,SDP,POP,path)

if iscell(path)
    for i = 1:length(path)
        addpath(genpath(path{i}))
    end
else
    addpath(genpath(path))
end

blk         = SDP.blk;
At          = SDP.At;
b           = SDP.b;
C           = svec(blk,SDP.C);
Xoptmat     = Xopt;
Xopt        = svec(blk,Xopt);
Sopt        = svec(blk,Sopt);
Amap  = @(X) AXfun(blk,At,X);
ATmap = @(y) Atyfun(blk,At,y);

%% standard SDP KKT residuals
Rp          = Fnorm(b - Amap(Xopt))/(1+Fnorm(b));
Rd          = Fnorm(ops(ops(C,'-',ATmap(yopt)),'-',Sopt))/(1+Fnorm(C));
pobj        = blktrace(blk,C,Xopt);
dobj        = b'*yopt;
gap         = abs(pobj - dobj)/(1+abs(pobj) + abs(dobj));

%% round a rank-one solution
Xmom        = Xoptmat{1};
[V,~]       = sorteig(Xmom);
v           = V(:,1)/V(1,1);
x_est       = v(2:1+POP.d);
f_est       = POP.f.coefficient * ( prod(x_est.^(POP.f.degmat),1) )';

S_mineig    = mineig( smat(blk, ops(C,'-',ATmap(yopt)) ) );
S_mineig_1  = min(S_mineig,0);
M           = SDP.M;
f_lb        = SDP.b'*yopt + M'*S_mineig_1;
eta         = abs(f_est - f_lb)/(1+abs(f_est)+abs(f_lb));

info.Rp     = Rp;
info.Rd     = Rd;
info.Rg     = gap;
info.Rs     = eta;
info.pobj   = pobj;
info.dobj   = dobj;
info.f_est      = f_est;
info.S_mineig   = S_mineig;
info.f_lb       = f_lb;
info.x_est      = x_est;

fprintf('\n========== Performance of Binary Quadratic Program ==========\n')
fprintf('Rp: %3.2e, Rd: %3.2e, Rg: %3.2e, Rs: %3.2e.\n',Rp,Rd,gap,eta);
fprintf('f_est: %3.4e, f_lb: %3.4e, pobj: %3.4e, dobj: %3.4e.\n',f_est,f_lb,pobj,dobj);
fprintf('==============================================================\n')

if iscell(path)
    for i = 1:length(path)
        rmpath(genpath(path{i}))
    end
else
    rmpath(genpath(path))
end
end


function r = XYRectangle(x1,x2,y1,y2,z)

% XYRECTANGLE  Rectangle in the XY plane.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

s1 = xSegment(x1,x2,y1,z);
s2 = ySegment(x2,y1,y2,z);
s3 = xSegment(x2,x1,y2,z);
s4 = ySegment(x1,y2,y1,z);

r = [s1 s2 s3 s4];

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

%   # START GPL LICENSE

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

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

%   # END GPL LICENSE


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

function [BB2 Conf Valid tld] = tldTracking(tld,BB1,I,J)
% Estimates motion of bounding box BB1 from frame I to frame J

% initialize output variables
BB2    = []; % estimated bounding
Conf   = []; % confidence of prediction
Valid  = 0;  % is the predicted bounding box valid? if yes, learning will take place ...

if isempty(BB1) || ~bb_isdef(BB1), return; end % exit function if BB1 is not defined

% estimate BB2
xFI    = bb_points(BB1,10,10,5); % generate 10x10 grid of points within BB1 with margin 5 px
xFJ    = lk(2,tld.img{I}.input,tld.img{J}.input,xFI,xFI); % track all points by Lucas-Kanade tracker from frame I to frame J, estimate Forward-Backward error, and NCC for each point
medFB  = median2(xFJ(3,:)); % get median of Forward-Backward error
medNCC = median2(xFJ(4,:)); % get median for NCC
idxF   = xFJ(3,:) <= medFB & xFJ(4,:)>= medNCC; % get indexes of reliable points
BB2    = bb_predict(BB1,xFI(:,idxF),xFJ(1:2,idxF)); % estimate BB2 using the reliable points only

tld.xFJ = xFJ(:,idxF); % save selected points (only for display purposes)

% detect failures
if ~bb_isdef(BB2) || bb_isout(BB2,tld.imgsize), BB2 = []; return; end % bounding box out of image
if tld.control.maxbbox > 0 && medFB > 10, BB2 = []; return; end  % too unstable predictions

% estimate confidence and validity
patchJ   = tldGetPattern(tld.img{J},BB2,tld.model.patchsize); % sample patch in current image
[~,Conf] = tldNN(patchJ,tld); % estimate its Conservative Similarity (considering 50% of positive patches only)

% Validity
Valid    = tld.valid(I); % copy validity from previous frame
if Conf > tld.model.thr_nn_valid, Valid = 1; end % tracker is inside the 'core'


% -------------------------------------------------------------------------------------------------------------------------
function [newTargetPosition, bestScale] = tracker_eval(net_x, s_x, scoreId, z_features, x_crops, targetPosition, window, p)
%TRACKER_STEP
%   runs a forward pass of the search-region branch of the pre-trained Fully-Convolutional Siamese,
%   reusing the features of the exemplar z computed at the first frame.
%
%   Luca Bertinetto, Jack Valmadre, Joao F. Henriques, 2016
% -------------------------------------------------------------------------------------------------------------------------
    % forward pass, using the pyramid of scaled crops as a "batch"
    net_x.eval({p.id_feat_z, z_features, 'instance', x_crops});
    responseMaps = reshape(net_x.vars(scoreId).value, [p.scoreSize p.scoreSize p.numScale]);
    responseMaps = gather(responseMaps);
    responseMapsUP = single(zeros(p.scoreSize*p.responseUp, p.scoreSize*p.responseUp, p.numScale));
    % Choose the scale whose response map has the highest peak
    if p.numScale>1
        currentScaleID = ceil(p.numScale/2);
        bestScale = currentScaleID;
        bestPeak = -Inf;
        for s=1:p.numScale
            if p.responseUp > 1
                % upsample to improve accuracy
                responseMapsUP(:,:,s) = imresize(responseMaps(:,:,s), p.responseUp, 'bicubic');
            else
                responseMapsUP(:,:,s) = responseMaps(:,:,s);
            end
            thisResponse = responseMapsUP(:,:,s);
            % penalize change of scale
            if s~=currentScaleID, thisResponse = thisResponse * p.scalePenalty; end
            thisPeak = max(thisResponse(:));
            if thisPeak > bestPeak, bestPeak = thisPeak; bestScale = s; end
        end
        responseMap = responseMapsUP(:,:,bestScale);
    else
        responseMap = responseMapsUP;
        bestScale = 1;
    end
    % make the response map sum to 1
    responseMap = responseMap - min(responseMap(:));
    responseMap = responseMap / sum(responseMap(:));
    % apply windowing
    responseMap = (1-p.wInfluence)*responseMap + p.wInfluence*window;
    [r_max, c_max] = find(responseMap == max(responseMap(:)), 1);
    [r_max, c_max] = avoid_empty_position(r_max, c_max, p);
    p_corr = [r_max, c_max];
    % Convert to crop-relative coordinates to frame coordinates
    % displacement from the center in instance final representation ...
    disp_instanceFinal = p_corr - ceil(p.scoreSize*p.responseUp/2);
    % ... in instance input ...
    disp_instanceInput = disp_instanceFinal * p.totalStride / p.responseUp;
    % ... in instance original crop (in frame coordinates)
    disp_instanceFrame = disp_instanceInput * s_x / p.instanceSize;
    % position within frame in frame coordinates
    newTargetPosition = targetPosition + disp_instanceFrame;
end

function [r_max, c_max] = avoid_empty_position(r_max, c_max, params)
    if isempty(r_max)
        r_max = ceil(params.scoreSize/2);
    end
    if isempty(c_max)
        c_max = ceil(params.scoreSize/2);
    end
end


% ts_plot for PS_PLOT function
%
%
%
%   Andy Hooper, June 2006
%
%   ======================================================================
%   11/2010 MMC & MA: plotting time series using 'ts' option
%   03/2011 AH convert radius to m, remove line fitting and add mean
%   08/2016 AH Replace break with return
%   ======================================================================

% Place button for new TS plots
% see ps_plot

mEditBox=findobj('Background',[1 1 1]); % get the handle of editable textbox
%radiusfactor=str2num(get(mEditBox,'String')) % get radius factor from editbox
radiusfactor = str2num(char(get(mEditBox,'String')));					% added by david this is also not a single value but a vector
radiusfactor = radiusfactor(1);								% select only the first value, i checked it for a couple of values and radius is correct

%if radiusfactor > 3600
%    disp('radius factor should be <= 3600')
%    return
%end

momfig_name=['(', get(gcf,'name'), ')']; % inherent fig_name from the velocity plot

% LOAD TS mat file ~ ps_plot_ts_v-d.mat
if ~exist('ph_mm','var')
  %fid = fopen(savetxt);
  fid = fopen('ps_plot_ts_matname.txt');
  tsmat=textscan(fid,'%s'); % get mat filename to load parameters
  fclose(fid);
  clear fid
  eval(['load ' tsmat{1}{1}])% load saved matrix
end
% end of load

%
% GET USER INPUT from MOUSE CLICK
%
 disp('Please select a point on the figure to plot time series (TS)')
 [lon0,lat0] = ginput(1); % turn on when final
 disp(['Selected point coordinates (lon,lat):' num2str(lon0),', ', num2str(lat0) ])

% MAKE A CIRCLE AROUND SELECTED POINT (lon0,lat0)
t = linspace(0,2*pi,114); % 114 pts
h=lon0; k=lat0;  % center cn for the circle
r=radiusfactor;
                   % change radius if you want to include more points
x = r*cos(t);
y = r*sin(t);

% SELECT POINTS based on LONLAT
xy=llh2local(lonlat',[lon0,lat0])'*1000;
in = inpolygon(xy(:,1),xy(:,2),x,y);
n_pts_near=sum(in);  % how many ps found

if sum(in) == 0
    disp(['No points found in radius of ', num2str(r) ] )
    disp('Please make new selection increasing radius factor...')
    return     % no pts selecte
end

% PLOT selection and points
figure
    set(gcf,'name',['Found #pt(s): ', num2str(n_pts_near),...
        '  in radius: ', num2str(r), ' m. ', momfig_name ])
    circlell=local2llh([x;y]/1000,[lon0,lat0]);
    plot(circlell(1,:),circlell(2,:));
    hold on
    plot(lon0,lat0,'*')

    lon2=lonlat(in,1);
    lat2=lonlat(in,2);
    plot(lon2,lat2,'dr')
    axis image; hold off

% if ps>1 than average
% [dist,az] = distance(lat0,lon0,lat2,lon2); % or use llh2local

% plot closest point or avg of multiple points.

% phases
% ph_mm holds corrected phase
% ph_all holds radians to meters
% v_all=-m(2,:)'; % ?

% PLOT TS for given point(s)
ts=ph_mm(in,:);
G=[ones(size(day)),day-master_day] ; % [ 1  a ] --> b + ax

offset=pi*1000*lambda/(4*pi);

ts=nanmean(ts,1);
x_hat=G\double(ts');
ts_hat=G*x_hat;
%tsup_hat=ts_hat+offset;
%tslo_hat=ts_hat-offset;

%%% Typical TS plot - no auxilary subplots
% figure
%     set(gcf,'name',[ ' Times series plot for #point(s): ',...
%         num2str(n_pts_near), ' ', momfig_name])
%     plot(day,ts,'--*'); hold on
%     plot(day,ts_hat,'-*r');
%     plot(day,tsup_hat,'-.g');
%     plot(day,tslo_hat,'-.g');
%     hold off
%     grid on
%     ylabel('mm');
%     xlabel('Time [mmmyy]')
%     %datetick('x','mmmyy')  % keepticksdoc
%     %set(gca, 'XTick',day);
%     set(gca, 'XTickLabel', datestr(day,'mmmyy'));

%%% Enhanced TS plot
 figure % main figure
   orient landscape
   % Bperp
%    subplot(10,1,1)     % Bperp
%      bperp(find(bperp==0))=[]; % drop master.
%      bar(bperp)
%      ylabel('Bperp [m]')
%    grid on
   % TS
%    subplot(10,10,[11 87]) % subplot(10,1,2:9)
       set(gcf,'name',[ ' Times series plot for #point(s): ',...
        num2str(n_pts_near), ' ', momfig_name])
    %h1=plot(day,ts,'--*'); hold on
    %plot(day,ts_hat,'-k','LineSmoothing','on'); % mess up ticks
    plot(day,ts_hat,'-r'); % mess up ticks
    hold on
    h2=plot(day,ts,'ob');
    set(h2,'linewidth',2)
    %h3=plot(day,tsup_hat,'-.g');
    %h4=plot(day,tslo_hat,'-.g');
    set(gca,'fontsize',20)
    hold off
    grid on
    ylabel('LOS (mm)');
    %datetick('x','mmmyy')  % keepticks or see below

    ts_years=unique(datenum(datestr(day,'yyyy'),'yyyy'));
    ts_dates=[ts_years(1):365.25:ceil(ts_years(end)+365.25)];
    %ts_dates=[day(1):365:day(end)+365];
    set(gca, 'XTick',ts_dates);
    set(gca, 'XTickLabel', datestr(ts_dates,'yyyy'));
    % annotate velocit slope in ts plot

   % IFG Dates - excluding master
%    subplot(10,10,[18 90]) % subplot for rectangle
%       putdates(0.05,1,datestr(day,'yyyy-mm-dd'),0.035,9) % putdates(xstart, ystart, labels, labeloffset, fontsize)
   %subplot(10,1,10)
   %bar(Bdop)

%EOF


function [E,dE,f,g] = spm_DEM_eval(M,qu,qp)
% evaluates state equations and derivatives for DEM schemes
% FORMAT [E dE f g] = spm_DEM_eval(M,qu,qp)
%
% M  - model structure
% qu - conditional mode of states
%  qu.v{i} - casual states
%  qu.x(i) - hidden states
%  qu.y(i) - response
%  qu.u(i) - input
% qp - conditional density of parameters
%  qp.p{i} - parameter deviates for i-th level
%  qp.u(i) - basis set
%  qp.x(i) - expansion point ( = prior expectation)
%
% E  - generalised errors  (i.e.., y - g(x,v,P); x[1] - f(x,v,P))
%
% dE:
%  dE.du   - de[1:n]/du
%  dE.dy   - de[1:n]/dy[1:n]
%  dE.dc   - de[1:n]/dc[1:d]
%  dE.dp   - de[1:n]/dp
%  dE.dup  - d/dp[de[1:n]/du
%  dE.dpu  - d/du[de[1:n]/dp
%
% where u = x{1:d]; v[1:d]
%
% To accelerate computations one can specify the nature of the model using
% the field:
%
% M(1).E.linear = 0: full        - evaluates 1st and 2nd derivatives
% M(1).E.linear = 1: linear      - equations are linear in x and v
% M(1).E.linear = 2: bilinear    - equations are linear in x, v & x*v
% M(1).E.linear = 3: nonlinear   - equations are linear in x, v, x*v, & x*x
% M(1).E.linear = 4: full linear - evaluates 1st derivatives (for generalised
%                                  filtering, where parameters change)
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_DEM_eval.m 6270 2014-11-29 12:04:48Z karl $

% get dimensions
%==========================================================================
nl    = size(M,2);                       % number of levels
ne    = sum(spm_vec(M.l));               % number of e (errors)
nv    = sum(spm_vec(M.m));               % number of x (causal states)
nx    = sum(spm_vec(M.n));               % number of x (hidden states)
np    = sum(spm_vec(M.p));               % number of p (parameters)

% evaluate functions at each hierarchical level
%==========================================================================

% Get states {qu.v{1},qu.x{1}} in hierarchical form (v{i},x{i})
%--------------------------------------------------------------------------
v     = spm_unvec(qu.v{1},{M(1 + 1:end).v});
x     = spm_unvec(qu.x{1},{M(1:end - 1).x});
for i = 1:(nl - 1)
    p      = spm_unvec(spm_vec(M(i).pE) + qp.u{i}*qp.p{i},M(i).pE);
    f{i,1} = feval(M(i).f,x{i},v{i},p);
    g{i,1} = feval(M(i).g,x{i},v{i},p);
end

% Get Derivatives
%==========================================================================
persistent D
try
    method = M(1).E.linear;
catch
    method = 0;
end

switch method

    % get derivatives at each iteration of D-step - full evaluation
    %----------------------------------------------------------------------
    case{0}

        D     = spm_DEM_eval_diff(x,v,qp,M);

        % gradients w.r.t. states
        %------------------------------------------------------------------
        dedy  = D.dedy;
        dedc  = D.dedc;
        dfdy  = D.dfdy;
        dfdc  = D.dfdc;
        dgdx  = D.dgdx;
        dgdv  = D.dgdv;
        dfdv  = D.dfdv;
        dfdx  = D.dfdx;
        dgdxp = D.dgdxp;
        dfdxp = D.dfdxp;
        dgdvp = D.dgdvp;
        dfdvp = D.dfdvp;

        % gradients w.r.t. parameters
        %------------------------------------------------------------------
        dgdp  = D.dgdp;
        dfdp  = D.dfdp;

    % linear: assume equations are linear in x and v
    %----------------------------------------------------------------------
    case{1}

        % get derivatives and store expansion point (states)
        %------------------------------------------------------------------
        if isempty(D)

            D     = spm_DEM_eval_diff(x,v,qp,M);
            D.x   = x;
            D.v   = v;

            % gradients w.r.t. states
            %--------------------------------------------------------------
            dedy  = D.dedy;
            dedc  = D.dedc;
            dfdy  = D.dfdy;
            dfdc  = D.dfdc;
            dgdx  = D.dgdx;
            dgdv  = D.dgdv;
            dfdv  = D.dfdv;
            dfdx  = D.dfdx;

            % gradients w.r.t. parameters (state-dependent)
            %--------------------------------------------------------------
            dgdxp = D.dgdxp;
            dfdxp = D.dfdxp;
            dgdvp = D.dgdvp;
            dfdvp = D.dfdvp;

            % gradients w.r.t. parameters
            %--------------------------------------------------------------
            dgdp  = D.dgdp;
            dfdp  = D.dfdp;

        % linear expansion for derivatives w.r.t. parameters
        %------------------------------------------------------------------
        else

            % gradients w.r.t. states
            %--------------------------------------------------------------
            dedy  = D.dedy;
            dedc  = D.dedc;
            dfdy  = D.dfdy;
            dfdc  = D.dfdc;
            dgdx  = D.dgdx;
            dgdv  = D.dgdv;
            dfdv  = D.dfdv;
            dfdx  = D.dfdx;
            dgdxp = D.dgdxp;
            dfdxp = D.dfdxp;
            dgdvp = D.dgdvp;
            dfdvp = D.dfdvp;

            % gradients w.r.t. parameters
            %--------------------------------------------------------------
            dx    = spm_vec(qu.x{1}) - spm_vec(D.x);
            dv    = spm_vec(qu.v{1}) - spm_vec(D.v);
            dgdp  = D.dgdp;
            dfdp  = D.dfdp;
            for p = 1:np
                dgdp(:,p) = D.dgdp(:,p) + D.dgdxp{p}*dx + D.dgdvp{p}*dv;
                if nx
                    dfdp(:,p) = D.dfdp(:,p) + D.dfdxp{p}*dx + D.dfdvp{p}*dv;
                end
            end

        end

    % bilinear: assume equations are linear in x and v and x*v
    %----------------------------------------------------------------------
    case{2}

        % get derivatives and store expansion point (states)
        %------------------------------------------------------------------
        if isempty(D)

            % get high-order derivatives
            %--------------------------------------------------------------
            [Dv D] = spm_diff('spm_DEM_eval_diff',x,v,qp,M,2);

            for i = 1:nv, Dv{i} = spm_unvec(Dv{i},D); end
            D.x   = x;
            D.v   = v;
            D.Dv  = Dv;

            % gradients w.r.t. states
            %--------------------------------------------------------------
            dedy  = D.dedy;
            dedc  = D.dedc;
            dfdy  = D.dfdy;
            dfdc  = D.dfdc;
            dgdx  = D.dgdx;
            dgdv  = D.dgdv;
            dfdv  = D.dfdv;
            dfdx  = D.dfdx;
            dgdxp = D.dgdxp;
            dfdxp = D.dfdxp;
            dgdvp = D.dgdvp;
            dfdvp = D.dfdvp;

            % gradients w.r.t. parameters
            %--------------------------------------------------------------
            dgdp  = D.dgdp;
            dfdp  = D.dfdp;

        % linear expansion for derivatives w.r.t. parameters
        %------------------------------------------------------------------
        else

            % gradients w.r.t. causes and data
            %--------------------------------------------------------------
            dedy  = D.dedy;
            dedc  = D.dedc;
            dfdy  = D.dfdy;
            dfdc  = D.dfdc;

            % states (relative to expansion point)
            %--------------------------------------------------------------
            dv    = spm_vec(qu.v{1}) - spm_vec(D.v);

            % gradients w.r.t. states
            %--------------------------------------------------------------
            dgdx  = D.dgdx;
            dgdv  = D.dgdv;
            dfdx  = D.dfdx;
            dfdv  = D.dfdv;
            for i = 1:nv; dgdx = dgdx + D.Dv{i}.dgdx*dv(i); end
            for i = 1:nv; dgdv = dgdv + D.Dv{i}.dgdv*dv(i); end
            for i = 1:nv; dfdx = dfdx + D.Dv{i}.dfdx*dv(i); end
            for i = 1:nv; dfdv = dfdv + D.Dv{i}.dfdv*dv(i); end

            % second-order derivatives
            %--------------------------------------------------------------
            dgdxp = D.dgdxp;
            dgdvp = D.dgdvp;
            dfdxp = D.dfdxp;
            dfdvp = D.dfdvp;
            for p = 1:np
                for i = 1:nv; dgdxp{p} = dgdxp{p} + D.Dv{i}.dgdxp{p}*dv(i); end
                for i = 1:nv; dgdvp{p} = dgdvp{p} + D.Dv{i}.dgdvp{p}*dv(i); end
                for i = 1:nv; dfdxp{p} = dfdxp{p} + D.Dv{i}.dfdxp{p}*dv(i); end
                for i = 1:nv; dfdvp{p} = dfdvp{p} + D.Dv{i}.dfdvp{p}*dv(i); end
            end

            % gradients w.r.t. parameters
            %--------------------------------------------------------------
            dgdp  = D.dgdp;
            dfdp  = D.dfdp;
            for p = 1:np
                Dgdxp     = (D.dgdxp{p} + dgdxp{p})/2;
                Dgdvp     = (D.dgdvp{p} + dgdvp{p})/2;
                Dfdxp     = (D.dfdxp{p} + dfdxp{p})/2;
                Dfdvp     = (D.dfdvp{p} + dfdvp{p})/2;
                dgdp(:,p) = dgdp(:,p) + Dgdvp*dv;
                dfdp(:,p) = dfdp(:,p) + Dfdvp*dv;
            end

        end

    % nonlinear: assume equations are bilinear in x and v
    %----------------------------------------------------------------------
    case{3}

        % get derivatives and store expansion point (states)
        %------------------------------------------------------------------
        if isempty(D)

            % get high-order derivatives
            %--------------------------------------------------------------
            [Dx D] = spm_diff('spm_DEM_eval_diff',x,v,qp,M,1,'q');
            [Dv D] = spm_diff('spm_DEM_eval_diff',x,v,qp,M,2,'q');

            for i = 1:nx, Dx{i} = spm_unvec(Dx{i},D); end
            for i = 1:nv, Dv{i} = spm_unvec(Dv{i},D); end
            D.x   = x;
            D.v   = v;
            D.Dx  = Dx;
            D.Dv  = Dv;

            % gradients w.r.t. states
            %--------------------------------------------------------------
            dedy  = D.dedy;
            dedc  = D.dedc;
            dfdy  = D.dfdy;
            dfdc  = D.dfdc;
            dgdx  = D.dgdx;
            dgdv  = D.dgdv;
            dfdv  = D.dfdv;
            dfdx  = D.dfdx;
            dgdxp = D.dgdxp;
            dfdxp = D.dfdxp;
            dgdvp = D.dgdvp;
            dfdvp = D.dfdvp;

            % gradients w.r.t. parameters
            %--------------------------------------------------------------
            dgdp  = D.dgdp;
            dfdp  = D.dfdp;

        % linear expansion for derivatives w.r.t. parameters
        %------------------------------------------------------------------
        else

            % gradients w.r.t. causes and data
            %--------------------------------------------------------------
            dedy  = D.dedy;
            dedc  = D.dedc;
            dfdy  = D.dfdy;
            dfdc  = D.dfdc;

            % states (relative to expansion point)
            %--------------------------------------------------------------
            dx    = spm_vec(qu.x{1}) - spm_vec(D.x);
            dv    = spm_vec(qu.v{1}) - spm_vec(D.v);

            % gradients w.r.t. states
            %--------------------------------------------------------------
            dgdx  = D.dgdx;
            dgdv  = D.dgdv;
            dfdx  = D.dfdx;
            dfdv  = D.dfdv;
            for i = 1:nx; dgdx = dgdx + D.Dx{i}.dgdx*dx(i); end
            for i = 1:nv; dgdx = dgdx + D.Dv{i}.dgdx*dv(i); end
            for i = 1:nx; dgdv = dgdv + D.Dx{i}.dgdv*dx(i); end
            for i = 1:nv; dgdv = dgdv + D.Dv{i}.dgdv*dv(i); end
            for i = 1:nx; dfdx = dfdx + D.Dx{i}.dfdx*dx(i); end
            for i = 1:nv; dfdx = dfdx + D.Dv{i}.dfdx*dv(i); end
            for i = 1:nx; dfdv = dfdv + D.Dx{i}.dfdv*dx(i); end
            for i = 1:nv; dfdv = dfdv + D.Dv{i}.dfdv*dv(i); end

            % second-order derivatives
            %--------------------------------------------------------------
            dgdxp = D.dgdxp;
            dgdvp = D.dgdvp;
            dfdxp = D.dfdxp;
            dfdvp = D.dfdvp;
            for p = 1:np
                for i = 1:nx; dgdxp{p} = dgdxp{p} + D.Dx{i}.dgdxp{p}*dx(i); end
                for i = 1:nv; dgdxp{p} = dgdxp{p} + D.Dv{i}.dgdxp{p}*dv(i); end
                for i = 1:nx; dgdvp{p} = dgdvp{p} + D.Dx{i}.dgdvp{p}*dx(i); end
                for i = 1:nv; dgdvp{p} = dgdvp{p} + D.Dv{i}.dgdvp{p}*dv(i); end
                for i = 1:nx; dfdxp{p} = dfdxp{p} + D.Dx{i}.dfdxp{p}*dx(i); end
                for i = 1:nv; dfdxp{p} = dfdxp{p} + D.Dv{i}.dfdxp{p}*dv(i); end
                for i = 1:nx; dfdvp{p} = dfdvp{p} + D.Dx{i}.dfdvp{p}*dx(i); end
                for i = 1:nv; dfdvp{p} = dfdvp{p} + D.Dv{i}.dfdvp{p}*dv(i); end
            end

            % gradients w.r.t. parameters
            %--------------------------------------------------------------
            dgdp  = D.dgdp;
            dfdp  = D.dfdp;
            for p = 1:np
                Dgdxp     = (D.dgdxp{p} + dgdxp{p})/2;
                Dgdvp     = (D.dgdvp{p} + dgdvp{p})/2;
                Dfdxp     = (D.dfdxp{p} + dfdxp{p})/2;
                Dfdvp     = (D.dfdvp{p} + dfdvp{p})/2;
                dgdp(:,p) = dgdp(:,p) + Dgdxp*dx + Dgdvp*dv;
                dfdp(:,p) = dfdp(:,p) + Dfdxp*dx + Dfdvp*dv;
            end

        end

    % repeated evaluation of first order derivatives (for Laplace scheme)
    %----------------------------------------------------------------------
    case{4}

        % get derivatives and store expansion point (states)
        %------------------------------------------------------------------
        if isempty(D)

            D     = spm_DEM_eval_diff(x,v,qp,M);
            D.x   = x;
            D.v   = v;

            % gradients w.r.t. states
            %--------------------------------------------------------------
            dedy  = D.dedy;
            dedc  = D.dedc;
            dfdy  = D.dfdy;
            dfdc  = D.dfdc;
            dgdx  = D.dgdx;
            dgdv  = D.dgdv;
            dfdv  = D.dfdv;
            dfdx  = D.dfdx;

            % gradients w.r.t. parameters (state-dependent)
            %--------------------------------------------------------------
            dgdxp = D.dgdxp;
            dfdxp = D.dfdxp;
            dgdvp = D.dgdvp;
            dfdvp = D.dfdvp;

            % gradients w.r.t. parameters
            %--------------------------------------------------------------
            dgdp  = D.dgdp;
            dfdp  = D.dfdp;

        % re-evaluate first-order derivatives
        %------------------------------------------------------------------
        else

            % retain second-order gradients
            %--------------------------------------------------------------
            dgdxp = D.dgdxp;
            dfdxp = D.dfdxp;
            dgdvp = D.dgdvp;
            dfdvp = D.dfdvp;

            % re-evaluate first-order gradients
            %--------------------------------------------------------------
            D     = spm_DEM_eval_diff(x,v,qp,M,0);
            dedy  = D.dedy;
            dedc  = D.dedc;
            dfdy  = D.dfdy;
            dfdc  = D.dfdc;
            dgdx  = D.dgdx;
            dgdv  = D.dgdv;
            dfdv  = D.dfdv;
            dfdx  = D.dfdx;

            % replace second-order gradients
            %--------------------------------------------------------------
            D.dgdxp = dgdxp;
            D.dfdxp = dfdxp;
            D.dgdvp = dgdvp;
            D.dfdvp = dfdvp;

            % gradients w.r.t. parameters
            %--------------------------------------------------------------
            dx    = spm_vec(qu.x{1}) - spm_vec(x);
            dv    = spm_vec(qu.v{1}) - spm_vec(v);
            dgdp  = D.dgdp;
            dfdp  = D.dfdp;
            for p = 1:np
                dgdp(:,p) = D.dgdp(:,p) + D.dgdxp{p}*dx + D.dgdvp{p}*dv;
                if nx
                    dfdp(:,p) = D.dfdp(:,p) + D.dfdxp{p}*dx + D.dfdvp{p}*dv;
                end
            end

        end

    otherwise
        disp('Unknown method')

end

% order parameters (d = n = 1 for static models)
%--------------------------------------------------------------------------
d       = M(1).E.d + 1;                    % generalisation order of q(v)
n       = M(1).E.n + 1;                    % embedding order     (n >= d)

% Generalised prediction errors and derivatives
%==========================================================================
Ex      = cell(n,1);
Ev      = cell(n,1);
[Ex{:}] = deal(sparse(nx,1));
[Ev{:}] = deal(sparse(ne,1));

% prediction error (E) - causes
%--------------------------------------------------------------------------
for i = 1:n
    qu.y{i} = spm_vec(qu.y{i});
end
Ev{1} = [qu.y{1}; qu.v{1}] - [spm_vec(g); qu.u{1}];
for i = 2:n
    Ev{i} = dedy*qu.y{i} + dedc*qu.u{i} ...      % generalised response
          - dgdx*qu.x{i} - dgdv*qu.v{i};         % and prediction
end

% prediction error (E) - states
%--------------------------------------------------------------------------
try
    Ex{1} = qu.x{2} - spm_vec(f);
end
for i = 2:n - 1
    Ex{i} = qu.x{i + 1} ...                      % generalised motion
          - dfdx*qu.x{i} - dfdv*qu.v{i};         % and prediction
end

% error
%--------------------------------------------------------------------------
E     = spm_vec({Ev,Ex});

% Kronecker forms of derivatives for generalised motion
%==========================================================================
if nargout < 2, return, end

% dE.dp (parameters)
%--------------------------------------------------------------------------
dgdp  = {dgdp};
dfdp  = {dfdp};
for i = 2:n
    dgdp{i,1} = dgdp{1};
    dfdp{i,1} = dfdp{1};
    for p = 1:np
        dgdp{i,1}(:,p) = dgdxp{p}*qu.x{i} + dgdvp{p}*qu.v{i};
        dfdp{i,1}(:,p) = dfdxp{p}*qu.x{i} + dfdvp{p}*qu.v{i};
    end
end

% generalised temporal derivatives: dE.du (states)
%--------------------------------------------------------------------------
dedy  = kron(spm_speye(n,n),dedy);
dedc  = kron(spm_speye(n,d),dedc);
dfdy  = kron(spm_speye(n,n),dfdy);
dfdc  = kron(spm_speye(n,d),dfdc);
dgdx  = kron(spm_speye(n,n),dgdx);
dgdv  = kron(spm_speye(n,d),dgdv);
dfdv  = kron(spm_speye(n,d),dfdv);
dfdx  = kron(spm_speye(n,n),dfdx) - kron(spm_speye(n,n,1),speye(nx,nx));

% 1st error derivatives (states)
%--------------------------------------------------------------------------
dE.dy =  spm_cat({dedy; dfdy});
dE.dc =  spm_cat({dedc; dfdc});
dE.dp = -spm_cat({dgdp; dfdp});
dE.du = -spm_cat({dgdx, dgdv  ;
                  dfdx, dfdv});

% bilinear derivatives
%--------------------------------------------------------------------------
for i = 1:np
    dgdxp{i}  = kron(spm_speye(n,n),dgdxp{i});
    dfdxp{i}  = kron(spm_speye(n,n),dfdxp{i});
    dgdvp{i}  = kron(spm_speye(n,d),dgdvp{i});
    dfdvp{i}  = kron(spm_speye(n,d),dfdvp{i});
    dE.dup{i} = -spm_cat({dgdxp{i}, dgdvp{i};
                          dfdxp{i}, dfdvp{i}});
end
if np
    dE.dpu    =  spm_cell_swap(dE.dup);
else
    dE.dpu    =  {};
end


function str = VBA_summary(out,newlines)
% writes a summary string from standard output of VBA model inversion
% function str = VBA_summary(out)
% IN:
%   - out: the 'out' structure of VBA inversion routine
%   - newlines: flag for inserting line separators (\n)
% OUT:
%   - str: a cell array of strings, which summarize the VBA inversion

try;newlines;catch,newlines=0;end

[LLH0] = VBA_LMEH0(out.y,out.options);
try F = out.F(end); catch, F = '?'; end
many = length(out.options.sources)>1; % more than one source?

str{1} = sprintf(['Date: ',datestr(out.date)]);
if ~out.options.OnLine
    s0 = ['VB converged in ',num2str(out.it),' iterations'];
else
    s0 = ['Online VB algorithm'];
end
try
    if floor(out.dt./60) == 0
        timeString = [num2str(floor(out.dt)),' sec'];
    else
        timeString = [num2str(floor(out.dt./60)),' min'];
    end
    str{2} = sprintf([s0,' (took ~',timeString,')']);
catch
    str{2} = sprintf(s0);
end
if many
    datastr = [' (number of sources=',num2str(length(out.options.sources)),')'];
else
    datastr = [];
end
str{3} = sprintf(['Dimensions of the model:','\n ',...
    '    - data: p=',num2str(out.dim.p),datastr,'\n ',...
    '    - time samples: t=',num2str(out.dim.n_t),'\n ',...
    '    - hidden states: n=',num2str(out.dim.n),'\n ',...
    '    - evolution parameters: n_theta=',num2str(out.dim.n_theta),'\n ',...
    '    - observation parameters: n_phi=',num2str(out.dim.n_phi),'\n ',...
    '    - inputs: n_u=',num2str(out.dim.u)]);
if numel(out.options.sources)>1
    tmp = ' (multisource)';
else
    switch out.options.sources.type
        case 0
            tmp = ' (gaussian data)';
        case 1
            tmp = ' (binomial data)';
        case 2
            tmp = ' (multinomial data)';
    end
end
if out.options.UNL
    so = 'un-normalized likelihood';
else
    so = 'observation';
end
if out.dim.n >= 1
    if isinf(out.options.priors.a_alpha) && isequal(out.options.priors.b_alpha,0)
        str{4} = sprintf('This was a deterministic dynamical system');
    else
        str{4} = sprintf('This was a stochastic dynamical system');
    end
    if isa(out.options.g_fname,'function_handle')
        gfn = func2str(out.options.g_fname);
    else
        gfn = out.options.g_fname;
    end
    if isequal(gfn,'g_embed')
        gfn0 = out.options.inG.g_fname;
        if isa(gfn0,'function_handle')
            gfn0 = func2str(gfn0);
        end
        gfn = [gfn,' (',gfn0,')'];
        str{4} = [str{4},' (with delay embedding)'];
    end
    if isa(out.options.f_fname,'function_handle')
        ffn = func2str(out.options.f_fname);
    else
        ffn = out.options.f_fname;
    end
    if isequal(ffn,'f_embed')
        ffn0 = out.options.inF.f_fname;
        if isa(ffn0,'function_handle')
            ffn0 = func2str(ffn0);
        end
        ffn = [ffn,' (',ffn0,')'];
    end
    str{4} = sprintf([str{4},'\n ',...
        '    - ',so,' function: ',gfn,tmp,'\n ',...
        '    - evolution function: ',ffn]);
else
    str{4} = ['The model was static (no hidden states)','\n '];
    if isa(out.options.g_fname,'function_handle')
        gfn = func2str(out.options.g_fname);
    else
        gfn = out.options.g_fname;
    end
    str{4} = sprintf([str{4},'    - ',so,' function: ',gfn,tmp]);
end
str{5} = sprintf(['Bayesian log model evidences:','\n',...
    '     - full model: log p(y|m) > ',num2str(F,'%4.3e'),'\n',...
    '     - null hypothesis: log p(y|H0) = ',num2str(LLH0,'%4.3e')]);
if ~out.options.OnLine && out.dim.n >= 1 && ~isinf(out.options.priors.a_alpha) && ~isequal(out.options.priors.b_alpha,0)
    Fd = out.options.init.out.F;
    str{5} = sprintf([str{5},'\n ',...
        '    - deterministic variant: log p(y|m,eta=0) > ',num2str(Fd,'%4.3e') ]);
end
% str{5} = [str{5}, '\n'];

gsi = find([out.options.sources.type]==0);
bsi = find([out.options.sources.type]~=0);
many = length(out.options.sources)>1;
R2str = ['     - determin. coeff. (R2):  '];
LLstr = ['     - log-likelihood: '];
AICstr = ['     - AIC: '];
BICstr = ['     - BIC: '];
if ~isempty(gsi)
    R2str = [R2str,catnum2str(out.fit.R2,gsi,many,'%')];
    CAstr = [];
    LLstr = [LLstr,catnum2str(out.fit.LL,gsi,many)];
    AICstr = [AICstr,catnum2str(out.fit.AIC,gsi,many)];
    BICstr = [BICstr,catnum2str(out.fit.BIC,gsi,many)];
    separator = ', ';
else
    separator = [];
end
if  ~isempty(bsi)
    R2str = [R2str,separator,catnum2str(out.fit.R2,bsi,many,'%')];
    CAstr = ['     - balanced classif. acc.:  '];
    CAstr = [CAstr,catnum2str(out.fit.bacc,bsi,many,'%'),'\n'];
    LLstr = [LLstr,separator,catnum2str(out.fit.LL,bsi,many)];
    AICstr = [AICstr,separator,catnum2str(out.fit.AIC,bsi,many)];
    BICstr = [BICstr,separator,catnum2str(out.fit.BIC,bsi,many)];
end
R2str = [R2str,'\n'];
LLstr = [LLstr,'\n'];
AICstr = [AICstr,'\n'];
% BICstr = [BICstr,'\n'];
str{6} = ['Classical goodness-of-fit metrics:','\n',...
    R2str,...
    CAstr,...
    LLstr,...
    AICstr,...
    BICstr];

if newlines
    for i=1:length(str)
        str{i} = [str{i},'\n'];
    end
end

function str = catnum2str(x,ind,many,flag)
try,flag;catch,flag=[];end
str = [];
for i=1:length(ind)
    si=ind(i);
    if isequal(flag,'%')
        str = [str,', ',num2str(100*x(si),'%2.1f%%'),'%'];
    else
        str = [str,', ',num2str(x(si),'%4.3e')];
    end
    if many
        str = [str,' (source #',num2str(si),')'];
    end
end
str(1:2) = [];


function a = nnz(t)
%NNZ Number of nonzeros in sparse tensor.
%
%   NNZ(T) is the number of nonzero elements in T.
%
%   See also SPTENSOR, SPTENSOR/FIND.
%
%MATLAB Tensor Toolbox.
%Copyright 2015, Sandia Corporation.

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

if isempty(t.subs)
    a = 0;
else
    a = size(t.subs,1);
end


function mprob = convGMatlab(prob,opts)
%CONVGMATLAB Convert OPTI problem to MATLAB Global Optimization Toolbox problem
%
%   mprob = convGMatlab(prob,opts)

%   Copyright (C) 2012 Jonathan Currie (I2C2)

%Ensure all args passed
if(nargin < 2)
    error('You must supply both the problem + options');
end
if(~isstruct(prob) || ~isstruct(opts))
    error('Both prob + opts must be structures!');
end

%Make sure we have an NLP
if(~any(strcmpi(prob.type,{'NLP','UNO','MINLP'})))
    error('You can only convert UNOs, NLPs and MINLPs to MATLAB Global format!');
end

%Starting Guess
if(isfield(prob,'x0'))
    mprob.x0 = prob.x0;
end

warn = strcmpi(opts.warnings,'all');

%Problem dependent args
switch(upper(prob.type))
    case 'UNO'
        mprob.solver = 'patternsearch';
        mprob.options = psoptimset(opts.solverOpts,'TimeLimit',opts.solverOpts.MaxTime);
        mprob.objective = prob.fun;

    case 'NLP'
        mprob.solver = 'patternsearch';
        mprob.options = psoptimset(opts.solverOpts,'TimeLimit',opts.solverOpts.MaxTime);
        %Linear stuff
        mprob.Aineq = prob.A;
        mprob.bineq = prob.b;
        mprob.Aeq = prob.Aeq;
        mprob.beq = prob.beq;
        mprob.lb = prob.lb;
        mprob.ub = prob.ub;
        %Objective
        mprob.objective = prob.fun;
        %Check for NL Constraints
        if(~isempty(prob.nlcon))
            %Get Constraint Types
            max_in = prob.nle == 1;
            min_in = prob.nle == -1;
            eq = prob.nle == 0;
            mprob.nonlcon = @(x) nlCon(x,prob.nlcon,prob.nlrhs,max_in,min_in,eq);
        end
    case 'MINLP'
        mprob.solver = 'ga';
        mprob.options = psoptimset(opts.solverOpts,'TimeLimit',opts.solverOpts.MaxTime);
        %Linear stuff
        mprob.Aineq = prob.A;
        mprob.bineq = prob.b;
        mprob.lb = prob.lb;
        mprob.ub = prob.ub;
        if(~isempty(prob.beq) && warn)
            warning('opti_gmatlab:ga_eq','The MATLAB GA Integer Solver does not accept linear equalities, ignoring');
        end
        %Objective
        mprob.fitnessfcn = prob.fun;
        mprob.nvars = prob.sizes.ndec;
        %Check for NL Constraints
        if(~isempty(prob.nlcon))
            %Get Constraint Types
            max_in = prob.nle == 1;
            min_in = prob.nle == -1;
            eq = prob.nle == 0;
            if(~isempty(eq) && warn)
                warning('opti_gmatlab:ga_eq','The MATLAB GA Integer Solver does not accept nonlinear equalities, ignoring');
            end
            mprob.nonlcon = @(x) nlCon(x,prob.nlcon,prob.nlrhs,max_in,min_in,eq);
        end
        %Integer Constraints
        if(any(prob.int.ind))
            mprob.intcon = prob.int.idx;
        end

    otherwise
        error('Not implemented yet');
end

%Check for iterfun
if(isfield(opts,'iterfun') && ~isempty(opts.iterfun))
    mprob.options.OutputFcns = @(optimV,o,f) mCall(optimV,o,f,opts.iterfun);
end

function [cin,ceq] = nlCon(x,fun,rhs,max_in,min_in,eq)
% Handle to allow matlab to get nonlinear inequality and equality
% constraints in a single function with selectable bounds
% (not very efficient)

%Get Constraint Eval
sol = fun(x);
%Defaults
cin = [];
ceq = [];
%Assign results with bounds
if(any(max_in))
    cin = -sol(max_in) + rhs(max_in);
end
if(any(min_in))
    cin = [cin; sol(min_in) - rhs(min_in)];
end
if(any(eq))
    ceq = sol(eq) - rhs(eq);
end

function [stop,o,oc] = mCall(optimValues,o,state,fun)
% Handle to convert MATLAB callback to OPTI callback

stop = false;
oc = false;
switch state
    case 'iter'
        stop = fun(optimValues.iteration,optimValues.fval,optimValues.x);
        drawnow;
end


function a = r8row_sort_quick_a ( m, n, a )

%*****************************************************************************80
%
%% R8ROW_SORT_QUICK_A ascending quick sorts an R8ROW.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 May 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the number of rows of A.
%
%    Input, integer N, the number of columns of A.
%
%    Input, real A(M,N), the array to be sorted.
%
%    Output, real A(M,N), the sorted array.
%
  level_max = 30;

  if ( n <= 0 )
    return
  end

  if ( m < 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8ROW_SORT_QUICK_A - Fatal error!\n' );
    fprintf ( 1, '  M < 1.\n' );
    error ( 'R8ROW_SORT_QUICK_A - Fatal error!' );
  end

  if ( m == 1 )
    return
  end

  level = 1;
  rsave(level) = m + 1;
  base = 1;
  m_segment = m;

  while ( 1 )
%
%  Partition the segment.
%
    [ a(base:base+m_segment-1,1:n), l_segment, r_segment ] = r8row_part_quick_a ( ...
      m_segment, n, a(base:base+m_segment-1,1:n) );
%
%  If the left segment has more than one element, we need to partition it.
%
    if ( 1 < l_segment )

      if ( level_max < level )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R8ROW_SORT_QUICK_A - Fatal error!\n' );
        fprintf ( 1, '  Exceeding recursion maximum of %d\n', level_max );
        error ( 'R8ROW_SORT_QUICK_A - Fatal error!' );
      end

      level = level + 1;
      m_segment = l_segment;
      rsave(level) = r_segment + base - 1;
%
%  The left segment and the middle segment are sorted.
%  Must the right segment be partitioned?
%
    elseif ( r_segment < m_segment )

      m_segment = m_segment + 1 - r_segment;
      base = base + r_segment - 1;
%
%  Otherwise, we back up a level if there is an earlier one.
%
    else

      while ( 1 )

        if ( level <= 1 )
          return
        end

        base = rsave(level);
        m_segment = rsave(level-1) - rsave(level);
        level = level - 1;

        if ( 0 < m_segment )
          break
        end

      end

    end

  end

  return
end


function [ node_x, element_node ] = gmsh_data_read ( gmsh_filename, ...
  node_dim, node_num, element_order, element_num )

%*****************************************************************************80
%
%% GMSH_DATA_READ reads data from a GMSH file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 October 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string GMSH_FILENAME, the GMSH filename.
%
%    Input, integer NODE_DIM, the spatial dimension.
%
%    Input, integer NODE_NUM, the number of nodes.
%
%    Input, integer ELEMENT_ORDER, the order of the elements.
%
%    Input, integer ELEMENT_NUM, the number of elements.
%
%    Output, real NODE_X(NODE_DIM,NODE_NUM), the node coordinates.
%
%    Output, integer ELEMENT_NODE(ELEMENT_ORDER,ELEMENT_NUM),
%    the nodes that make up each element.
%
  node_x = zeros ( node_dim, node_num );
  element_node = zeros ( element_order, element_num );
%
%  Open the file.
%
  input = fopen ( gmsh_filename, 'rt' );

  if ( input < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'GMSH_DATA_READ - Error!\n' );
    fprintf ( 1, '  Could not open the input file "%s".\n', gmsh_filename );
    error ( 'GMSH_DATA_READ - Error!' );
    return
  end

  level = 0;

  while ( 1 )

    text = fgetl ( input );

    if ( text == -1 )
      break
    end

    if ( level == 0 )
      if ( s_begin ( text(1:6), '$Nodes' ) )
        level = 1;
        j = 0;
      end
    elseif ( level == 1 )
      [ value, count ] = sscanf ( text, '%d' );
      level = 2;
    elseif ( level == 2 )
      if ( s_begin ( text(1:9), '$EndNodes' ) )
        break
      else
        j = j + 1;
        [ value, count ] = sscanf ( text, '%d  %f  %f  %f' );
        indx = value(1);
        node_x(1,j) = value(2);
        if ( 2 < count )
          node_x(2,j) = value(3);
          if ( 3 < count )
            node_x(3,j) = value(4);
          end
        end
      end
    end

  end
%
%  Now read element information.
%
  level = 0;

  while ( 1 )

    text = fgetl ( input );

    if ( text == -1 )
      fprintf ( 'ran out\n' );
      break
    end

    if ( level == 0 )
      if ( s_begin ( text(1:9), '$Elements' ) )
        level = 1;
        j = 0;
      end
    elseif ( level == 1 )
      [ value, count ] = sscanf ( text, '%d' );
      level = 2;
    elseif ( level == 2 )
      if ( s_begin ( text(1:12), '$EndElements' ) )
        break
      else
        j = j + 1;
        [ value, count ] = sscanf ( text, '%d' );
        for i = 1 : element_order
          element_node(i,j) = value(5+i);
        end
      end
    end

  end

  fclose ( input );

  return
end


function refinement_model=train_refiner(imnames, region_meta_info, featdir, sptextdir, regspimgdir, sbddir, Wsz, categid)
feats=[];
labels=[];

regidsall=cell(numel(imnames),1);
movindall=cell(numel(imnames),1);
%collect training examples
for i=1:numel(imnames)
    %check if there is any groundtruth for this category
    if(~any(region_meta_info.gt{i}==categid))
        continue;
    end
    fprintf('Getting training regions %d\n', i);

    %find ground truths
    gtids=find(region_meta_info.gt{i}==categid);

    %find regions that overlap by more than 70\%
    [mov, movind]=max(region_meta_info.overlaps{i}(gtids,:),[],1);
    regids=find(mov>=0.7);
    movind=gtids(movind(regids));

    %index into features/sp
    nongtids=find(region_meta_info.gt{i}==0);
    regids=nongtids(regids);

    regidsall{i}=regids;
    movindall{i}=movind;
end
for i=1:numel(imnames)
    regids=regidsall{i};
    movind=movindall{i};
    if(isempty(regids))
        continue;
    end
    fprintf('Getting training features:%d\n', i);

    %load gt
    [cls, inst] = load_gt(sbddir, imnames{i});
    %load features
    d=load(fullfile(featdir, [imnames{i} '.mat']));
    f=d.feats(regids,:)';

    %load superpixels
    [sp, reg2sp]=read_sprep(fullfile(sptextdir, [imnames{i} '.txt']), fullfile(regspimgdir, [imnames{i} '.png']));

    %get boxes
    boxes=get_region_boxes(sp, reg2sp);
    spf=[];
    lab=[];
    %for each selected region
    for j=1:numel(regids)
        box=boxes(regids(j),:);
        box=expand_box(box, 16/(227-32));
        msk=reg2sp(:,regids(j));
        msk=msk(sp);
        clipped_msk=clip_img(msk, box);
        clipped_gt=clip_img(double(double(inst)==movind(j)),box);
        cl_msk_rsz=imresize(clipped_msk,Wsz);
        cl_gt_rsz=imresize(clipped_gt, Wsz);
        spf=[spf cl_msk_rsz(:)];
        lab=[lab cl_gt_rsz(:)>0.5];
    end

    f=[f; spf];
    if(isempty(feats))
        feats=zeros(size(f,1),10000);
        labels=zeros(10000,prod(Wsz));
        cnt=0;
    end
    feats(:,cnt+(1:size(f,2)))=f;
    labels(cnt+(1:size(f,2)),:)=double(lab');
    cnt=cnt+size(f,2);
end
feats=feats(:,1:cnt);
labels=labels(1:cnt,:);

%train svms
for i=1:prod(Wsz)
fprintf('Training coarse model for grid cell %d\n',i);
logisticmodel=liblinear_train(double(labels(:,i)), double(feats), '-s 0 -c 0.01 -B 1', 'col');
if(logisticmodel.Label(1)==0)
    W{i}=-logisticmodel.w;
else
    W{i}=logisticmodel.w;
end
end
W=cat(1, W{:});

%make all predictions
scr=bsxfun(@plus, W(:,1:end-1)*feats, W(:,end));
pred=1./(1+exp(-scr));

%train superpixel predictor
feats=zeros(2,1000000);
labels=zeros(1, 1000000);;
cnt=0;
cnt2=0;
for i=1:numel(imnames)
    regids=regidsall{i};
    movind=movindall{i};
    if(isempty(regids)) continue; end
    fprintf('Getting second stage feats:%d\n',i);
    %load superpixels
    [sp, reg2sp]=read_sprep(fullfile(sptextdir, [imnames{i} '.txt']), fullfile(regspimgdir, [imnames{i} '.png']));

    %get all coarse predictions
    predcurr=pred(:,cnt+(1:numel(regids)));
    cnt=cnt+numel(regids);

    boxes=get_region_boxes(sp, reg2sp);

    spareas=accumarray(sp(:),1);
    %apply it to each region
    for j=1:numel(regids)
        box=boxes(regids(j),:);
        box=expand_box(box, 16/(227-32));
        coarse_reg2sp=apply_mask(predcurr(:,j), box, sp,Wsz);
        orig_reg2sp=reg2sp(:,regids(j));

        %only choose large pixels and pixels for which prediction is large enough
        idx=find(spareas>100 & (coarse_reg2sp>0.2 | orig_reg2sp>0));

        %next get the true labels
        lab=reg2sp(:,movind(j));
        feats(1,cnt2+(1:numel(idx)))=coarse_reg2sp(idx);
        feats(2, cnt2+(1:numel(idx)))=orig_reg2sp(idx);
        labels(cnt2+(1:numel(idx)))=lab(idx);
        cnt2=cnt2+numel(idx);
    end
end
feats=feats(:,1:cnt2);
labels=labels(:,1:cnt2);

%learn second model
spmodel=liblinear_train(labels(:), feats, '-s 0 -c 1 -B 1', 'col');

refinement_model.W=W;
refinement_model.spmodel=spmodel;


clc;clear;
models = {'','useCN10_ECSSD'};

Num = length(models);
method_col = {[1,0,0],[0,1,0],[0.5 0.5 0.5],[136 0 21]/255,[255 127 39]/255,...
    [0 162 232]/255,[163 73 164]/255,[1 0 1]};
for i = 1 : Num
    load(models{i});
    mmFmeasure = (1+0.3).*mPre.*mRecall./(0.3.*mPre+mRecall);
    plot([0:255/20:255],mmFmeasure,'Color',method_col{i},'LineWidth',2);
    axis([0 255 0 0.9]);
    grid on;
    hold on;
end
legend( models );


function [pv01, fx]=pitchestm(data, fs, nfr10, pv01)
% function [pv01, pvblk, pvblkb, pv]=pitchestm(data, fs, nfr10, pv01)

[fx,tt,pv,fv]=fxpefac(data, fs); % should plus 3
npv=length(pv);
pv01=zeros(nfr10,1); sign_pv=0;
for i=1:npv
    if pv(i)>0.25
        pv01(i+3) =1;
        if sign_pv==0
            sign_pv=1;
            nstart=i;
        end
    else
        if sign_pv==1
            sign_pv=0;
            nstop=i-1;
            if nstop-nstart<3
                pv01(nstart+3:nstop+3)=0;  % Remove 2 frames only pitch
            end
        end
    end
end
pv01(1:3)=pv01(4);
fxtmp(1:3)=fx(4); fxtmp(4:npv+3)=fx(1:npv);
if (npv+3) < nfr10
    pv01(npv+4:nfr10)=pv01(npv+3);
    fxtmp(npv+4:nfr10)=fx(npv);
else
    pv01=pv01(1:nfr10);
    fxtmp=fxtmp(1:nfr10);
end
fx=fxtmp;


function ROI = grayLineROI(nodes, edges, startPoint, endPoint, mmPerVox, mask);
% Create a line ROI representing the shortest path ("geodesic") between two
% gray nodes. Requires mrManDist.
%
%    ROI = grayLineROI([nodes, edges], startPoint, endPoint, [mmPerVox=1,1,1], [mask]);
%
% This function simply adapts some test code provided into the comments
% for mrManDist, to create a separate function to find the geodesic.
%
% Returns a mrVista-format ROI. (See roiCreate1 for format.)
%
% INPUTS:
% nodes, edges: gray nodes and edges from a gray graph. You can also
% provide a path to a NIFTI classification file or mrGray gray graph as the
% nodes argument, and it will load/grow them from the file. [default:
% prompt for a file.]
%
% startPoint: node index or 3x1 [x y z] volume coords of the start point for
% the line ROI.
%
% endPoint: node index or 3x1 [x y z] volume coords of the end point for
% the line ROI.
%
% mask: optional [1 x N] mask vector, where N is the number of nodes. Will
% only look for the geodesic along nodes where the mask is 1 (true).
%
% OUTPUTS:
%
% ROI: mrVista-format ROI containing the line coordinates.
%
% NOTE: There is an error on some versions of MATLAB (such as 2007a,b on
% Windows) where mrManDist returns an invalid set of distances -- it
% doesn't error, but also doesn't measure distances. If that's the case,
% this function will not work.
%
%
% ras, 07/2009. I implemented this separate from the mrVista views, so it
% will hopefully be more portable in the future.
if notDefined('nodes') & notDefined('edges')
	[pth ok] = mrvSelectFile('r', {'gray' 'Gray' 'nii' 'nii.gz'}, ...
					    'Select a gray graph or NIFTI file');
	if ~ok, disp('Aborted.'); return; end
	[p f ext] = fileparts(pth);
	if strncmp( lower(ext), '.gray', 5 )
		[nodes edges] = readGrayGraph(pth);
	elseif strncmp( lower(ext), 'nii', 4 );
		%% TODO: support NIFTI
	else
		error('Invalid file type %s.', pth);
	end
end

if notDefined('startPoint') | notDefined('endPoint')
	error('Need start and end points.')
end

if notDefined('mmPerVox'),	mmPerVox = [1 1 1];		end

%% TODO: parse 3x1 start/end point specifications into nodes
if length(startPoint)==3
	startPoint = nearestGrayNode(nodes, startPoint);
end

if length(endPoint)==3
	endPoint = nearestGrayNode(nodes, endPoint);
end

%% core part of code: get geodisc using mrManDist.
% find distances from start point, and connected list of points from start
% point.
[dist npts lastPoint] = mrManDist( double(nodes), double(edges), ...
								   startPoint, mmPerVox, -1, 0 );

% track back along the 'lastPoint' list, from the start point to the end
% point, to construct the geodesic:
geodesic = [];
nextPoint = endPoint;
while nextPoint ~= startPoint
	geodesic(end+1) = lastPoint(nextPoint);
	nextPoint = lastPoint(nextPoint);
end

%% create line ROI from geodesic.
ROI = roiCreate1;
ROI.name = sprintf('Line ROI %s %s', num2str(startPoint), num2str(endPoint));
ROI.color = [1 1 0];
ROI.coords = nodes([2 1 3],geodesic);
ROI.comments = [sprintf('Created by %s %s.\n', mfilename, datestr(now)) ...
				sprintf('Start point: %s', num2str(startPoint)) ...
				sprintf('End point: %s', num2str(endPoint))];

return
% /--------------------------------------------------------------/ %

% /--------------------------------------------------------------/ %
function node = nearestGrayNode(nodes, pt);
% find the index of the gray node nearest the point at 3x1 coordinate pt.
% we assume here the point is specified using mrVista conventions: [axi cor
% sag].

%% first, check if the point is in the nodes list.
% the mrVista coordinate specification is [axi cor sag], while the
% convention for the gray nodes is [cor axi sag]. Hence the flip.
node = find( nodes(2,:)==pt(1) & nodes(1,:)==pt(2) & nodes(3,:)==pt(3) );

%% if the node is found, we're done. Otherwise, find the nearest gray node.
if isempty(node)
	if prefsVerboseCheck >= 1
		fprintf('[%s]: looking for nearest gray node to %s...', ...
				mfilename, num2str(pt));
	end

% 	% this doesn't seem to work...
% 	[node bestSqDist] = nearpoints(double(pt), nodes([2 1 3],:));

	% use the algorithm I use in segGet to find the nearest node
	tolerance = 5; % mm
	dist = sqrt( [nodes(2,:) - pt(1)] .^ 2 + ...
		[nodes(1,:) - pt(2)] .^ 2 + ...
		[nodes(3,:) - pt(3)] .^ 2 );
	if min(dist) > tolerance
		warning(sprintf('[%s]: no node found within tolerance [%i mm]', ...
			mfilename, tolerance));
		varargout{1} = [];
	else
		I = find(dist==min(dist));
		node = I(1);
	end

	if prefsVerboseCheck >= 1
		fprintf('done. Best distance: %.1f.\n', min(dist));
	end
end

return


function t = getLinesearch(problem, x, d, storedb, key)
% Returns a hint for line-search algorithms.
%
% function t = getLinesearch(problem, x, d)
% function t = getLinesearch(problem, x, d, storedb)
% function t = getLinesearch(problem, x, d, storedb, key)
%
% For a line-search problem at x along the tangent direction d, computes
% and returns t such that retracting t*d at x yields a good point around
% where to look for a line-search solution. That is: t is a hint as to
% "how far to look" along the line.
%
% storedb is a StoreDB object, key is the StoreDB key to point x.
%
% See also: canGetLinesearch

% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, July 17, 2014.
% Contributors:
% Change log:
%
%   April 3, 2015 (NB):
%       Works with the new StoreDB class system.

    % Allow omission of the key, and even of storedb.
    if ~exist('key', 'var')
        if ~exist('storedb', 'var')
            storedb = StoreDB();
        end
        key = storedb.getNewKey();
    end

    if isfield(problem, 'linesearch')
    %% Compute the line-search hint function using linesearch.

        % Check whether this function wants to deal with storedb or not.
        switch nargin(problem.linesearch)
            case 2
                t = problem.linesearch(x, d);
            case 3
                % Obtain, pass along, and save the store for x.
                store = storedb.getWithShared(key);
                [t, store] = problem.linesearch(x, d, store);
                storedb.setWithShared(store, key);
            case 4
                % Pass along the whole storedb (by reference), with key.
                t = problem.linesearch(x, d, storedb, key);
            otherwise
                up = MException('manopt:getLinesearch:badfun', ...
                    'linesearch should accept 2, 3 or 4 inputs.');
                throw(up);
        end

    else
    %% Abandon computing the line-search function.

        up = MException('manopt:getLinesearch:fail', ...
            ['The problem description is not explicit enough to ' ...
             'compute a line-search hint.']);
        throw(up);

    end

end


function x = p03_x ( n )

%*****************************************************************************80
%
%% P03_X returns the least squares solution X for problem 3.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 April 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of variables.
%
%    Output, real X(N,1), the least squares solution.
%
  x = [ -7.5555556; 0.1111111; 7.7777778 ];

  return
end


function p = adjustable_CPD(CPD)
% ADJUSTABLE_CPD Does this CPD have any adjustable params? (gaussian)
% p = adjustable_CPD(CPD)

p = ~CPD.clamped_mean | ~CPD.clamped_cov | ~CPD.clamped_weights;