%% Microstrip low-pass filter analysis using 3D FDTD code with UPML
%% absorbing borders (ABC)
%
% Here we use FDTD 3D with UPML to calculate scattering coefficients S_{11}
% and S_{21} for planar microstrip low-pass filter following by the original
% paper by D. Sheen, S. Ali, M. Abouzahra, J. Kong "Application of the
% Three-Dimensional Finite-Difference Time-Domain Method to the Analysis of
% planar Microstrip Circuits", IEEE Trans. on Microwave Theory and Techniques
% (http://dx.doi.org/10.1109/22.55775).
% Also |S_{21}| dependence can be taken from the paper "Computational
% electromagnetic method for interconnects and small structures" by C.
% Balanis, A. Policarpou and S. Georgakopoulos
% (http://dx.doi.org/10.1006/spmi.2000.0865)
%% Current code includes some improvements in comparison with the original
%% calculations:
% 1) imposing UPML instead of Mur ABCs;
% 2) using real metal (copper) as a patch conductor material instead of PEC;
% 3) applying matched load at the ends of filter's transmission microstrip
%    lines to prevent physical reflections;
% 4) no "magnetic wall" or "electric wall" conditions at the Ez source plane.
%
function FDTD_3D_Lowpass
close all; clear; clc;
%% Physical constants
   epsilon0 = 8.85418782e-12; mu0 = 1.25663706e-6;
   c = 1.0/sqrt(mu0*epsilon0);

%% Gaussian half-width
   t_half = 15.0e-12;

%% Microstrip transmission lines parameters
   lineW = 2.413e-3;
   lineH = 1.0e-3;
   lineEr = 2.2;
   Z0 = 49.2526;

%% End time
   t_end = 1.5e-9;

%% Total mesh dimensions and grid cells sizes (without PML)
   nx = 80; ny = 100; nz = 16;
   dx = 0.4064e-3; dy = 0.4233e-3; dz = 0.2650e-3;

%% Number of PML layers
   PML = 5;

%% Matrix of material's constants
   number_of_materials = 4;
   % For material of number x = 1,2,3... :
   % Material(x,1) - relative permittivity, Material(x,2) - relative permeability,
   % Material(x,3) - specific conductivity
   % Vacuum
   Material(1,1) = 1.0;   Material(1,2) = 1.0;   Material(1,3) = 0.0;
   % Metal (Copper)
   Material(2,1) = 1.0;   Material(2,2) = 1.0;   Material(2,3) = 5.88e+7;
   % Substrate material (RT/Duroid 5880)
   Material(3,1) = lineEr;   Material(3,2) = 1.0;   Material(3,3) = 0.0;
   % Matched load material is calculated from transmission line parameters
   Material(4,1) = 1.0;   Material(4,2) = 1.0;   Material(4,3) = lineH/(Z0*lineW*dy);

% Add PML layers
   nx = nx + 2*PML; ny = ny + 2*PML; nz = nz + 2*PML;
% Calculate dt
   dt = (1.0/c/sqrt( 1.0/(dx^2) + 1.0/(dy^2) + 1.0/(dz^2)))*0.9999;
   number_of_iterations = ceil(t_end/dt);

%% 3D array for geometry
   Index = ones(nx, ny, nz);

%% Define of low-pass filter geometry
   % Ground plane
   Index((1+PML):(nx-PML), (1+PML):(ny-PML), PML+1) = 2;
   % Rectangular patch (one cell thickness)
   Index((nx/2-25):(nx/2+25), (ny/2-3):(ny/2+3), PML+5) = 2;
   % Transmission line from port 1 to rectangular patch
   Index((nx/2-10):(nx/2-5), (PML+1):ny/2, PML+5) = 2;
   % Transmission line from rectangular patch to port 2
   Index((nx/2+5):(nx/2+10), ny/2:(ny-PML), PML+5) = 2;
   % Dielectric substrate between ground plane and filter patch
   Index((1+PML):(nx-PML), (1+PML):(ny-PML), (PML+2):(PML+4)) = 3;
   % Matched load before port 1
   Index((nx/2-10):(nx/2-5), PML+1, (PML+2):(PML+4)) = 4;
   % Matched load after port 2
   Index((nx/2+5):(nx/2+10), ny-PML, (PML+2):(PML+4)) = 4;

%% 3D FDTD physical (fields) and additional arrays are defined as 'single'
%% to increase performance
   Ex = zeros(nx, ny+1, nz+1, 'single');
   Gx = zeros(nx, ny+1, nz+1, 'single');
   Fx = zeros(nx, ny+1, nz+1, 'single');
   Ey = zeros(nx+1, ny, nz+1, 'single');
   Gy = zeros(nx+1, ny, nz+1, 'single');
   Fy = zeros(nx+1, ny, nz+1, 'single');
   Ez = zeros(nx+1, ny+1, nz, 'single');
   Gz = zeros(nx+1, ny+1, nz, 'single');
   Fz = zeros(nx+1, ny+1, nz, 'single');
   Hx = zeros(nx+1, ny, nz, 'single');
   Bx = zeros(nx+1, ny, nz, 'single');
   Hy = zeros(nx, ny+1, nz, 'single');
   By = zeros(nx, ny+1, nz, 'single');
   Hz = zeros(nx, ny, nz+1, 'single');
   Bz = zeros(nx, ny, nz+1, 'single');

%% FDTD PML coefficients arrays. Here they are already filled with values
%% corresponding to free space
   m = 4; ka_max = 1.0; R_err = 1.0e-16;
   eta = sqrt(mu0/epsilon0*Material(1,1)/Material(1,2));
   k_Ex_c = ones(nx, ny, nz, 'single')*2.0*epsilon0;
   k_Ex_d = ones(nx, ny, nz, 'single')*(-2.0*epsilon0);
   k_Ey_a = ones(nx+1, ny, nz, 'single');
   k_Ey_b = ones(nx+1, ny, nz, 'single')/(2.0*epsilon0);
   k_Gz_a = ones(nx+1, ny, nz, 'single');
   k_Gz_b = ones(nx+1, ny, nz, 'single');
   k_Hy_a = ones(nx, ny, nz, 'single');
   k_Hy_b = ones(nx, ny, nz, 'single')/(2.0*epsilon0);
   k_Hx_c = ones(nx+1, ny, nz, 'single')*2.0*epsilon0/mu0;
   k_Hx_d = ones(nx+1, ny, nz, 'single')*(-2.0*epsilon0/mu0);
   k_Bz_a = ones(nx, ny, nz, 'single');
   k_Bz_b = ones(nx, ny, nz, 'single')*dt;
   k_Gx_a = ones(nx, ny+1, nz, 'single');
   k_Gx_b = ones(nx, ny+1, nz, 'single');
   k_Ey_c = ones(nx, ny, nz, 'single')*2.0*epsilon0;
   k_Ey_d = ones(nx, ny, nz, 'single')*(-2.0*epsilon0);
   k_Ez_a = ones(nx, ny+1, nz, 'single');
   k_Ez_b = ones(nx, ny+1, nz, 'single')/(2.0*epsilon0);
   k_Bx_a = ones(nx, ny, nz, 'single');
   k_Bx_b = ones(nx, ny, nz, 'single')*dt;
   k_Hy_c = ones(nx, ny+1, nz, 'single')*2.0*epsilon0/mu0;
   k_Hy_d = ones(nx, ny+1, nz, 'single')*(-2.0*epsilon0/mu0);
   k_Hz_a = ones(nx, ny, nz, 'single');
   k_Hz_b = ones(nx, ny, nz, 'single')/(2.0*epsilon0);
   k_Ex_a = ones(nx, ny, nz+1, 'single');
   k_Ex_b = ones(nx, ny, nz+1, 'single')/(2.0*epsilon0);
   k_Gy_a = ones(nx, ny, nz+1, 'single');
   k_Gy_b = ones(nx, ny, nz+1, 'single');
   k_Ez_c = ones(nx, ny, nz, 'single')*2.0*epsilon0;
   k_Ez_d = ones(nx, ny, nz, 'single')*(-2.0*epsilon0);
   k_Hx_a = ones(nx, ny, nz, 'single');
   k_Hx_b = ones(nx, ny, nz, 'single')/(2.0*epsilon0);
   k_By_a = ones(nx, ny, nz, 'single');
   k_By_b = ones(nx, ny, nz, 'single')*dt;
   k_Hz_c = ones(nx, ny, nz+1, 'single')*2.0*epsilon0/mu0;
   k_Hz_d = ones(nx, ny, nz+1, 'single')*(-2.0*epsilon0/mu0);

%% General FDTD coefficients
   I = 1:number_of_materials;
   K_a(I) = (2.0*epsilon0*Material(I,1) - Material(I,3)*dt)./...
            (2.0*epsilon0*Material(I,1) + Material(I,3)*dt);
   K_b(I) = 2.0*dt./(2.0*epsilon0*Material(I,1) + Material(I,3)*dt);
   K_c(I) = Material(I,2);
   Ka = single(K_a(Index)); Kb = single(K_b(Index)); Kc = single(K_c(Index));

%% PML coefficients along x-axis
   sigma_max = -(m + 1.0)*log(R_err)/(2.0*eta*PML*dx);
   for I=0:(PML-1)
        sigma_x = sigma_max*((PML - I)/PML)^m;
        ka_x = 1.0 + (ka_max - 1.0)*((PML - I)/PML)^m;
        k_Ey_a(I+1,:,:) = (2.0*epsilon0*ka_x - sigma_x*dt)/...
                          (2.0*epsilon0*ka_x + sigma_x*dt);
        k_Ey_a(nx-I,:,:) = k_Ey_a(I+1,:,:);
        k_Ey_b(I+1,:,:) = 1.0/(2.0*epsilon0*ka_x + sigma_x*dt);
        k_Ey_b(nx-I,:,:) = k_Ey_b(I+1,:,:);
        k_Gz_a(I+1,:,:) = (2.0*epsilon0*ka_x - sigma_x*dt)/...
                          (2.0*epsilon0*ka_x + sigma_x*dt);
        k_Gz_a(nx-I,:,:) = k_Gz_a(I+1,:,:);
        k_Gz_b(I+1,:,:) = 2.0*epsilon0/(2.0*epsilon0*ka_x + sigma_x*dt);
        k_Gz_b(nx-I,:,:) = k_Gz_b(I+1,:,:);
        k_Hx_c(I+1,:,:) = (2.0*epsilon0*ka_x + sigma_x*dt)/mu0;
        k_Hx_c(nx-I,:,:) = k_Hx_c(I+1,:,:);
        k_Hx_d(I+1,:,:) = -(2.0*epsilon0*ka_x - sigma_x*dt)/mu0;
        k_Hx_d(nx-I,:,:) = k_Hx_d(I+1,:,:);

        sigma_x = sigma_max*((PML - I - 0.5)/PML)^m;
        ka_x = 1.0 + (ka_max - 1.0)*((PML - I - 0.5)/PML)^m;
        k_Ex_c(I+1,:,:) = 2.0*epsilon0*ka_x + sigma_x*dt;
        k_Ex_c(nx-I-1,:,:) = k_Ex_c(I+1,:,:);
        k_Ex_d(I+1,:,:) = -(2.0*epsilon0*ka_x - sigma_x*dt);
        k_Ex_d(nx-I-1,:,:) = k_Ex_d(I+1,:,:);
        k_Hy_a(I+1,:,:) = (2.0*epsilon0*ka_x - sigma_x*dt)/...
                          (2.0*epsilon0*ka_x + sigma_x*dt);
        k_Hy_a(nx-I-1,:,:) = k_Hy_a(I+1,:,:);
        k_Hy_b(I+1,:,:) = 1.0/(2.0*epsilon0*ka_x + sigma_x*dt);
        k_Hy_b(nx-I-1,:,:) = k_Hy_b(I+1,:,:);
        k_Bz_a(I+1,:,:) = (2.0*epsilon0*ka_x - sigma_x*dt)/...
                          (2.0*epsilon0*ka_x + sigma_x*dt);
        k_Bz_a(nx-I-1,:,:) = k_Bz_a(I+1,:,:);
        k_Bz_b(I+1,:,:) = 2.0*epsilon0*dt/(2.0*epsilon0*ka_x + sigma_x*dt);
        k_Bz_b(nx-I-1,:,:) = k_Bz_b(I+1,:,:);
   end

%% PML coefficients along y-axis
   sigma_max = -(m + 1.0)*log(R_err)/(2.0*eta*PML*dy);
   for J=0:(PML-1)
        sigma_y = sigma_max*((PML - J)/PML)^m;
        ka_y = 1.0 + (ka_max - 1.0)*((PML - J)/PML)^m;
        k_Gx_a(:,J+1,:) = (2.0*epsilon0*ka_y - sigma_y*dt)/...
                          (2.0*epsilon0*ka_y + sigma_y*dt);
        k_Gx_a(:,ny-J,:) = k_Gx_a(:,J+1,:);
        k_Gx_b(:,J+1,:) = 2.0*epsilon0/(2.0*epsilon0*ka_y + sigma_y*dt);
        k_Gx_b(:,ny-J,:) = k_Gx_b(:,J+1,:);
        k_Ez_a(:,J+1,:) = (2.0*epsilon0*ka_y - sigma_y*dt)/...
                          (2.0*epsilon0*ka_y + sigma_y*dt);
        k_Ez_a(:,ny-J,:) = k_Ez_a(:,J+1,:);
        k_Ez_b(:,J+1,:) = 1.0/(2.0*epsilon0*ka_y + sigma_y*dt);
        k_Ez_b(:,ny-J,:) = k_Ez_b(:,J+1,:);
        k_Hy_c(:,J+1,:) = (2.0*epsilon0*ka_y + sigma_y*dt)/mu0;
        k_Hy_c(:,ny-J,:) = k_Hy_c(:,J+1,:);
        k_Hy_d(:,J+1,:) = -(2.0*epsilon0*ka_y - sigma_y*dt)/mu0;
        k_Hy_d(:,ny-J,:) = k_Hy_d(:,J+1,:);

        sigma_y = sigma_max*((PML - J - 0.5)/PML)^m;
        ka_y = 1.0 + (ka_max - 1.0)*((PML - J - 0.5)/PML)^m;
        k_Ey_c(:,J+1,:) = 2.0*epsilon0*ka_y+sigma_y*dt;
        k_Ey_c(:,ny-J-1,:) = k_Ey_c(:,J+1,:);
        k_Ey_d(:,J+1,:) = -(2.0*epsilon0*ka_y-sigma_y*dt);
        k_Ey_d(:,ny-J-1,:) = k_Ey_d(:,J+1,:);
        k_Bx_a(:,J+1,:) = (2.0*epsilon0*ka_y-sigma_y*dt)/...
                          (2.0*epsilon0*ka_y+sigma_y*dt);
        k_Bx_a(:,ny-J-1,:) = k_Bx_a(:,J+1,:);
        k_Bx_b(:,J+1,:) = 2.0*epsilon0*dt/(2.0*epsilon0*ka_y+sigma_y*dt);
        k_Bx_b(:,ny-J-1,:) = k_Bx_b(:,J+1,:);
        k_Hz_a(:,J+1,:) = (2.0*epsilon0*ka_y-sigma_y*dt)/...
                          (2.0*epsilon0*ka_y+sigma_y*dt);
        k_Hz_a(:,ny-J-1,:) = k_Hz_a(:,J+1,:);
        k_Hz_b(:,J+1,:) = 1.0/(2.0*epsilon0*ka_y+sigma_y*dt);
        k_Hz_b(:,ny-J-1,:) = k_Hz_b(:,J+1,:);
   end

%% PML coefficients along z-axis
   sigma_max = -(m + 1.0)*log(R_err)/(2.0*eta*PML*dz);
   for K=0:(PML-1)
        sigma_z = sigma_max*((PML - K)/PML)^m;
        ka_z = 1.0 + (ka_max - 1.0)*((PML-K)/PML)^m;
        k_Ex_a(:,:,K+1) = (2.0*epsilon0*ka_z - sigma_z*dt)/...
                          (2.0*epsilon0*ka_z + sigma_z*dt);
        k_Ex_a(:,:,nz-K) = k_Ex_a(:,:,K+1);
        k_Ex_b(:,:,K+1) = 1.0/(2.0*epsilon0*ka_z + sigma_z*dt);
        k_Ex_b(:,:,nz-K) = k_Ex_b(:,:,K+1);
        k_Gy_a(:,:,K+1) = (2.0*epsilon0*ka_z - sigma_z*dt)/...
                          (2.0*epsilon0*ka_z + sigma_z*dt);
        k_Gy_a(:,:,nz-K) = k_Gy_a(:,:,K+1);
        k_Gy_b(:,:,K+1) = 2.0*epsilon0/(2.0*epsilon0*ka_z + sigma_z*dt);
        k_Gy_b(:,:,nz-K) = k_Gy_b(:,:,K+1);
        k_Hz_c(:,:,K+1) = (2.0*epsilon0*ka_z + sigma_z*dt)/mu0;
        k_Hz_c(:,:,nz-K) = k_Hz_c(:,:,K+1);
        k_Hz_d(:,:,K+1) = -(2.0*epsilon0*ka_z - sigma_z*dt)/mu0;
        k_Hz_d(:,:,nz-K) = k_Hz_d(:,:,K+1);

        sigma_z = sigma_max*((PML - K - 0.5)/PML)^m;
        ka_z = 1.0 + (ka_max - 1.0)*((PML - K - 0.5)/PML)^m;
        k_Ez_c(:,:,K+1) = 2.0*epsilon0*ka_z + sigma_z*dt;
        k_Ez_c(:,:,nz-K-1) = k_Ez_c(:,:,K+1);
        k_Ez_d(:,:,K+1) = -(2.0*epsilon0*ka_z - sigma_z*dt);
        k_Ez_d(:,:,nz-K-1) = k_Ez_d(:,:,K+1);
        k_Hx_a(:,:,K+1) = (2.0*epsilon0*ka_z - sigma_z*dt)/...
                          (2.0*epsilon0*ka_z + sigma_z*dt);
        k_Hx_a(:,:,nz-K-1) = k_Hx_a(:,:,K+1);
        k_Hx_b(:,:,K+1) = 1.0/(2.0*epsilon0*ka_z + sigma_z*dt);
        k_Hx_b(:,:,nz-K-1) = k_Hx_b(:,:,K+1);
        k_By_a(:,:,K+1) = (2.0*epsilon0*ka_z - sigma_z*dt)/...
                          (2.0*epsilon0*ka_z + sigma_z*dt);
        k_By_a(:,:,nz-K-1) = k_By_a(:,:,K+1);
        k_By_b(:,:,K+1) = 2.0*epsilon0*dt/(2.0*epsilon0*ka_z + sigma_z*dt);
        k_By_b(:,:,nz-K-1) = k_By_b(:,:,K+1);
   end

%% Main 3D FDTD+UPML routine (operates with 'singles' to increase speed)
   hhh = waitbar(0, 'Calculations in progress...');
   tic;
   for T=0:(number_of_iterations-1)
        %% Calculate Fx -> Gx -> Ex
        I = 1:nx; J = 2:ny; K = 2:nz;
        Fx_r = Fx(I,J,K);
        Fx(I,J,K) = Ka(I,J,K).*Fx(I,J,K) + Kb(I,J,K).*...
                    ((Hz(I,J,K) - Hz(I,J-1,K))/dy - (Hy(I,J,K) - Hy(I,J,K-1))/dz);
        Gx_r = Gx(I,J,K);
        Gx(I,J,K) = k_Gx_a(I,J,K).*Gx(I,J,K) + k_Gx_b(I,J,K).*(Fx(I,J,K) - Fx_r);
        Ex(I,J,K) = k_Ex_a(I,J,K).*Ex(I,J,K) + k_Ex_b(I,J,K).*...
                    (k_Ex_c(I,J,K).*Gx(I,J,K) + k_Ex_d(I,J,K).*Gx_r);

        %% Calculate Fy -> Gy -> Ey
        I = 2:nx; J = 1:ny; K = 2:nz;
        Fy_r = Fy(I,J,K);
        Fy(I,J,K) = Ka(I,J,K).*Fy(I,J,K) + Kb(I,J,K).*...
                    ((Hx(I,J,K) - Hx(I,J,K-1))/dz - (Hz(I,J,K) - Hz(I-1,J,K))/dx);
        Gy_r = Gy(I,J,K);
        Gy(I,J,K) = k_Gy_a(I,J,K).*Gy(I,J,K) + k_Gy_b(I,J,K).*(Fy(I,J,K) - Fy_r);
        Ey(I,J,K) = k_Ey_a(I,J,K).*Ey(I,J,K) + k_Ey_b(I,J,K).*...
                    (k_Ey_c(I,J,K).*Gy(I,J,K) + k_Ey_d(I,J,K).*Gy_r);

        %% Calculate Fz -> Gz -> Ez
        I = 2:nx; J = 2:ny; K = 1:nz;
        Fz_r = Fz(I,J,K);
        Fz(I,J,K) = Ka(I,J,K).*Fz(I,J,K) + Kb(I,J,K).*...
                    ((Hy(I,J,K) - Hy(I-1,J,K))/dx - (Hx(I,J,K) - Hx(I,J-1,K))/dy);
        Gz_r = Gz(I,J,K);
        Gz(I,J,K) = k_Gz_a(I,J,K).*Gz(I,J,K) + k_Gz_b(I,J,K).*(Fz(I,J,K) - Fz_r);
        Ez(I,J,K) = k_Ez_a(I,J,K).*Ez(I,J,K) + k_Ez_b(I,J,K).*...
                    (k_Ez_c(I,J,K).*Gz(I,J,K) + k_Ez_d(I,J,K).*Gz_r);

        %% Source of vertical electric field Ez applied to the whole face
        %% plane at the port 1
        if (T*dt<=10.0*t_half)
            Ez((nx/2-10):(nx/2-5), PML+2, (PML+2):(PML+4)) = Source(t_half, 1.0, T*dt);
        end

        %% Save reflected Ez at port 1, passed through Ez at port 2 and Ez
        %% distribution between electrodes
        Incident(T+1) = Source(t_half, 1.0, T*dt);
        Reflected(T+1) = Ez(nx/2-7, PML+2, PML+3) - Incident(T+1);
        Passed(T+1) = Ez(nx/2+7, ny-PML-1, PML+3);
        Ez_saved(1:(ny-2*PML-1), 1:(nx-2*PML-1), T+1) = ...
                Ez((PML+1):(nx-PML-1), (PML+1):(ny-PML-1), PML+3)';

        %% Calculate Bx -> Hx
        I = 2:nx; J = 1:ny; K = 1:nz;
        Bx_r = Bx(I,J,K);
        Bx(I,J,K) = k_Bx_a(I,J,K).*Bx(I,J,K) + k_Bx_b(I,J,K).*...
                    ((Ey(I,J,K+1) - Ey(I,J,K))/dz - (Ez(I,J+1,K) - Ez(I,J,K))/dy);
        Hx(I,J,K) = k_Hx_a(I,J,K).*Hx(I,J,K) + k_Hx_b(I,J,K).*...
                    (k_Hx_c(I,J,K).*Bx(I,J,K) + k_Hx_d(I,J,K).*Bx_r)./Kc(I,J,K);

        %% Calculate By -> Hy
        I = 1:nx; J = 2:ny; K = 1:nz;
        By_r = By(I,J,K);
        By(I,J,K) = k_By_a(I,J,K).*By(I,J,K) + k_By_b(I,J,K).*...
                    ((Ez(I+1,J,K) - Ez(I,J,K))/dx - (Ex(I,J,K+1) - Ex(I,J,K))/dz);
        Hy(I,J,K) = k_Hy_a(I,J,K).*Hy(I,J,K) + k_Hy_b(I,J,K).*...
                    (k_Hy_c(I,J,K).*By(I,J,K) + k_Hy_d(I,J,K).*By_r)./Kc(I,J,K);

        %% Calculate Bz -> Hz
        I = 1:nx; J = 1:ny; K = 2:nz;
        Bz_r = Bz(I,J,K);
        Bz(I,J,K) = k_Bz_a(I,J,K).*Bz(I,J,K) + k_Bz_b(I,J,K).*...
                    ((Ex(I,J+1,K) - Ex(I,J,K))/dy - (Ey(I+1,J,K) - Ey(I,J,K))/dx);
        Hz(I,J,K) = k_Hz_a(I,J,K).*Hz(I,J,K) + k_Hz_b(I,J,K).*...
                    (k_Hz_c(I,J,K).*Bz(I,J,K) + k_Hz_d(I,J,K).*Bz_r)./Kc(I,J,K);

        %% Progress bar updates at every time percent
        if ( mod(T, ceil(number_of_iterations/100)) == 0 )
            waitbar((T+1)/number_of_iterations, hhh);
        end

    end
    toc
    close(hhh);

%% Plots: signals, scattering parameters and Ez field between plates
   figure('units','normalized','outerposition',[0 0 1 1]);
   set(gcf, 'doublebuffer', 'on');
   % Input signal, reflected (at port 1) and passed through (port 2)
     subplot(2,2,1);
     plot(1e9*dt*(0:T), Incident, 'k-', 1e9*dt*(0:T), Reflected, 'r-', 1e9*dt*(0:T), Passed, 'b-', 'LineWidth', 2);
     title('Input, reflected (Port 1) and passed (Port 2) signals', 'FontSize', 18);
     xlabel('Time, [ns]', 'FontSize', 16);
     ylabel('Strength, [V/cm]', 'FontSize', 16);
     legend('Incident (Port 1)' ,'Reflected (Port 1)', 'Passed (Port 2)');
     grid on;
   % |S_11| and |S_21|
     NFFT = 2^nextpow2(T);
     S_11 = fft(Reflected, NFFT)./fft(Incident, NFFT);
     S_21 = fft(Passed, NFFT)./fft(Incident, NFFT);
     subplot(2,2,3);
     f = (0.5/dt)*linspace(0, 1, NFFT/2);
     plot(f*1e-9, 20*log10(abs(S_11(1:NFFT/2))), 'r', ...
          f*1e-9, 20*log10(abs(S_21(1:NFFT/2))), 'b', 'LineWidth', 2);
     title('Scattering parameters - |S_{11}| and |S_{21}|', 'FontSize', 18);
     xlabel('Frequency, [GHz]', 'FontSize', 16);
     ylabel('Magnitude, [dB]', 'FontSize', 16);
     legend('Reflected (Port 1)', 'Passed (Port 2)', 'Location', 'SouthEast');
     xlim([0 20]);
     grid on;
   % Electric field strength Ez between electrodes
     for T=1:20:number_of_iterations
         subplot(2,2,[2 4]);
         contour(1e3*dx*(1:(nx-2*PML-1)), 1e3*dy*(1:(ny-2*PML-1)), ...
         Index((PML+1):(nx-PML-1), (PML+1):(ny-PML-1), PML+5)', 1);
         hold on;
         subplot(2,2,[2 4]);
         pcolor(1e3*dx*(1:(nx-2*PML-1)), 1e3*dy*(1:(ny-2*PML-1)), double(Ez_saved(:, :, T)));
         title(['Time t = ', num2str(round(T*dt*1e12)),' ps'], 'FontSize', 18);
         xlabel('[mm]', 'FontSize', 16);
         ylabel('[mm]', 'FontSize', 16);
         shading interp;
         axis image;
         caxis([-1 1]);
         colorbar;
         drawnow;
     end

%% Gauss function for voltage source
function [res] = Source(t_half, amplitude, t)
% Pulse delay
t0 = 3.0*t_half;
res = amplitude*exp(-0.5*((t-t0)/(t_half/2.35482))^2.0);


function tapas_hgf_binary_mab_plotTraj(r)
% Plots the estimated or generated trajectories for the binary HGF perceptual model for multi-armed
% bandit situations.
%
% Usage example:  est = tapas_fitModel(responses, inputs); tapas_hgf_binary_plotTraj(est);
%
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2013 Christoph Mathys, TNU, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

% Optional plotting of standard deviations (true or false)
plotsd = true;

% Optional plotting of responses (true or false)
ploty = true;

% Set up display
scrsz = get(0,'screenSize');
outerpos = [0.2*scrsz(3),0.2*scrsz(4),0.8*scrsz(3),0.8*scrsz(4)];
figure(...
    'OuterPosition', outerpos,...
    'Name', 'HGF trajectories');

% Set up colors
colors = [1 0 0; 0.67 0 1; 0 0.67 1; 0.67 1 0];

% Number of bandits
b = r.c_prc.n_bandits;

% Number of trials
n = size(r.u,1);

% Time axis
if size(r.u,2) > 1
    t = r.u(:,end)';
else
    t = ones(1,n);
end

ts = cumsum(t);
ts = [0, ts];

% Number of levels
try
    l = r.c_prc.n_levels;
catch
    l = (length(r.p_prc.p)+1)/5;
end

% Upper levels
for j = 1:l-2

    % Subplots
    subplot(l,1,j);

    if plotsd == true
        upperprior = r.p_prc.mu_0(l-j+1) +sqrt(r.p_prc.sa_0(l-j+1));
        lowerprior = r.p_prc.mu_0(l-j+1) -sqrt(r.p_prc.sa_0(l-j+1));
        upper = [upperprior; r.traj.mu(:,l-j+1,1)+sqrt(r.traj.sa(:,l-j+1,1))];
        lower = [lowerprior; r.traj.mu(:,l-j+1,1)-sqrt(r.traj.sa(:,l-j+1,1))];

        plot(0, upperprior, 'ob', 'LineWidth', 1);
        hold all;
        plot(0, lowerprior, 'ob', 'LineWidth', 1);
        fill([ts, fliplr(ts)], [(upper)', fliplr((lower)')], ...
             'b', 'EdgeAlpha', 0, 'FaceAlpha', 0.15);
    end
    plot(ts, [r.p_prc.mu_0(l-j+1); r.traj.mu(:,l-j+1,1)], 'b', 'LineWidth', 2);
    hold all;
    plot(0, r.p_prc.mu_0(l-j+1), 'ob', 'LineWidth', 2); % prior
    xlim([0 ts(end)]);
    title(['Posterior expectation of x_' num2str(l-j+1)], 'FontWeight', 'bold');
    ylabel(['\mu_', num2str(l-j+1)]);
end

% Second level
subplot(l,1,l-1)

if plotsd == true
    for j=1:b
        upperprior = r.p_prc.mu_0(2) +sqrt(r.p_prc.sa_0(2));
        lowerprior = r.p_prc.mu_0(2) -sqrt(r.p_prc.sa_0(2));
        upper = [upperprior; r.traj.mu(:,2,j)+sqrt(r.traj.sa(:,2,j))];
        lower = [lowerprior; r.traj.mu(:,2,j)-sqrt(r.traj.sa(:,2,j))];

        plot(0, upperprior, 'o', 'Color', colors(j,:), 'LineWidth', 1);
        hold all;
        plot(0, lowerprior, 'o', 'Color', colors(j,:), 'LineWidth', 1);
        fill([ts, fliplr(ts)], [(upper)', fliplr((lower)')], ...
             colors(j,:), 'EdgeAlpha', 0, 'FaceAlpha', 0.15);
    end
end
for j=1:b
    plot(ts, [r.p_prc.mu_0(1); r.traj.mu(:,2,j)], 'Color', colors(j,:), 'LineWidth', 2);
    hold all;
    plot(0, r.p_prc.mu_0(1), 'o', 'Color', colors(j,:), 'LineWidth', 2); % prior
end
xlim([0 ts(end)]);
title('Posterior expectations of x_2', 'FontWeight', 'bold');
ylabel('\mu_2');

% Input level
subplot(l,1,l);

for j=1:b
    plot(ts, [tapas_sgm(r.p_prc.mu_0(2), 1); tapas_sgm(r.traj.mu(:,2,j), 1)], 'Color', colors(j,:), 'LineWidth', 2);
    hold all;
    plot(0, tapas_sgm(r.p_prc.mu_0(2), 1), 'o', 'Color', colors(j,:), 'LineWidth', 2); % prior
end
plot(ts(2:end), r.u(:,1), '.', 'Color', [0 0 0]); % inputs
plot(ts(2:end), r.traj.wt(:,1), 'k') % implied learning rate
if (ploty == true) && ~isempty(find(strcmp(fieldnames(r),'y'))) && ~isempty(r.y)
    y = r.y(:,1);
    if ~isempty(find(strcmp(fieldnames(r),'irr')))
        y(r.irr) = NaN; % weed out irregular responses
        plot(ts(r.irr)+1,  1.08.*ones([1 length(r.irr)]), 'x', 'Color', [1 0.7 0], 'Markersize', 11, 'LineWidth', 2); % irregular responses
    end
    for j=1:b
        plot(find(y==j), 1.08*ones([1 length(find(y==j))]), '.', 'Color', colors(j,:)); % responses
    end
    title(['Response y, input u (black dots), learning rate (fine black line), and posterior expectation of reward s(\mu_2) ', ...
           '(colour coded) for \rho=', num2str(r.p_prc.rho(2:end)), ', \kappa=', ...
           num2str(r.p_prc.ka(2:end)), ', \omega=', num2str(r.p_prc.om(2:end))], ...
      'FontWeight', 'bold');
    ylabel('y, u, s(\mu_2)');
    axis([0 ts(end) -0.15 1.15]);
else
    title(['Input u (black dots), learning rate (fine black line), and posterior expectation of input s(\mu_2) ', ...
           '(red) for \rho=', num2str(r.p_prc.rho(2:end)), ', \kappa=', ...
           num2str(r.p_prc.ka(2:end)), ', \omega=', num2str(r.p_prc.om(2:end))], ...
      'FontWeight', 'bold');
    ylabel('u, s(\mu_2)');
    axis([0 ts(end) -0.1 1.1]);
end
plot(ts(2:end), 0.5, 'k');
xlabel('Trial number');
hold off;


function [ SparsityMatrix ] = sparsity_grid( x, side, width, width_end)
%SIMILARITYNEIGHBOR Summary of this function goes here
%   Detailed explanation goes here

    % this assumes that the patch is laid out with first column, then second
    % column, ... final column (column major)

    SimilarityMatrix = zeros(side*side);
    for i=1:width
        SimilarityMatrix = (similarity_neighbor_grid_further(x, side, [1,2,3,4], i) | SimilarityMatrix);
    end

    SimilarityMatrix_end = zeros(side*side);
    for i=1:width_end
        SimilarityMatrix_end = (similarity_neighbor_grid_further(x, side, [1,2,3,4], i) | SimilarityMatrix_end);
    end

    SparsityMatrix = double(SimilarityMatrix_end & (~SimilarityMatrix));

    assert(isequal(SparsityMatrix, SparsityMatrix'));
end


function vscl = vscale( f )
%VSCALE   Estimate the vertical scale of a function.
%   VSCALE(F) estimates the vertical scale (also known as the dynamical range)
%   of a function. This is required because a CHEBTECH does not store its
%   interpolation data. If F is an array-valued CHEBTECH with K columns, then
%   the result is a row vector of length K.

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

% Get the coefficients:
c = f.coeffs;

% Check isempty:
if ( isempty( c ) )
    vscl = 0;
elseif ( size(c, 1) == 1 )
    vscl = abs(c);
else
    % Compute values:
    vals = f.coeffs2vals( c );
    % Take max:
    vscl = max(abs(vals), [], 1);
end

end


classdef LevelSetSphere < LevelSetSphereNdim

    methods (Access = public)

        function obj = LevelSetSphere(cParams)
            obj.fracRadius = cParams.fracRadius;
            obj.compute(cParams);
        end
    end

    methods (Access = protected)
        function computeLevelSetValue(obj)
            ls = obj.dist - 1;
            obj.levelSet = ls;
        end
    end

end


%GM_PHD_Predict_Birth
%Last modified 2nd September 2013
%Matlab code by Bryan Clarke b.clarke@acfr.usyd.edu.au

%This file performs prediction for newly birthed and spawned targets
%This is necessary since their positions were initialised in a previous timestep and they may
%have moved between then and now
%We iterate through j = 1..J_b,k where J_b,k is number of birthed landmarks
%at time k (but the landmarks correspond to the measurement from time k-1)
%For this implementation, birthed and spawned targets are identical except
%they have weights that are calculated from different functions, and
%different starting covariances. A target is spawned or birthed depending
%on which weighting function will give it a higher starting weight.

%The means of these will be the position in Cartesian space where they are detected
%The covariances & weights are calculated according to Vo&Ma
s = sprintf('Step 1: Prediction for birthed and spawned targets.');
disp(s);

m_birth_before_prediction = [m_birth, m_spawn]; %Need to store these BEFORE prediction for use in the update step.

%Perform prediction for birthed targets using birthed velocities.
for j = 1:numBirthedTargets
    i = i + 1;
    %w_birth was already instantiated in GM_PHD_Create_Birth
    m_birth(:,j) = F * m_birth(:,j);
    P_range = calculateDataRange4(j);
    P_birth(:,P_range) = Q + F * P_birth(:,P_range) * F';
end
%Perform prediction for birthed targets using birthed velocities.
for j = 1:numSpawnedTargets
    i = i + 1;
    %w_birth was already instantiated in GM_PHD_Create_Birth
    m_spawn(:,j) = F * m_spawn(:,j);
    P_range = calculateDataRange4(j);
    P_spawn(:,P_range) = Q + F * P_spawn(:,P_range) * F';
end

if(VERBOSE == 1)
  for j = 1:numBirthedTargets
        thisM = m_birth(:,j);
        s = sprintf('Birthed target %d: %3.4f %3.4f %3.4f %3.4f Weight %3.9f', j, thisM(1), thisM(2), thisM(3), thisM(4), w_birth(j));
        disp(s);
  end
  for j = 1:numSpawnedTargets
        thisM = m_spawn(:,j);
        s = sprintf('Spawned target %d: %3.4f %3.4f %3.4f %3.4f Weight %3.9f', j, thisM(1), thisM(2), thisM(3), thisM(4), w_birth(j));
        disp(s);
   end
end


function SubOffspring = CreateOff(Problem,Population,SubPopulation,RMP)

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

    %% Parent selection
    Parent11 = [];
    Parent21 = [];
    Parent12 = [];
    Parent22 = [];
    for i = 1 : floor(length(Population)/2)
        P1  = Population(i);
        P2  = Population(i+floor(length(Population)/2));
        rmp = RMP(P1.dec(end),P2.dec(end));
        if (P1.dec(end) == P2.dec(end)) || (rand<rmp)
            Parent11 = [Parent11,P1];
            Parent21 = [Parent21,P2];
        else
            Parent12 = [Parent12,P1,P2];
            Parent22 = [Parent22,SubPopulation{P1.dec(end)}(randi(end)),SubPopulation{P2.dec(end)}(randi(end))];
        end
    end

    %% Offspring generation
    if ~isempty(Parent11)
        Parent1Dec     = Parent11.decs;
        Parent2Dec     = Parent21.decs;
        OffDec1        = OperatorGA(Problem,[Parent1Dec;Parent2Dec]);
        OffDec1(:,end) = [Parent1Dec(:,end);Parent2Dec(:,end)];
    else
        OffDec1 = [];
    end
    if ~isempty(Parent12)
        Parent1Dec     = Parent12.decs;
        Parent2Dec     = Parent22.decs;
        OffDec2        = OperatorGAhalf(Problem,[Parent1Dec;Parent2Dec]);
        OffDec2(:,end) = Parent1Dec(:,end);
    else
        OffDec2 = [];
    end
    SubOffspring = Divide(Problem.Evaluation([OffDec1;OffDec2]),length(Problem.SubD));
end


function [y] = symextend(x,Nnum)

y(:,1:Nnum) = fliplr(x(:,1:Nnum));
y = [fliplr(x(:,1:Nnum)) x x(:,end:-1:end-Nnum+1)];
y = [flipud(y(1:Nnum,:)); y ;y(end:-1:end-Nnum+1,:)];


function  p = updateboundsfromupper(p,upper)
if nargin == 1
    upper = p.upper;
end
if ~isinf(upper)
    LU = [p.lb p.ub];
    if nnz(p.c.*(p.ub-p.lb)) == 1 & nnz(p.Q)==0
        i = find(p.c.*(p.ub-p.lb));
        if p.c(i) > 0
            % We are minimizing x(i), since an upper bound is UPPER
            % this means c(i)*x(i) has to be < UPPER in optimal solution
            p.ub(i) = min([p.ub(i) upper/p.c(i)]);
        elseif p.c(i) < 0
            % We are maximizing x(i), since an lower bound is -UPPER
            % this means x(i) has to be > -UPPER in optimal solution
            p.lb(i) = max([p.lb(i) -upper/abs(p.c(i))]);
        end

    end
    if ~isempty(p.bilinears) & nnz(p.Q)==0
        quad_v = find(p.bilinears(:,2) == p.bilinears(:,3));
        quad_x = p.bilinears(quad_v,2);
        quad_v = p.bilinears(quad_v,1);
        i = find(p.c(quad_v)>0);
        quad_v = quad_v(i);
        quad_x = quad_x(i);
        if ~isempty(quad_v) & ~any(isinf(p.lb(quad_x))) & ~any(isinf(p.ub(quad_x)))
            % x'*D*x + c'*x + f + h(x) < U
            D = diag(p.c(quad_v));
            if all(diag(D)>0)
                c = p.c(quad_x);
                h = p.c;
                h(quad_x) = 0;
                h(quad_v) = 0;
                % Complete
                % (x + D^-0.5*c/2)'*D*(x + D^-0.5*c/2) - c'*D*c/4 + f + h(x) < U
                xc = -(D^-1)*c/2;
                rhs = upper - p.f - (h(h<0)'*p.ub(h<0) + h(h>=0)'*p.lb(h>=0)) + xc'*D*xc;
                if rhs>0
                    D = D/rhs;
                    % (x-xc)'*D*(x-xc) <= 1
                    for i = 1:length(quad_x)
                        p.lb(quad_x(i)) = max(p.lb(quad_x(i)),xc(i) - 1/sqrt(D(i,i)));
                        p.ub(quad_x(i)) = min(p.ub(quad_x(i)),xc(i) + 1/sqrt(D(i,i)));
                    end
                end
            end
        end
    end
    if ~isequal(LU,[p.lb p.ub])
        p.changedbounds = 1;
    end

    % Some initial code for using inverse objective to derive bounds.
    if nnz(p.Q)==0 && nnz(p.c)==1
        [pos,~,val] = find(p.c);
        if val == -1
            fi = find(p.evalVariables == pos);
            if ~isempty(fi)
                % We're maximizing f(x)
                if ~isempty(p.evalMap{fi}.properties.inverse)
                    if strcmp(p.evalMap{fi}.properties.definiteness,'positive')
                        if strcmp(p.evalMap{fi}.properties.monotonicity,'increasing')
                            if length(p.evalMap{fi}.arg)==2
                                lower = -upper;
                                p.lb(p.evalMap{fi}.variableIndex) = max([p.lb(p.evalMap{fi}.variableIndex) p.evalMap{fi}.properties.inverse(lower)]);
                            end
                        end
                    end
                end
            end
        end
        if val == 1
            fi = find(p.evalVariables == pos);
            if ~isempty(fi)
                % We're minimizing f(x)
                if ~isempty(p.evalMap{fi}.properties.inverse)
                    if strcmp(p.evalMap{fi}.properties.definiteness,'positive')
                        if strcmp(p.evalMap{fi}.properties.monotonicity,'increasing')
                            if length(p.evalMap{fi}.arg)==2
                                p.ub(p.evalMap{fi}.variableIndex) = min([p.ub(p.evalMap{fi}.variableIndex) p.evalMap{fi}.properties.inverse(upper)]);
                            end
                        end
                    end
                end
            end
        end
    end
    if any(p.lb > p.ub + 1e-7)
        p.feasible = 0;
    end
end


%UNDISTORT  Transforms an image to compensate for lens distortion
%
%     dst = cv.undistort(src, cameraMatrix, distCoeffs)
%     dst = cv.undistort(..., 'OptionName', optionValue, ...)
%
% ## Input
% * __src__ Input (distorted) image.
% * __cameraMatrix__ Input camera matrix `A = [fx 0 cx; 0 fy cy; 0 0 1]`.
% * __distCoeffs__ Input vector of distortion coefficients
%   `[k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,taux,tauy]` of 4, 5, 8, 12 or 14
%   elements. If the vector is empty, the zero distortion coefficients are
%   assumed.
%
% ## Output
% * __dst__ Output (corrected) image that has the same size and type as `src`.
%
% ## Options
% * __NewCameraMatrix__ Camera matrix of the distorted image. By default, it
%   is the same as `cameraMatrix` but you may additionally scale and shift the
%   result by using a different matrix. Not set by default
%
% The function transforms an image to compensate radial and tangential lens
% distortion.
%
% The function is simply a combination of cv.initUndistortRectifyMap (with
% unity `R`) and cv.remap (with bilinear interpolation). See the former
% function for details of the transformation being performed.
%
% Those pixels in the destination image, for which there is no correspondent
% pixels in the source image, are filled with zeros (black color).
%
% A particular subset of the source image that will be visible in the
% corrected image can be regulated by `NewCameraMatrix`. You can use
% cv.getOptimalNewCameraMatrix to compute the appropriate `NewCameraMatrix`
% depending on your requirements.
%
% The camera matrix and the distortion parameters can be determined using
% cv.calibrateCamera. If the resolution of images is different from the
% resolution used at the calibration stage, `fx`, `fy`, `cx` and `cy` need to
% be scaled accordingly, while the distortion coefficients remain the same.
%
% See also: cv.undistortPoints, cv.calibrateCamera,
%  cv.initUndistortRectifyMap, cv.remap, undistortImage
%


function g = mrdivide(f,c)
%/   Right scalar divide for BALLFUN objects.
%   X = B/A or X = mrdivide(B, A) is equivalent to X = B./A.
%
% See also MTIMES.

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

g = f*(1/c);
end


function [cmps2] = Gal2cmps2(Gal)
% Convert acceleration from galileos to centimeters per second-squared
% Chad A. Greene 2012
cmps2 = Gal;
end


function obj = replace_basis_set(obj, condition_num, xBF_hires)
% Replace a basis set in an fmri_model object with another one of your
% choosing.
%
% This allows one to use a custom basis set, and also to use different
% basis sets for different trial types.
%
% Each condition across all sessions must be modeled with the same basis
% set. That is, there can be only one basis set per condition, e.g., one
% for anticipation (used in each session) and one for pain.
%
% :Usage:
% ::
%
%     obj = replace_basis_set(obj, condition_num, xBF_hires)
%
% :Examples:
% ::
%
%    % generate a custom spline basis set and use that for Condition 1,
%    % and the standard one for Condition 2:
%
%    [xBF_hires, xBF] = fmri_spline_basis(2, 'length', 12, 'nbasis', 3, 'order', 3, 'plot');
%
%    %save this to get info that is not typically in basis set until after
%    %model is built.

oldBF = obj.xBF(1);

% SPM adds these things here, so we will too, for consistency
xBF_hires.T = oldBF.T;
xBF_hires.T0 = oldBF.T0;
xBF_hires.UNITS = oldBF.UNITS;
xBF_hires.Volterra = oldBF.Volterra;

obj.xBF(condition_num) = xBF_hires;

end


function [gX, kern] = pathKernGradSym(kern, X, X2)

% PATHKERNGRADSYM Gradient of the symetric PATH kernel's parameters.
% FORMAT
% DESC computes the gradient of functions with respect to the
% path
% kernel's parameters. As well as the kernel structure and the
% input positions, the user provides a matrix PARTIAL which gives
% the partial derivatives of the function with respect to the
% relevant elements of the kernel matrix.
% ARG kern : the kernel structure for which the gradients are being
% computed.
% ARG x : the input locations for which the gradients are being
% computed.
% ARG partial : matrix of partial derivatives of the function of
% interest with respect to the kernel matrix. The argument takes
% the form of a square matrix of dimension  numData, where numData is
% the number of rows in X.
% RETURN g : gradients of the function of interest with respect to
% the kernel parameters. The ordering of the vector should match
% that provided by the function kernExtractParam.
% RETURN kern : the updated kernel structure
%
% FORMAT
% DESC computes the derivatives as above, but input locations are
% now provided in two matrices associated with rows and columns of
% the kernel matrix.
% ARG kern : the kernel structure for which the gradients are being
% computed.
% ARG x1 : the input locations associated with the rows of the
% kernel matrix.
% ARG x2 : the input locations associated with the columns of the
% kernel matrix.
% ARG partial : matrix of partial derivatives of the function of
% interest with respect to the kernel matrix. The matrix should
% have the same number of rows as X1 and the same number of columns
% as X2 has rows.
% RETURN g : gradients of the function of interest with respect to
% the kernel parameters.
% RETURN kern : the updated kernel structure
%
% SEEALSO pathKernParamInit, kernGradient, pathKernDiagGradient
%
% COPYRIGHT : Andrea Baisero, Carl Henrik Ek, 2013

% SHEFFIELDML

maxl=max(cellfun(@(x)size(x,1),[X,X2]));
kern=pathKernUpdateWMat(kern,maxl);

num=length(X);
num2=length(X2);

gX=cell(num,num2);
for i=1:num
    for j=1:num2
        gX{i,j}=pathKernGradSymSeq(kern,X{i},X2{j});
    end
end

function gX = pathKernGradSymSeq(kern, x, x2)

l=size(x,1);
l2=size(x2,1);
dim=size(x,2);

t=kernGradX(kern.gkern,x,x2);
kw=kern.wmat(1:l,1:l2);

gX=zeros(size(x));
for i=1:l
    gX(i,:)=sum((kw(i,:)'*ones(1,dim)).*t(:,:,i));
end


seed = 0;
rand('state', seed);
randn('state', seed);

chars = ['a', 'c', 'g', 't'];
motif = 'accca';
motif_length = length(motif);
motif_code = zeros(1, motif_length);
for i=1:motif_length
  motif_code(i) = find(chars == motif(i));
end

[bnet_init, Qnodes, Fnodes, Onode] = mk_motif_hhmm('motif_length', length(motif));
%[bnet_init, Qnodes, Fnodes, Onode] = mk_motif_hhmm('motif_pattern', motif);
ss = bnet_init.nnodes_per_slice;

% We generate a training set by creating uniform sequences,
% and inserting a single motif at a random location.
ntrain = 100;
T = 20;
cases = cell(1, ntrain);

if 1
  % uniform background
  background_dist = normalise(ones(1, length(chars)));
end
if 0
  % use a constant background
  background_dist = zeros(1, length(chars));
  m = find(chars=='t');
  background_dist(m) = 1.0;
end
if 0
  % use a background skewed away from the motif
  p = 0.01; q = (1-(2*p))/2;
  background_dist = [p p q q];
end

unif_pos = normalise(ones(1, T-length(motif)));
cases = cell(1, ntrain);
data = zeros(1,T);
for i=1:ntrain
  data = sample_discrete(background_dist, 1, T);
  L = sample_discrete(unif_pos, 1, 1);
  data(L:L+length(motif)-1) = motif_code;
  cases{i} = cell(ss, T);
  cases{i}(Onode,:) = num2cell(data);
end
disp('sample training cases')
for i=1:5
  chars(cell2num(cases{i}(Onode,:)))
end

engine_init = hmm_inf_engine(bnet_init);

[bnet_learned, LL, engine_learned] = ...
    learn_params_dbn_em(engine_init, cases, 'max_iter', 100, 'thresh', 1e-2);
%			'anneal', 1, 'anneal_rate', 0.7);

% extract the learned motif profile
eclass = bnet_learned.equiv_class;
CPDO=struct(bnet_learned.CPD{eclass(Onode,1)});
fprintf('columns = chars, rows = states\n');
profile_learned = squeeze(CPDO.CPT(2,:,:))
[m,ndx] = max(profile_learned, [], 2);
map_motif_learned = chars(ndx)
back_learned = squeeze(CPDO.CPT(1,1,:))'
%map_back_learned = chars(argmax(back_learned))

CPDO_init = struct(bnet_init.CPD{eclass(Onode,1)});
profile_init = squeeze(CPDO_init.CPT(2,:,:));
back_init = squeeze(CPDO_init.CPT(1,1,:))';


function sgmga_product_weight_tests ( )

%****************************************************************************80
%
%% SGMGA_PRODUCT_WEIGHT_TESTS calls SGMGA_PRODUCT_WEIGHT_TEST.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 February 2010
%
%  Author:
%
%    John Burkardt
%
  addpath ( '../sandia_rules' );

  timestamp ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'SGMGA_PRODUCT_WEIGHT_TESTS\n' );
  fprintf ( 1, '  Call SGMGA_PRODUCT_WEIGHT_TEST with various arguments.\n' );

  dim_num = 2;
  order_1d = [ 3, 5 ]';
  order_nd = prod ( order_1d(1:dim_num) );
  rule = [ 1, 1 ]';
  np = [ 0, 0 ]';
  np_sum = sum ( np(1:dim_num) );
  p = [];
  sgmga_product_weight_test ( dim_num, order_1d, order_nd, rule, np, p );

  dim_num = 2;
  order_1d = [ 3, 7 ]';
  order_nd = prod ( order_1d(1:dim_num) );
  rule = [ 1, 5 ]';
  np = [ 0, 0 ]';
  np_sum = sum ( np(1:dim_num) );
  p = [];
  sgmga_product_weight_test ( dim_num, order_1d, order_nd, rule, np, p );

  dim_num = 2;
  order_1d = [ 3, 3 ]';
  order_nd = prod ( order_1d(1:dim_num) );
  rule = [ 3, 7 ]';
  np = [ 0, 0 ]';
  np_sum = sum ( np(1:dim_num) );
  p = [];
  sgmga_product_weight_test ( dim_num, order_1d, order_nd, rule, np, p );

  dim_num = 2;
  order_1d = [ 5, 5 ]';
  order_nd = prod ( order_1d(1:dim_num) );
  rule = [ 1, 8 ]';
  np = [ 0, 1 ]';
  np_sum = sum ( np(1:dim_num) );
  p(1,1) = 1.5;
  sgmga_product_weight_test ( dim_num, order_1d, order_nd, rule, np, p );

  dim_num = 2;
  order_1d = [ 5, 5 ]';
  order_nd = prod ( order_1d(1:dim_num) );
  rule = [ 2, 9 ]';
  np = [ 0, 2 ]';
  np_sum = sum ( np(1:dim_num) );
  p(1,1) = 0.5;
  p(2,1) = 1.5;
  sgmga_product_weight_test ( dim_num, order_1d, order_nd, rule, np, p );

  dim_num = 2;
  order_1d = [ 7, 9 ]';
  order_nd = prod ( order_1d(1:dim_num) );
  rule = [ 6, 10 ]';
  np = [ 1, 0 ]';
  np_sum = sum ( np(1:dim_num) );
  p(1,1) = 2.0;
  sgmga_product_weight_test ( dim_num, order_1d, order_nd, rule, np, p );

  dim_num = 3;
  order_1d = [ 2, 3, 3 ]';
  order_nd = prod ( order_1d(1:dim_num) );
  rule = [ 1, 4, 5 ]';
  np = [ 0, 0, 0 ]';
  np_sum = sum ( np(1:dim_num) );
  p = [];
  sgmga_product_weight_test ( dim_num, order_1d, order_nd, rule, np, p );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SGMGA_PRODUCT_WEIGHT_TESTS:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  fprintf ( 1, '\n' );
  timestamp ( );

  rmpath ( '../sandia_rules' );

  return
end


function f = toFunctionIn(disc, coeffs)
%TOFUNCTION   Convert discrete values of a TRIGSPEC to a CHEBFUN.
%   F = TOFUNCTIONIN(DISC, COEFFS) converts the coeffs returned by TRIGSPEC
%   to a CHEBFUN.
%
% See also TOVALUES, TOFUNCTIONOUT.

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

% Get the domain:
dom = disc.domain;

% Create a TRIGTECH object from the coefficients:
tech = trigtech({[], coeffs});

% Create a BNDFUN from the TRIGTECH:
fun{1} = bndfun(tech, struct('domain', dom));

% Create a CHEBFUN from the BNDFUN:
f = chebfun(fun);

end


function varargout = drawPolyline3d(varargin)
%DRAWPOLYLINE3D Draw a 3D polyline specified by a list of vertex coords.
%
%   drawPolyline3d(POLY);
%   packs coordinates in a single N-by-3 array.
%
%   drawPolyline3d(PX, PY, PZ);
%   specifies coordinates in separate numeric vectors (either row or
%   columns)
%
%   drawPolyline3d(..., CLOSED);
%   Specifies if the polyline is closed or open. CLOSED can be one of:
%   - 'closed'
%   - 'open'    (the default)
%   - a boolean variable with value TRUE for closed polylines.
%
%   drawPolyline3d(..., PARAM, VALUE);
%   Specifies style options to draw the polyline, see plot for details.
%
%   H = drawPolyline3d(...);
%   also returns a handle to the list of created line objects.
%
%   Example
%     t = linspace(0, 2*pi, 100)';
%     xt = 10 * cos(t);
%     yt = 5 * sin(t);
%     zt = zeros(1,100);
%     figure; drawPolyline3d(xt, yt, zt, 'b');
%
%   See also
%   polygons3d, drawPolygon3d, fillPolygon3d
%

% ------
% Author : David Legland
% E-mail: david.legland@inra.fr
% Created: 2005-02-15
% Copyright 2005-2022 INRA - TPV URPOI - BIA IMASTE

%% Process input arguments

% Check if axes handle is specified
if isAxisHandle(varargin{1})
    hAx = varargin{1};
    varargin(1) = [];
else
    hAx = gca;
end

% check case we want to draw several curves, stored in a cell array
var = varargin{1};
if iscell(var)
    hold on;
    h = zeros(length(var(:)), 1);
    for i = 1:length(var(:))
        h(i) = drawPolyline3d(hAx, var{i}, varargin{2:end});
    end
    if nargout > 0
        varargout = {h};
    end
    return;
end

% extract curve coordinates
if min(size(var)) == 1
    % if first argument is a vector (either row or column), then assumes
    % first argument contains x coords, second argument contains y coords
    % and third one the z coords
    px = var;
    if length(varargin) < 3
        error('geom3d:drawPolyline3d:Wrong number of arguments in drawPolyline3d');
    end
    if  isnumeric(varargin{2}) && isnumeric(varargin{3})
        py = varargin{2};
        pz = varargin{3};
        varargin(1:3) = [];
    else
        px = var(:, 1);
        py = var(:, 2);
        pz = var(:, 3);
        varargin(1) = [];
    end
else
    % all coordinates are grouped in the first argument
    px = var(:, 1);
    py = var(:, 2);
    pz = var(:, 3);
    varargin(1) = [];
end

% check if curve is closed or open (default is open)
closed = false;
if ~isempty(varargin)
    var = varargin{1};
    if islogical(var)
        % check boolean flag
        closed = var;
        varargin = varargin(2:end);

    elseif ischar(var)
        % check string indicating close or open
        if strncmpi(var, 'close', 5)
            closed = true;
            varargin = varargin(2:end);

        elseif strncmpi(var, 'open', 4)
            closed = false;
            varargin = varargin(2:end);
        end

    end
end

%% draw the curve

% for closed curve, add the first point at the end to close curve
if closed
    px = [px(:); px(1)];
    py = [py(:); py(1)];
    pz = [pz(:); pz(1)];
end

h = plot3(hAx, px, py, pz, varargin{:});

if nargout > 0
    varargout = {h};
end


function varargout = AffineTrnasformation(varargin)
% AFFINETRNASFORMATION M-file for AffineTrnasformation.fig
% Affine_Transf computes and applies the geometric affine transformation to a 2-D image.
%
% The program main functions are:
% - Load Image: Load the image to be transformed.
% - Transform Image: Computes the transformation matrix from the transformation parameters specified by the user, then it applies the transformation to the loaded image.
% - Save Image: Save the transformed image.
% - Quit: Exit the program.
% The transformation parameters are specified by the user by editing the
% values of the rotation, scale (x and y), and shear (x and y). The
% translation is not icluded because it can be easily (normalized or) removed from image by
% subtracting the shape cetroid.
%
% The affine matrix and the transformation are computed using Matlab Image Processing Toolbox
% functions: maketform and imtransform, so this program is only demonstrates the computation and the applying of these functions to a 2-D image.
%
% Version 1.0
% Copyright Feb 2003, Ibrahim El Rube
% ielrube@yahoo.com

% Begin initialization code - DO NOT EDIT
global gg gc;
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @AffineTrnasformation_OpeningFcn, ...
                   'gui_OutputFcn',  @AffineTrnasformation_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin & isstr(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before AffineTrnasformation is made visible.
function AffineTrnasformation_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to AffineTrnasformation (see VARARGIN)

% Choose default command line output for AffineTrnasformation
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes AffineTrnasformation wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = AffineTrnasformation_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global gg
% Get default command line output from handles structure
varargout{1} = handles.output;

gg=2;
% --- Executes on button press in Load_image.
function Load_image_Callback(hObject, eventdata, handles)
% hObject    handle to Load_image (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global gg gc;

h=guidata(gcbo);
set(h.message_text,'String','');  % Clear Messages
gg=gg+2;
h.image_filename=1;
h.image_pathname=1;
[filename, pathname] = uigetfile( ...
       {'*.bmp;*.tif;*.jpg;*.pcx;*.png;*.hdf;*.xwd;*.ras;*.pbm;*.pgm;*.ppm;*.pnm', 'All MATLAB SUPPORTED IMAGE Files (*.bmp,*.tif,*.jpg,*.pcx,*.png,*.hdf,*.xwd,*.ras,*.pbm,.pgm,*.ppm,*.pnm)'} ...
        ,'Pick a file');     % Load Image file and path names
    if filename~=0
        gg=1;
        h.gg=1;
        h.image_filename=filename;  % Image file name
        h.image_pathname=pathname;  % Image path name
        set(h.Showaxes,'visible','off');
        axes(h.axes1);
        set(h.figure1_title,'Visible','on');
        image_1=imread([pathname filename]); % Load Image
        imshow(image_1);                     % Show Loaded Image
        h.image_1=image_1;
        set(h.axes2,'Visible','off');
        axes(h.axes2);
        cla;
        set(h.figure2_title,'Visible','off');
        gc=0;
        h.axis12=0;
        guidata(gcbo,h);
    end
% --- Executes during object creation, after setting all properties.
function xscale_CreateFcn(hObject, eventdata, handles)
% hObject    handle to xscale (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function xscale_Callback(hObject, eventdata, handles)
% hObject    handle to xscale (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of xscale as text
%        str2double(get(hObject,'String')) returns contents of xscale as a
%        double

% --- Executes during object creation, after setting all properties.
function rot_CreateFcn(hObject, eventdata, handles)
% hObject    handle to rot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function rot_Callback(hObject, eventdata, handles)
% hObject    handle to rot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of rot as text
%        str2double(get(hObject,'String')) returns contents of rot as a double

% --- Executes during object creation, after setting all properties.
function xshear_CreateFcn(hObject, eventdata, handles)
% hObject    handle to xshear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function xshear_Callback(hObject, eventdata, handles)
% hObject    handle to xshear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of xshear as text
%        str2double(get(hObject,'String')) returns contents of xshear as a double

% --- Executes during object creation, after setting all properties.
function xtrans_CreateFcn(hObject, eventdata, handles)
% hObject    handle to xtrans (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function xtrans_Callback(hObject, eventdata, handles)
% hObject    handle to xtrans (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of xtrans as text
%        str2double(get(hObject,'String')) returns contents of xtrans as a double

% --- Executes on button press in deg.
function deg_Callback(hObject, eventdata, handles)
% hObject    handle to deg (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of deg
h=guidata(gcbo);
%set(h.rad,'Value',0);
ch=get(hObject,'Value');
switch ch
case 0
   set(h.rad,'Value',1)
case 1
   set(h.rad,'Value',0)
end
guidata(gcbo,h);
% --- Executes on button press in rad.
function rad_Callback(hObject, eventdata, handles)
% hObject    handle to rad (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of rad
h=guidata(gcbo);
%set(h.rad,'Value',0);
ch=get(hObject,'Value');
switch ch
case 0
  set(h.deg,'Value',1)
case 1
  set(h.deg,'Value',0)
end
guidata(gcbo,h);
% --- Executes on button press in bshear.
function bshear_Callback(hObject, eventdata, handles)
% hObject    handle to bshear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of bshear

% --- Executes on button press in checkbox2.
function checkbox2_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox2

% --- Executes during object creation, after setting all properties.
function ytrans_CreateFcn(hObject, eventdata, handles)
% hObject    handle to ytrans (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function ytrans_Callback(hObject, eventdata, handles)
% hObject    handle to ytrans (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of ytrans as text
%        str2double(get(hObject,'String')) returns contents of ytrans as a double

% --- Executes on button press in btrans.
function btrans_Callback(hObject, eventdata, handles)
% hObject    handle to btrans (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of btrans

% --- Executes during object creation, after setting all properties.
function yscale_CreateFcn(hObject, eventdata, handles)
% hObject    handle to yscale (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function yscale_Callback(hObject, eventdata, handles)
% hObject    handle to yscale (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of yscale as text
%        str2double(get(hObject,'String')) returns contents of yscale as a double

% --- Executes on button press in bscale.
function bscale_Callback(hObject, eventdata, handles)
% hObject    handle to bscale (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of bscale

% --- Executes on button press in Transform.
function Transform_Callback(hObject, eventdata, handles)
% hObject    handle to Transform (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global gg gc;
gc=0;
h=guidata(gcbo);
if  gg~=2
    h=guidata(gcbo);
    image_1=h.image_1;  % Get Image 1
    hb(1)=num_check(h.rot); % Rotation
    hb(2)=num_check(h.xscale); % Scale in x-direction
    hb(3)=num_check(h.yscale); % Scale in y-direction
    hb(4)=num_check(h.xshear); % Shear
    hb(5)=num_check(h.yshear);
    hc=sum(hb);
    switch hc
        case 0
            a=str2num(get(h.xscale,'String'));
            b=str2num(get(h.xshear,'String'));
            c=str2num(get(h.yshear,'String'));
            d=str2num(get(h.yscale,'String'));
            th=str2num(get(h.rot,'String'));  %2*pi/10;
            ch=get(h.deg,'Value');
            switch ch
                case 0
                    th=th;
                otherwise
                    th=th*pi/180;;
            end
            k=1;
            TT=k*[cos(th) -sin(th); sin(th) cos(th)]*[a b; c d];
            TTT=[ 1 0 0; 0 1 0; 0 0 1];
            TTT(1:2,1:2)=TT;
            set(h.message_text,'String','Transformaing .... Please Wait');
            tform=maketform('affine',TTT);
            [image_2] = imtransform(image_1,tform);
            h.image_2=image_2;
            axes(h.axes2);
            set(h.figure2_title,'Visible','on');
            imshow(image_2,[]);
            gc=1;
            axes(h.axes2);
            g2=h.axis12;
            switch g2
                case 0
                    axes(h.axes1);
                    axis on;
                    axes(h.axes2);
                    axis on;
                otherwise
                    axes(h.axes1);
                    axis off;
                    axes(h.axes2);
                    axis off;
            end
            set(h.message_text,'String','Done');
            set(h.Showaxes,'Visible','on');
            guidata(gcbo,h);
        otherwise
            set(h.message_text,'String','Invalid value: enter a real number only');
    end
end

% --- Executes on button press in Save_image.
function Save_image_Callback(hObject, eventdata, handles)
% hObject    handle to Save_image (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global gg gc;
h=guidata(gcbo);
set(h.message_text,'String','');
if   gc~=0
    dot='.';
    pathname=h.image_pathname;
    [filename, pathname] = uiputfile('*.*', 'Save Transformed Image');
    if filename~=0
        try_again=find(filename==dot);
        if ~isempty(try_again)
            image_ex=filename(try_again+1:end);
            valid_ex=['BMP'; 'TIF'; 'JPG'; 'PCX'; 'PNG'; 'HDF'; 'XWD'; 'RAS'; 'PBM'; 'PGM'; 'PPM'; 'PNM';];
            p=['\<' image_ex '\>'];
            g=regexpi(valid_ex,p);  % Match Exact extension, ignoring case.
            b=cell2mat(g);           % Convert cell to matrix
            if b~=0 & length(image_ex)==3
                  CMap=colormap(h.axes1);
                  h.savedimage_filename=filename;
                  h.savedimage_pathname=pathname;
                  imwrite(h.image_2,CMap,[pathname filename]);
                  savedto=['Image Saved to:    ' pathname filename];
                  set(h.message_text,'String',savedto);
             else
                  set(h.message_text,'String','Invalid file extension: Image NOT saved, use one of these extensions, BMP TIF JPG PCX PNG HDF XWD RAS PBM PGM PPM PNM');
            end
        else
            set(h.message_text,'String','Empty file extension: Image NOT saved, use one of these extensions, BMP TIF JPG PCX PNG HDF XWD RAS PBM PGM PPM PNM');
        end

    end
end
% --- Executes on button press in pushbutton4.
function pushbutton4_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
close;

% --- Executes during object creation, after setting all properties.
function yshear_CreateFcn(hObject, eventdata, handles)
% hObject    handle to yshear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

function yshear_Callback(hObject, eventdata, handles)
% hObject    handle to yshear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of yshear as text
%        str2double(get(hObject,'String')) returns contents of yshear as a double

function hb=num_check(ha);
% This function checks the validation of the entered transformation
% parameters
% ha is the handle to be checked
% hb is a flag, 1 for correct range, 0 for incorrect range.
h=guidata(gcbo);
ba=get(ha,'String');
bb=str2num(ba);
hb=0;
if isempty(bb) | ba=='i' | ba=='j'
    axes(h.axes2);
    cla;
    set(h.message_text,'String','Invalid value: enter a real number only');
    switch ha
        case h.xscale
            set(ha,'String','1');
        case h.yscale
            set(ha,'String','1');
        otherwise
            set(ha,'String','0');
    end
    hb=1;
    %break
end
%hb=ha;
%guidata(gcbo,h);

% --- Executes on button press in Showaxes.
function Showaxes_Callback(hObject, eventdata, handles)
% hObject    handle to Showaxes (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
h=guidata(gcbo);
sh=get(h.Showaxes,'String');
switch sh
    case 'Show Axes'
        set(h.Showaxes,'String','Hide Axes');
        h.axis12=0;
    otherwise
        set(h.Showaxes,'String','Show Axes');
        h.axis12=1;
end
g1=get(h.axes1,'visible');
axes(h.axes1);
switch g1
    case 'off'
        axis on;
        set(h.axes1,'visible','on');
    otherwise
        axis off;
        set(h.axes1,'visible','off');
end
g2=get(h.axes2,'visible');
axes(h.axes2);
switch g2
    case 'off'
        axis on;
        set(h.axes2,'visible','on');
    otherwise
        axis off;
        set(h.axes2,'visible','off');
end;
guidata(gcbo,h);


function test_headmodel_dipoli_new_old

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY ft_headmodel_dipoli mesh_sphere ft_prepare_vol_sens ft_compute_leadfield

% tests the old and new version of dipoli wrapper

% generate a unit sphere
[pnt, tri] = mesh_sphere(162);

% create the BEM geometries
geom = [];
geom.bnd(1).pnt = pnt * 100;
geom.bnd(1).tri = tri;
geom.bnd(2).pnt = pnt * 90;
geom.bnd(2).tri = tri;
geom.bnd(3).pnt = pnt * 80;
geom.bnd(3).tri = tri;

elec.chanpos = pnt * 100;
elec.elecpos = pnt * 100;
for i=1:size(pnt,1)
  elec.label{i} = sprintf('%d', i);
end

arg(1).name = 'conductivity';
arg(1).value = {[], [1 1/20 1], [0.33 0.125 0.33], [1 1 1], [0.1 0.1 0.1]};

arg(2).name = 'isolatedsource';
arg(2).value = {'yes' , 'no'};

optarg = constructalloptions(arg);

for i=1:size(optarg,1)

  vol = {};
  arg = optarg(i,:);

  % new way - low level:
  vol{1} = ft_headmodel_dipoli(geom.bnd,arg{:});

  % old way:
  tmpcfg = ft_keyval2cfg(arg{:});
  tmpcfg.method = 'dipoli';
  vol{2} = ft_prepare_bemmodel(tmpcfg,geom);
  vol{2} = rmfield(vol{2},'unit');

  % new way - high level:
  tmpcfg = ft_keyval2cfg(arg{:});
  tmpcfg.method = 'bem_dipoli';
  vol{3} = ft_prepare_headmodel(tmpcfg,geom.bnd);
  vol{3} = rmfield(vol{3},'unit');

  % compute the leadfields for a comparison
  [vol{1}, elec] = ft_prepare_vol_sens(vol{1}, elec);
  [vol{2}, elec] = ft_prepare_vol_sens(vol{2}, elec);
  [vol{3}, elec] = ft_prepare_vol_sens(vol{3}, elec);
  lf{1} = ft_compute_leadfield([0 10 60], elec, vol{1});
  lf{2} = ft_compute_leadfield([0 10 60], elec, vol{2});
  lf{3} = ft_compute_leadfield([0 10 60], elec, vol{3});

  % compare the leadfields in all possible combinations
  comb = nchoosek(1:numel(vol),2);
  for j=1:size(comb,1)
    chk = comb(j,:);
    err = norm(lf{chk(1)} - lf{chk(2)}) / norm(lf{chk(1)});
    if err>0.001
      error('combination %d %d not successful\n',chk(1),chk(2));
    end
  end

end


% function spm_induced_demo
% Demo routine for induced responses
%==========================================================================
%
% This demonstration illustrates the generative or forward model used for
% time frequency responses - in other words, a biophysically plausible
% dynamic causal model for induced responses. The basic idea is to
% integrate a neural mass model to obtain expected hidden neuronal
% states produced by an unknown (parameterised) exogenous input. The states
% are used as the expansion point for a linear perturbation analysis of
% the frequency response properties that are local in peristimulus time.
% The ensuing spectra (induced complex cross spectra) are then convolved
% with a wavelet window to generate predictions of a conventional time
% frequency (wavelet) transform. Crucially, these predictions are complex
% and can be used to characterise delays - in terms of cross covariance
% functions. Nonlinearities in the neural mass model mean that the spectral
% responses caused by random neuronal fluctuations are state dependent and
% therefore change with the expected hidden states over peristimulus time.
%
% This routine first creates a simple - two source - generative model using
% a canonical microcircuit architecture and convolution based dynamics. It
% then produces predictions of induced responses to a short and sustained
% input to the first source - as measured by two local field potential
% recordings at each source. Exactly the same model is then integrated in
% time,  using (serially correlated) random fluctuations to drive each
% source (in addition to the exogenous input). This is repeated over 16
% trials and the simulated responses are characterised in terms of a
% wavelet transform - to produce complex cross spectral  data features.
% These are shown graphically with their analytic predictions from the
% generative model.
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_induced_demo.m 7679 2019-10-24 15:54:07Z spm $

% Model specification
%==========================================================================
rng('default')
clear spm_fp_cmc_tfm

% number of regions in coupled map lattice
%--------------------------------------------------------------------------
Nc    = 2;                                       % number of channels
Ns    = 2;                                       % number of sources
options.spatial  = 'LFP';
options.model    = 'TFM';
options.analysis = 'TFM';
M.dipfit.model = options.model;
M.dipfit.type  = options.spatial;
M.dipfit.Nc    = Nc;
M.dipfit.Ns    = Ns;

% extrinsic connections (forward an backward)
%--------------------------------------------------------------------------
A{1} = [0 0; 1 0];
A{2} = [0 1; 0 0];
A{3} = [0 0; 0 0];
C    = [1 0;0 1];

% get priors
%--------------------------------------------------------------------------
pE    = spm_dcm_neural_priors(A,{},C,options.model);
pE    = spm_L_priors(M.dipfit,pE);
pE    = spm_ssr_priors(pE);
x     = spm_dcm_x_neural(pE,options.model);

% extrinsic connections
%--------------------------------------------------------------------------
pE.A{1}   = pE.A{1} + 1;
pE.A{2}   = pE.A{2} + 1;
pE.A{3}   = pE.A{3} - 1;
pE.A{4}   = pE.A{4} - 1;

% supress noise
%--------------------------------------------------------------------------
pE.a(1,:) = -2;
pE.b(1,:) = -4;
pE.c(1,:) = -4;

% orders and model
%==========================================================================
nx    = length(spm_vec(x));
nu    = size(pE.C,2);

% create forward model
%--------------------------------------------------------------------------
M.g   = 'spm_gx_erp';
M.f   = 'spm_fx_cmc_tfm';
M.h   = 'spm_fp_cmc_tfm';
M.x   = x;
M.n   = nx;
M.pE  = pE;
M.m   = nu;
M.l   = Nc;
M.Hz  = 2:64;
M.Rft = 4;
M.ds  = 4;

% solve for steady state
%--------------------------------------------------------------------------
M.x   = spm_dcm_neural_x(pE,M);

% Integrate system to see response (time-frequency)
%==========================================================================

% invoke exogenous inputs
%--------------------------------------------------------------------------
N     = 128;
U.dt  = 6/1024;
pst   = ((1:N)' - N/4)*U.dt;
U.u   = sparse(N,M.m);

% exogenous input - a sustained input of about 128 seconds
%--------------------------------------------------------------------------
M.ons    = 64;
U.u(:,1) = spm_erp_u(pst,pE,M);

% integrate generative model to simulate a time frequency response
%--------------------------------------------------------------------------
[csd,erp,CSD,mtf,w,pst,x,dP] = spm_csd_int(pE,M,U);

% plot expected responses
%==========================================================================
spm_figure('GetWin','Simulated time-frequency responses');
pst = 1000*pst;

subplot(4,2,1)
plot(pst,U.u)
xlabel('peristimulus time (ms)')
title('Exogenous input','FontSize',16)
spm_axis tight

% LFP - expectation
%--------------------------------------------------------------------------
subplot(4,2,2)
j   = find(kron(sparse(1,[3 1 5],1,1,8),ones(Ns,1)));
plot(pst,x(j,:))
xlabel('peristimulus time (ms)')
title('Hidden neuronal states','FontSize',16)
spm_axis tight

subplot(4,2,3)
plot(pst,erp{1})
xlabel('peristimulus time (ms)')
title('Evoked response','FontSize',16)
spm_axis tight

% LFP - expectation
%--------------------------------------------------------------------------
subplot(4,2,4)
plot(pst,dP{1})
xlabel('peristimulus time (ms)')
title('intrinsic connectivity','FontSize',16)
spm_axis tight

% expected time frequency response (coherence and cross-covariance)
%--------------------------------------------------------------------------
spm_dcm_tfm_image(CSD{1},pst,w,1)

% expected time frequency response
%--------------------------------------------------------------------------
spm_figure('GetWin','transfer functions');

spm_dcm_tfm_transfer(mtf{1},pst,w)

% simulated responses
%==========================================================================
spm_figure('GetWin','Predicted responses');

% time-frequency
%--------------------------------------------------------------------------
xY.erp = erp;
xY.csd = csd;
spm_dcm_tfm_response(xY,pst,w)

% Integrate system to simulate responses
%==========================================================================
spm_figure('GetWin','Simulated trials');

% get spectral density of neuronal fluctuations
%--------------------------------------------------------------------------
Hz    = 2:128;
Gu    = spm_csd_mtf_gu(pE,Hz);

% simulate Nt trials
%--------------------------------------------------------------------------
M.ds  = 0;                                       % switch to ERP generation
Nt    = 8;
V     = U;
for j = 1:Nt

    fprintf('\nsimulating trial %i',j)
    y    = 32;
    while max(abs(spm_vec(y))) > 1
        V.u  = U.u + spm_rand_power_law(Gu,Hz,U.dt,N)*2;
        y    = spm_csd_int(pE,M,V);
    end
    D(:,:,j) = full(real(y{1}));

    % LFP - random fluctuations
    %----------------------------------------------------------------------
    subplot(2,2,1)
    plot(pst,D(:,:,j)), hold on
    xlabel('time (s)')
    title('simulated response and ERP','FontSize',16)
    spm_axis tight, axis square; drawnow

end
hold off

% LFP - expectations
%--------------------------------------------------------------------------
subplot(2,2,2)
plot(pst*1000,erp{1},'-.'), hold on
plot(pst*1000,mean(D,3)), hold off
xlabel('time (s)')
title('LFP response - expectation','FontSize',16)
spm_axis tight, axis square

% Time frequency response
%--------------------------------------------------------------------------
Nf    = length(M.Hz);
P     = zeros(N,Nf,Nc,Nc);
Q     = zeros(N,Nf,Nc,Nc);
E     = mean(D,3);
for k = 1:Nt

    d     = full(double(D(:,:,k)));
    G     = spm_morlet(d - E,w*U.dt,M.Rft);
    for i = 1:Nc
        for j = 1:Nc
            P(:,:,i,j) = (G(:,:,i).*conj(G(:,:,j)));
        end
    end
    Q = Q + P;
end

% scale induced responsest sample variance
%--------------------------------------------------------------------------
Vm    = mean(mean((var(D))));
Vs    = mean(diag(squeeze(mean(squeeze(mean(Q))))));
Q     = Vm*Q/Vs;

% time-frequency
%--------------------------------------------------------------------------
spm_dcm_tfm_image(Q,pst,w,1)

% simulated responses
%==========================================================================
spm_figure('GetWin','Predicted responses - simulated');

% time-frequency
%--------------------------------------------------------------------------
xY.erp{1} = E;
xY.csd{1} = Q;
spm_dcm_tfm_response(xY,pst,w)

% compare expected and simulated responses
%==========================================================================
spm_figure('GetWin','Expected and simulated responses');

spm_dcm_tfm_image(csd{1},pst,w,0)
spm_dcm_tfm_image(Q,pst,w,1)


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This code is to replicate the results of RUSBoost model               %
% Our results are generated using Matlab R2020b on Windows 10           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

diary("results_rusboost.txt");
for year_test = 2003:2014
    rng(0,'twister'); % fix random seed for reproducing the results
    % read training data
    fprintf('==> Running RUSBoost (training period: %d-%d, testing period: %d, with %d-year gap)...\n',1991,year_test-2,year_test,2);
    data_train = data_reader('data_FraudDetection_JAR2020.csv','data_default',1991,year_test-2);
    y_train = data_train.labels;
    X_train = data_train.features;
    paaer_train = data_train.paaers;
    % read testing data
    data_test = data_reader('data_FraudDetection_JAR2020.csv','data_default',year_test,year_test);
    y_test = data_test.labels;
    X_test = data_test.features;
    paaer_test = unique(data_test.paaers(data_test.labels~=0));

    % handle serial frauds using PAAER
    y_train(ismember(paaer_train,paaer_test)) = 0;

    % train model
    t1 = tic;
    t = templateTree('MinLeafSize',5); % base model
    % see "tune_RUSBoost.m" for the tuning of the number of trees
    rusboost = fitensemble(X_train,y_train,'RUSBoost',300,t,'LearnRate',0.1,'RatioToSmallest',[1 1]);
    t_train = toc(t1);

    % test model
    t2 = tic;
    [label_predict,dec_values] = predict(rusboost,X_test);
    dec_values = dec_values(:,2);
    t_test = toc(t2);

    % print performance results
    fprintf('Training time: %g seconds | Testing time %g seconds \n', t_train, t_test);
    for topN = [0.01, 0.02, 0.03, 0.04, 0.05]
        metrics = evaluate(y_test,label_predict,dec_values,topN);
        fprintf('Performance (top%d%% as cut-off thresh): \n',topN*100);
        fprintf('AUC: %.4f \n', metrics.auc);
        fprintf('NCDG@k: %.4f \n', metrics.ndcg_at_k);
        fprintf('Sensitivity: %.2f%% \n', metrics.sensitivity_topk*100);
        fprintf('Precision: %.2f%% \n', metrics.precision_topk*100);
    end
end
diary off;


classdef PTKFissurenessHessianFactor < PTKPlugin
    % PTKFissureApproximation. Plugin to detect fissures using analysis of the
    %     Hessian matrix
    %
    %     This is a plugin for the Pulmonary Toolkit. Plugins can be run using
    %     the gui, or through the interfaces provided by the Pulmonary Toolkit.
    %     See PTKPlugin.m for more information on how to run plugins.
    %
    %     Plugins should not be run directly from your code.
    %
    %     This is an intermediate stage towards lobar segmentation.
    %
    %     PTKFissurenessHessianFactor computes the components of the fissureness
    %     generated using analysis of eigenvalues of the Hessian matrix.
    %
    %     For more information, see
    %     [Doel et al., Pulmonary lobe segmentation from CT images using
    %     fissureness, airways, vessels and multilevel B-splines, 2012]
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2012.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties
        ButtonText = 'Fissureness <BR>(Hessian part)'
        ToolTip = 'The part of the fissureness filter which uses Hessian-based analysis'
        Category = 'Fissures'

        AllowResultsToBeCached = false
        AlwaysRunPlugin = false
        PluginType = 'ReplaceOverlay'
        HidePluginInDisplay = false
        FlattenPreviewImage = false
        PTKVersion = '1'
        ButtonWidth = 6
        ButtonHeight = 2
        GeneratePreview = true
        Visibility = 'Developer'
        Version = 2

        MemoryCachePolicy = 'Temporary'
        DiskCachePolicy = 'Off'
    end

    methods (Static)
        function results = RunPlugin(dataset, reporting)
            reporting.UpdateProgressValue(0);
            left_and_right_lungs = dataset.GetResult('PTKLeftAndRightLungs');

            right_lung = dataset.GetResult('PTKGetRightLungROI');

            fissureness_right = PTKFissurenessHessianFactor.ComputeFissureness(right_lung, left_and_right_lungs, reporting, false);

            reporting.UpdateProgressValue(50);
            left_lung = dataset.GetResult('PTKGetLeftLungROI');
            fissureness_left = PTKFissurenessHessianFactor.ComputeFissureness(left_lung, left_and_right_lungs, reporting, true);

            reporting.UpdateProgressValue(100);
            results = PTKCombineLeftAndRightImages(dataset.GetTemplateImage(PTKContext.LungROI), fissureness_left, fissureness_right, left_and_right_lungs);

            results.ImageType = PTKImageType.Scaled;
        end
    end

    methods (Static, Access = private)

        function lung = DuplicateImageInMask(lung, mask_raw)
            mask_raw = mask_raw > 0;
            if any(mask_raw(:) > 0)
                [~, labelmatrix] = bwdist(mask_raw);
                lung(~mask_raw(:)) = lung(labelmatrix(~mask_raw(:)));
            else
                lung(:) = 0;
            end
        end

        function fissureness = ComputeFissureness(image_data, left_and_right_lungs, reporting, is_left_lung)

            left_and_right_lungs = left_and_right_lungs.Copy;
            left_and_right_lungs.ResizeToMatch(image_data);
            image_data.ChangeRawImage(PTKFissurenessHessianFactor.DuplicateImageInMask(image_data.RawImage, left_and_right_lungs.RawImage));

            mask = [];
            fissureness = PTKImageDividerHessian(image_data, @PTKFissurenessHessianFactor.ComputeFissurenessPartImage, mask, 1.5, [], false, false, is_left_lung, reporting);
        end

        function fissureness_wrapper = ComputeFissurenessPartImage(hessian_eigs_wrapper, voxel_size)
            fissureness_wrapper = PTKComputeFissurenessFromHessianeigenvalues(hessian_eigs_wrapper, voxel_size);
        end
    end
end


function [ node_num, edge_num ] = grf_example_size ( )

%*****************************************************************************80
%
%% GRF_EXAMPLE_SIZE sizes a GRF example.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 January 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Stephen Skiena,
%    Implementing Discrete Mathematics,
%    Combinatorics and Graph Theory with Mathematica,
%    Addison-Wesley, 1990.
%
%  Parameters:
%
%    Output, integer NODE_NUM, the number of nodes.
%
%    Output, integer EDGE_NUM, the number of edges.
%
  node_num = 28;
  edge_num = 84;

  return
end


function [C_offset] = updateTemporal_endoscope(obj, Y, smin)
%% run HALS by fixating all spatial components
% input:
%   Y:  d*T, fluorescence data
%   smin: scalar, threshold for detecting one spikes (>smin*sigma)
% output:
%   C_raw: K*T, temporal components without being deconvolved

% Author: Pengcheng Zhou, Carnegie Mellon University, adapted from Johannes

% options
maxIter = obj.options.maxIter;
if ~exist('smin', 'var') || isempty(smin)
    smin = 3;
end
%% initialization
A = obj.A;
K = size(A, 2);     % number of components
C = obj.C;
C_raw = zeros(size(C));
C_offset = zeros(K, 1);
S = zeros(size(C));
A = full(A);
U = A'*Y;
V = A'*A;
aa = diag(V);   % squares of l2 norm all all components
sn =  zeros(1, K);
kernel = obj.kernel;
kernel_pars = zeros(K, 2);

%% updating
ind_del = false(K, 1);
for miter=1:maxIter
    for k=1:K
        if ind_del
            continue;
        end
        temp = C(k, :) + (U(k, :)-V(k, :)*C)/aa(k);
        % estimate noise
        if miter==1
            sn(k) = get_noise_fft(temp);
        end

        % remove baseline
        [temp, C_offset(k)] = remove_baseline(temp, sn(k));

        % deconvolution
        if obj.options.deconv_flag
            if miter==1
                [ck, sk, kernel] = deconvCa(temp, kernel, smin, true, false, sn(k));
                kernel_pars(k, :) = kernel.pars;
            else
                kernel.pars = kernel_pars(k, :);
                [ck, sk, kernel] = deconvCa(temp, kernel, smin, false, false, sn(k));
            end
        else
            ck = max(0, temp);
        end

        % save convolution kernels and deconvolution results
        C(k, :) = ck;

        if sum(ck(2:end))==0
            ind_del(k) = true;
        end
        % save the spike count in the last iteration
        if miter==maxIter
            if obj.options.deconv_flag
                S(k, :) = sk;
            end
            C_raw(k, :) = temp;
        end
    end
end
obj.A = bsxfun(@times, A, sn);
obj.C = bsxfun(@times, C, 1./sn');
obj.C_raw = bsxfun(@times, C_raw, 1./sn');
obj.S = bsxfun(@times, S, 1./sn');
obj.P.kernel_pars = kernel_pars;
obj.delete(ind_del);


function options = spset(varargin)
% SPSET   Create/alter sparse interpolation OPTIONS structure
%   OPTIONS = SPSET('NAME1',VALUE1,'NAME2',VALUE2,...) creates an
%   options structure OPTIONS in which the named properties have
%   the specified values. Any unspecified properties have default
%   values. It is sufficient to type only the leading characters
%   that uniquely identify the property. Case is ignored for
%   property names.
%
%   OPTIONS = SPSET(OLDOPTS,'NAME1',VALUE1,...) alters an existing
%   options structure OLDOPTS.
%
%   OPTIONS = SPSET(OLDOPTS,NEWOPTS) combines an existing options
%   structure OLDOPTS with a new options structure NEWOPTS. Any new
%   properties overwrite corresponding old properties.
%
%   SPSET with no input arguments displays all property names and
%   their possible values.
%
%   See also SPGET, SPINTERP, SPVALS.
%
%
% SPSET PROPERTIES
%
% GridType - Sparse grid type and basis functions to use
%   [ {Clenshaw-Curtis} | Maximum | NoBoundary | Chebyshev |
%   Gauss-Patterson ]. For an illustration of  the grid types,
%   run CMPGRIDS.
%
% RelTol - Relative error tolerance [ positive scalar {1e-2} ]
%   A relative error tolerance that applies to all hierarchical
%   surpluses of the sparse grid representation. The grid is
%   further refined until all hierarchical surpluses are less than
%   max(RelTol*(max(fevalRange)-min(fevalRange)),AbsTol), with
%   fevalRange containing all results evaluating FUN up to
%   that point.
%
% AbsTol - Absolute error tolerance [ positive scalar {1e-6} ]
%   Used by the error control stated under RelTol.
%
% Vectorized - Vectorized function FUN [ on | {off} ]
%   Indicates if FUN is available for vectorized evaluation.
%   Vectorized coding of FUN can significantly reduce the
%   computation time used by SPVALS. For an example using a
%   vectorized function, please see SPDEMO.
%
% MinDepth - Minimum interpolation depth [ integer {2} ]
%   Minimum number of hierarchical interpolation levels n to
%   compute.
%
% MaxDepth - Maximum interpolation depth [ integer {8} ]
%   Maximum number of hierarchical interpolation levels n to
%   compute. The maximum supported depth (and the default) is 6
%   for the Gauss-Patterson grid.
%
% VariablePositions - Position of the ranges to interpolate in the
%   argument list when FUN is evaluated. [ 1xD vector {[]} ]
%   By setting VariablePositions, SPVALS will evaluate FUN with respect
%   to some of its input parameters, but not necessarily the first
%   D ones. With VARPOS, the actual position of each variable may
%   be set. VARPOS must be a 1xD array.
%
% NumberOfOutputs - Number of outputs [ integer {1} ]
%   If FUN produces multiple outputs (all must be scalar), indicate
%   this here to perform the sparse grid computation for many
%   output variables at once. Also see the example SPDEMOVAROUT.
%
% PrevResults - Previous sparse grid representation [ struct {[]} ]
%   An existing result structure obtained from SPVALS may be
%   provided to further refine an existing sparse grid.
%
% FunctionArgType - Function argument type [ {list} | vector ]
%   Indicates whether the objective function takes the input
%   parameters as a comma-separated list (default) or as a vector.
%
% KeepFunctionValues - Keep the function evaluations [ {off} | on ]
%   If this parameter is set, a structure field 'fvals' is
%   returned, containing a cell array with the function values at
%   the sparse grid points.
%
% KeepGrid - Keep the sparse grid points [ {off} | on ]
%   If this parameter is set, a structure field 'grid' is
%   returned, containing a cell array with the the sparse grid
%   points.
%
% DimensionAdaptive - Set dimension adaptivity option [ {off} | on ]
%   Dimension-adaptive grids try to adaptively find important
%   dimensions and adjust the sparse grid structure
%   accordingly. The implementation of dimension-adaptive sparse
%   grids follows the approach by Gerstner/Griebel.
%
% MinPoints - Minimum number of support nodes [ integer {100} ]
%   This parameter only applies to dimension-adaptive sparse grids,
%   and indicates the minimum number of support nodes
%   (i.e. function evaluations to perform).
%
% MaxPoints - Maximum number of support nodes [ integer {10000} ]
%   This parameter only applies to dimension-adaptive sparse grids.
%   The dimension-adaptive algorithm is aborted once the function
%   evaluation count exceeds this number.
%
% DimadaptDegree - Fine-tuning parameter to alter the degree of
%   dimension-adaptivity [ positive scalar {0.9} ]. A value of 1
%   places complete emphasis on the error estimates, and thus leads
%   to "greedy" dimension-adaptivity. A value of 0 disregards the
%   error estimates, and constructs a conventional sparse grid
%   based on the amount of work involved.
%
% DegreeStrategy - [ {balancing} | depth ] Strategy for the degree
%   of dimensional adaptivity.
%   The 'balancing' strategy balances the number of grid points
%   generated according to the greedy, error estimate-based refine-
%   ment rule compared to the number of points generated by the
%   conventional (regular) sparse grid refinement rule. I.e., a
%   DimadaptDegree value of 0.9 would mean that around 90% of the
%   grid points are generated by the error estimate-based rule, and
%   the remaining points are selected according to the regular
%   rule.
%   The 'depth' strategy makes sure that the maximum level depth
%   reached by the error estimate-based refinement in one dimension
%   does not get too deep compared to the depth reached in the other
%   dimensions. This measurement degree strategy is the one used
%   prior to version 5.1.0 of the toolbox, and is described on page
%   61 of A. Klimke, "Uncertainty modeling using fuzzy arithmetic
%   and sparse grids". This approach is still supported but no
%   the default strategy.
%
% SparseIndices - [ {auto} | on | off ] Manually turn the efficient
%   sparse storage scheme (new feature since version 3.0) of the
%   multi-index arrays on or off. The default switch auto uses the
%   new scheme for the ClenshawCurtis and the Chebyshev grid, and
%   the old (full) storage scheme from version 2.x for the Maximum
%   and the NoBoundary grid (the sparse grid storage scheme is not
%   supported for these two grid types).
%
% DropTol - Drop tolerance [ {auto} | off | 1x2 double vector ]
%   During the sparse grid construction progress, the spvals
%   algorithm may add subgrids with hierarchical surpluses that are
%   all close to zero or of negligible magnitude compared to the
%   surpluses of other sub-grids. In particular, this occurs when
%   additive structure is present in the objective function.
%   To increase the performance of the spinterp algorithm,
%   subgrids where all (absolute) hierarchical surpluses are less
%   than max(relDropTol*(max(fevalRange)-min(fevalRange),absDropTol))
%   can be omitted from the interpolation process by running the
%   sppurge algoritm (see help sppurge).
%   You may specify the absolute and the relative drop tolerance
%   as a vector [ absDropTol, relDropTol ], or turn it off completely
%   (= behavior of version 3.0 and earlier). The switch 'auto' uses
%   the values absDropTol = 0, relDropTol = 100*eps, that is, by
%   default, only a relative drop tolerance is used.
%
% EnableDCT - [ {on} | off ]  Use the DCT when constructing the
%   Chebyshev-Gauss-Lobatto type sparse grid.

% Author : Andreas Klimke, Universitaet Stuttgart
% Version: 1.9
% Date   : November 18, 2007

% Change log:
% V1.0   : Sep 23, 2003
%          Initial release
% V1.1   : Dec 23, 2003
%          Added FunctionArgType handling for more flexibility in
%          defining the objective function.
% V1.2   : Jan 07, 2004
%          Added KeepFunctionValues property to allow the user to
%          access the function values at the sparse grid points.
% V1.3   : Jan 08, 2004
%          Added KeepGrid property to allow the user to access the
%          sparse grid points.
% V1.4   : Apr 22, 2004
%          Added options for dimension-adaptive sparse grids.
% V1.5   : Feb 22, 2005
%          Added handling of sparse sets of indices (useful for
%          high-dimensional interpolation)
% V1.6   : January 13, 2006
%          Added documentation of SparseIndices property
% V1.7   : February 2, 2006
%          Added DropTol property
% V1.8   : March 1, 2006
%          Added DCT feature
% V1.9   : November 18, 2007
%          Added new grid type : Gauss-Patterson
% V2.0   : January 20, 2007
%          Added new parameter for dimensional adaptivity degree
%          strategy.

% ------------------------------------------------------------
% Sparse Grid Interpolation Toolbox
% Copyright (c) 2006 W. Andreas Klimke, Universitaet Stuttgart
% Copyright (c) 2007-2008 W. A. Klimke. All Rights Reserved.
% See LICENSE.txt for license.
% email: klimkeas@ians.uni-stuttgart.de
% web  : http://www.ians.uni-stuttgart.de/spinterp
% ------------------------------------------------------------

% Note: SPSET is similar in syntax and code the the options
% handling with ODEGET and ODESET of the MATLAB ODE suite by Marc
% Reichelt and Lawrence Shampine.

% Print out possible values of properties.
if (nargin == 0) && (nargout == 0)
  fprintf(['          GridType: [ {Clenshaw-Curtis} | Maximum |' ...
					 ' NoBoundary | Chebyshev | Gauss-Patterson ]\n']);
  fprintf('            RelTol: [ positive scalar {1e-2} ]\n');
  fprintf('            AbsTol: [ positive scalar {1e-6} ]\n');
  fprintf('        Vectorized: [ {off} | on ]\n');
	fprintf('          MinDepth: [ positive integer {2} ]\n');
	fprintf('          MaxDepth: [ positive integer {8} ] (6 for Gauss-Patt.)\n');
  fprintf(' VariablePositions: [ double matrix {[]} ]\n');
  fprintf('   NumberOfOutputs: [ positive integer {1} ]\n');
  fprintf('       PrevResults: [ struct {[]} ]\n');
	fprintf('   FunctionArgType: [ {list} | vector ]\n');
	fprintf('KeepFunctionValues: [ {off} | on ]\n');
	fprintf('          KeepGrid: [ {off} | on ]\n');
	fprintf(' DimensionAdaptive: [ {off} | on ]\n');
	fprintf('         MinPoints: [ positive integer {100} ]\n');
	fprintf('         MaxPoints: [ positive integer {10000} ]\n');
	fprintf('    DimadaptDegree: [ positive scalar in [0,1] {0.9} ]\n');
	fprintf('    DegreeStrategy: [ {balancing} | depth ]\n');
	fprintf('     SparseIndices: [ {auto} | on | off ]\n');
	fprintf(['           DropTol: [ {auto} | off |' ...
					 ' [absTol, relTol] (pos. scalars)]\n']);
	fprintf('         EnableDCT: [ {on} | off ]\n');
  fprintf('\n');
  return;
end

Names = {'GridType', 'RelTol', 'AbsTol', 'Vectorized', 'MinDepth', ...
				 'MaxDepth', 'VariablePositions', 'NumberOfOutputs', ...
				 'PrevResults', 'FunctionArgType', 'KeepFunctionValues', ...
				 'KeepGrid', 'DimensionAdaptive', 'MinPoints', ...
				 'MaxPoints', 'DimadaptDegree', 'DegreeStrategy', ...
				 'SparseIndices', 'DropTol', 'EnableDCT'};

m = length(Names);
names = cell(m,1);
for k = 1:m
	names{k} = lower(Names{k});
end

% Combine all leading options structures o1, o2, ... in odeset(o1,o2,...).
options = [];
for k = 1:m
  options.(Names{k}) = [];
end

k = 1;
while k <= nargin
  arg = varargin{k};
  if ischar(arg)                        % arg is an option name
    break;
  end
  if ~isempty(arg)                      % [] is a valid options argument
    if ~isa(arg,'struct')
      msg = sprintf(['Expected argument %d to be a string property' ...
										 ' name or an options structure\ncreated with' ...
										 ' SPSET.'], k);
      error(msg);
    end
    for l = 1:m
      if any(strcmp(fieldnames(arg),Names{l}))
        val = arg.(Names{l});
      else
        val = [];
      end
      if ~isempty(val)
        options.(Names{l}) = val;
      end
    end
		k = k + 1;
  else
		k = k + 1;
		break;
	end
end

% now process the name-value pairs.
if rem(nargin-k+1,2) ~= 0
  error('Arguments must occur in name-value pairs.');
end

expectval = 0;                      % start expecting a name, not a
                                    % value
while k <= nargin
  arg = varargin{k};

  if ~expectval
    if ~ischar(arg)
      msg = sprintf(['Expected argument %d to be a string property' ...
										 ' name.'], k);
      error(msg);
    end
    lowArg = lower(arg);
    matched = strmatch(lowArg,names);
    if isempty(matched)
      msg = sprintf('Unrecognized property name ''%s''.', arg);
      error(msg);
    elseif length(matched) > 1
      msg = sprintf('Ambiguous property name ''%s'' ', arg);
      msg = [msg '(' Names{matched(1)}];
      for l = matched(2:length(matched))'
        msg = [msg ', ' Names{l}];
      end
      msg = sprintf('%s).', msg);
      error(msg);
    end
    expectval = 1;                      % we expect a value next

  else
    options.(Names{matched}) = arg;
    expectval = 0;

  end
  k = k + 1;
end

if expectval
  msg = sprintf('Expected value for property ''%s''.', arg);
  error(msg);
end


function imResult = blendMode_Glow(A, B, offsetW, offsetH)
%% Glow blending mode: This mode is a variation of reflect mode (base and
%   blend color swapped).
%
% Input:
%       A       -       Base Image
%       B       -       Top Image
%   offsetW     -   move picture B horizontally in respect to the top-left
%                   corner of picture A. Default value = 1.
%   offsetH     -   move picture B vertically in respect to the top-left
%                   corner of picture A. Default value = 1.
%
% Output:
%       imResult    -   Result of the blending, having the same size of the
%                       Base Image A.
%

%% Check Input
a = size(A);
b = size(B);
blendMode_checkInput(nargin, a, b, func2str(@blendMode_Glow));

if nargin < 3
    offsetW = 1;
    offsetH = 1;
end

if nargin < 4
    offsetH = 1;
end

%% Implementation
imResult = A;

if (((offsetW ~= 1) || (offsetH ~= 1)) || (sum(a == b) ~= length(a)))
    [A, B] = blendMode_ResizeImages(A, B, a, b, offsetW, offsetH);
end

C = blendMode_Reflect(B, A);

if (((offsetW ~= 1) || (offsetH ~= 1)) || (sum(a == b) ~= length(a)))
    imResult = blendMode_CreateResult(imResult, C, offsetW, offsetH);
else
    imResult = C;
end

end