function recoverScenario(struct, idx_recover, mode, file_name)

% Authors:
%       Salih Guemues
%       Alexander Wischnewski
% Description:
%   function used to recalculate one simulation step to recover the
%   specific QP definition of the (soft) TMPC
% Inputs/parameters:
%   struct:      Log file struct
%   idx_recover: ID of the optimization problem which is plotted (debug_slow.tmpc_cnt)
%   mode:        Choose 'DD' for data dictionary parameters or 'script' for setupTMPCstruct to
%                   obtain the parameters
%   file_name:   if given, store results in seperate .mat file for dedicated visualization purposes

%% -------------------- HOW TO USE ---------------------------- %%
% Run Simulink model controller_dev ->
% execute convertSimLogs(logsout,'SimTest.mat'); ->
% load data via data = load('SimTest.mat');
% call this script via recoverScenario(data, t_recover, mode) and specify t_recover and mode

%% -------------------- DEFINE PARAMETERS ---------------------------- %%
% maximum number of iterations (high to check whether online solution may not have converged)
max_iter = 1000;

%% ---------------------- IMPORT CONTROLLER AND VEHICLE DATA ------------------------- %%
% get access to dictionary with controller parameters
sysDict = Simulink.data.dictionary.open('il_mvdc_mpc.sldd');
dDataSectObj2 = getSection(sysDict,'Design Data');
if(strcmp(mode, 'DD'))
    % load controller parameters from data dictionary
    sys = getValue(getEntry(dDataSectObj2,'sys'));
elseif(strcmp(mode, 'script'))
    % load controller parameters from initialize script
    sys = setupTMPCStruct(false);
else
    disp('No valid mode has been specified. Use DD or script');
end
help = getValue(getEntry(dDataSectObj2,'P_VDC_VirtualController'));
P_VDC_VirtualController = help.Value;
help = getValue(getEntry(dDataSectObj2,'P_VDC_PositiveAxLimScale'));
P_VDC_PositiveAxLimScale = help.Value;

% get access to dictionary with controller parameters
vehDict = Simulink.data.dictionary.open('il_vehicleparameter.sldd');
dDataSectObj3 = getSection(vehDict,'Design Data');
% get some more vehicle parameters
drag_coefficient = getValue(getEntry(dDataSectObj3, 'drag_coefficient'));
help = getValue(getEntry(dDataSectObj3,'roh_air'));
roh_air = help.Value;
vehiclemass_kg = getValue(getEntry(dDataSectObj3, 'vehiclemass_kg'));

%% ------------ IMPORT TRAJECTORY, VEHICLE, PREDICTION DATA AND RECONSTRUCT SCENARIO --------------- %%
% create TargetTrajectory struct and fill with logged data
TargetTrajectory.LapCnt         = struct.debug_slow.debug_slow_tartraj_LapCnt.Data(idx_recover,:);
TargetTrajectory.TrajCnt        = struct.debug_slow.debug_slow_tartraj_TrajCnt.Data(idx_recover,:);
TargetTrajectory.PointIdx       = uint16(0);
TargetTrajectory.s_loc_m        = struct.debug_slow.debug_slow_tartraj_s_loc_m.Data(idx_recover,:)';
TargetTrajectory.s_glob_m       = struct.debug_slow.debug_slow_tartraj_s_glob_m.Data(idx_recover,:)';
TargetTrajectory.x_m            = struct.debug_slow.debug_slow_tartraj_x_m.Data(idx_recover,:)';
TargetTrajectory.y_m            = struct.debug_slow.debug_slow_tartraj_y_m.Data(idx_recover,:)';
TargetTrajectory.psi_rad        = struct.debug_slow.debug_slow_tartraj_psi_rad.Data(idx_recover,:)';
TargetTrajectory.kappa_radpm    = struct.debug_slow.debug_slow_tartraj_kappa_radpm.Data(idx_recover,:)';
TargetTrajectory.v_mps          = struct.debug_slow.debug_slow_tartraj_v_mps.Data(idx_recover,:)';
TargetTrajectory.ax_mps2        = struct.debug_slow.debug_slow_tartraj_ax_mps2.Data(idx_recover,:)';
TargetTrajectory.banking_rad    = struct.debug_slow.debug_slow_tartraj_banking_rad.Data(idx_recover,:)';
TargetTrajectory.ax_lim_mps2    = struct.debug_slow.debug_slow_tartraj_ax_lim_mps2.Data(idx_recover,:)';
TargetTrajectory.ay_lim_mps2    = struct.debug_slow.debug_slow_tartraj_ay_lim_mps2.Data(idx_recover,:)';

% create VehicleDynamicState struct and fill with logged data
VehicleDynamicState.Pos.x_m             = struct.debug_slow.debug_slow_x_real_m.Data(idx_recover,:);
VehicleDynamicState.Pos.y_m             = struct.debug_slow.debug_slow_y_real_m.Data(idx_recover,:);
VehicleDynamicState.Pos.psi_rad         = struct.debug_slow.debug_slow_psi_real_rad.Data(idx_recover,:);
VehicleDynamicState.beta_rad            = struct.debug_slow.debug_slow_beta_real_rad.Data(idx_recover,:);
VehicleDynamicState.v_mps               = struct.debug_slow.debug_slow_vx_real_mps.Data(idx_recover,:);

ax_dist_mps2 = struct.debug_slow.debug_slow_ax_dist_mps2.Data(idx_recover, :)';
ay_dist_mps2 = struct.debug_slow.debug_slow_ay_dist_mps2.Data(idx_recover, :)';
% recalculate uncertainty matrices
UncertaintyTube = calcTubeShapeMatrices(sys.A_d, sys.B_d, P_VDC_VirtualController, sys.M_1, [ax_dist_mps2'; ay_dist_mps2'], sys.N_hor+1);
[PathPos, ~] = localTrajectoryMatching(VehicleDynamicState, TargetTrajectory);
% extract terminal set speed
v_terminal_mps = struct.debug_slow.debug_slow_be_l_abs.Data(idx_recover, 1);
dot_d_numerical = struct.debug_slow.debug_slow_dot_d_numerical_mps.Data(idx_recover, 1);

% get predictions vx_pred, d_psi_pred, s_dot_pred
x_pred_log       = struct.debug_slow.debug_slow_x_pred_m.Data(idx_recover, :)';
y_pred_log       = struct.debug_slow.debug_slow_y_pred_m.Data(idx_recover, :)';
vx_pred_log      = struct.debug_slow.debug_slow_vx_pred_mps.Data(idx_recover, :)';
d_pred_log       = struct.debug_slow.debug_slow_d_pred_m.Data(idx_recover, :)';
dot_d_pred_log   = struct.debug_slow.debug_slow_dot_d_pred_mps.Data(idx_recover, :)';
ax_pred_log      = struct.debug_slow.debug_slow_ax_pred_mps2.Data(idx_recover, :)';
ax_tire_pred_log = struct.debug_slow.debug_slow_ax_tire_pred_mps2.Data(idx_recover, :)';
ay_pred_log      = struct.debug_slow.debug_slow_ay_pred_mps2.Data(idx_recover, :)';

% get linearization and target trajectory
x_traj              = struct.debug_slow.debug_slow_x_traj_m.Data(idx_recover, :)';
y_traj              = struct.debug_slow.debug_slow_y_traj_m.Data(idx_recover, :)';
psi_traj            = struct.debug_slow.debug_slow_psi_traj_rad.Data(idx_recover, :)';
v_traj              = struct.debug_slow.debug_slow_v_traj_mps.Data(idx_recover, :)';
kappa_traj          = struct.debug_slow.debug_slow_kappa_traj_radpm.Data(idx_recover, :)';
ax_diff_traj        = struct.debug_slow.debug_slow_ax_diff_traj_mps2m.Data(idx_recover, :)';
ax_traj             = struct.debug_slow.debug_slow_ax_traj_mps2.Data(idx_recover, :)';
ay_traj             = struct.debug_slow.debug_slow_ay_traj_mps2.Data(idx_recover, :)';
ax_lim_mps2         = struct.debug_slow.debug_slow_ax_lim_mps2.Data(idx_recover, :)';
ay_lim_mps2         = struct.debug_slow.debug_slow_ay_lim_mps2.Data(idx_recover, :)';
d_lim_ub_m          = struct.debug_slow.debug_slow_d_lim_ub_m.Data(idx_recover, :)';
d_lim_lb_m          = struct.debug_slow.debug_slow_d_lim_lb_m.Data(idx_recover, :)';
d_Target_m          = struct.debug_slow.debug_slow_d_Target_m.Data(idx_recover, :)';
dot_d_Target_mps    = struct.debug_slow.debug_slow_dot_d_Target_mps.Data(idx_recover, :)';
ax_traj_old         = struct.debug_slow.debug_slow_ax_traj_mps2.Data(idx_recover-1, :)';
ay_traj_old         = struct.debug_slow.debug_slow_ay_traj_mps2.Data(idx_recover-1, :)';
vx_lin_mps          = struct.debug_slow.debug_slow_vx_lin_mps.Data(idx_recover, :)';
kappa_lin_radpm     = struct.debug_slow.debug_slow_kappa_lin_radpm.Data(idx_recover, :)';
u_opt_total_sim     = struct.debug_slow.debug_slow_u_opt_total.Data(idx_recover, :)';
u_opt_old_log       = struct.debug_slow.debug_slow_u_opt_total.Data(idx_recover-1, :)';

%% --------------------- SETUP INITIAL QP  ------------------------------ %%
% Define problem data by reconstructing it using the sparsity pattern
% init empty matrices
P_help = zeros(sys.osqp_n, sys.osqp_n);
A_help = zeros(sys.osqp_m, sys.osqp_n);
% fill values according to sparsity pattern
P_help(sys.P_i_lin) = sys.P_x_par;
% NOTE THAT P IS STORED AS UPPER TRIANGULAR, however calculations require
% FULL P MATRIX --> add transpose and substract diagonal elements
P_help = P_help + P_help' - diag(diag(P_help));
A_help(sys.A_i_lin) = sys.A_x_par;
q = sys.osqp_qpar;
l = sys.l_par;
u = sys.u_par;
P = sparse(P_help);
A = sparse(A_help);
% Create an OSQP object
prob = osqp;
% change settings
settings = prob.default_settings();
settings.alpha = 1.0;
settings.verbose = true;
settings.scaling = 0;  % number of scaling iterations
settings.max_iter = max_iter;
settings.warm_start = true;
settings.eps_abs = 1e-5;
settings.eps_rel = 1e-5;
% Setup workspace, change alpha parameter and disable prints
prob.setup(P, q, A, l, u, settings);

%% ----------- CALL prepareOptimizationProblem TO RECOVER QP ----------------- %%
[f, lb, ub, A_x, be_u_abs, be_l_abs, ~, error_state] =...
    prepareOptimizationProblem(VehicleDynamicState, dot_d_numerical, PathPos, ...
    v_traj, ax_diff_traj, ax_traj, ay_traj, ax_lim_mps2, ay_lim_mps2, ...
    d_lim_ub_m, d_lim_lb_m, d_Target_m, dot_d_Target_mps, ...
    vx_lin_mps, kappa_lin_radpm, UncertaintyTube, v_terminal_mps, ...
    ax_traj_old, ay_traj_old, u_opt_old_log, ...
    sys, P_VDC_VirtualController, drag_coefficient, roh_air, vehiclemass_kg, ...
    P_VDC_PositiveAxLimScale, true, 0.9);

%% --------------------- UPDATE AND SOLVE QP  ------------------------------ %%
% update QP vectors
prob.update('q', f, 'l', lb, 'u', ub);
prob.update('Ax', A_x);
% solve problem and get solution. two runs necessary to replicate warm start behavior of online
% solution while running the car.
res = prob.solve();
u_opt_total = res.x;
% meaning of status as in https://osqp.org/docs/interfaces/status_values.html
status = res.info.status_val;

% debug output
disp(['The problem has been solved during reoptimization with status: ' num2str(status)]);
disp(['It took ' num2str(res.info.iter) ' iterations and ' num2str(res.info.solve_time) ' seconds']);

%% ----------- CALL transformMPCResult TO RECOVER OPTIMIZED TRAJ. AND PREDICTIONS ----------------- %%
[u_opt_total, x_pred, y_pred, x_pred_left, y_pred_left, x_pred_right, y_pred_right, ...
    vx_pred, d_pred, dot_d_pred, ~, ax_pred, ax_tire_pred, ay_pred, ~, ~]  ...
    = transformMPCResult(status, u_opt_total, error_state,...
    x_traj, y_traj, psi_traj, v_traj, ax_diff_traj, d_Target_m, ax_lim_mps2, ay_lim_mps2, ...
    vx_lin_mps, kappa_lin_radpm, UncertaintyTube, ...
    sys, drag_coefficient, roh_air, vehiclemass_kg, P_VDC_PositiveAxLimScale);

%% plotting of optimization problem result

% recalculate tubes
[lb_v, ub_v] = calcBoundsPlot(zeros(sys.N_hor, 1), UncertaintyTube, false, P_VDC_VirtualController, sys.N_hor, repmat([1; 0; 0], 1, sys.N_hor));
[lb_d, ub_d] = calcBoundsPlot(zeros(sys.N_hor, 1), UncertaintyTube, false, P_VDC_VirtualController, sys.N_hor, repmat([0; 1; 0], 1, sys.N_hor));
[lb_dot_d, ub_dot_d] = calcBoundsPlot(zeros(sys.N_hor, 1), UncertaintyTube, false, P_VDC_VirtualController, sys.N_hor, repmat([0; 0; 1], 1, sys.N_hor));
[~, ub_tire1] = calcBoundsPlot(zeros(sys.N_hor+1, 1), UncertaintyTube, true, ...
    P_VDC_VirtualController, sys.N_hor+1, [1./(P_VDC_PositiveAxLimScale*ax_lim_mps2), 1./ay_lim_mps2]');
[~, ub_tire2] = calcBoundsPlot(zeros(sys.N_hor+1, 1), UncertaintyTube, true, ...
    P_VDC_VirtualController, sys.N_hor+1, [1./ax_lim_mps2, 1./ay_lim_mps2]');
[~, ub_tire3] = calcBoundsPlot(zeros(sys.N_hor+1, 1), UncertaintyTube, true, ...
    P_VDC_VirtualController, sys.N_hor+1, [-1./ax_lim_mps2, 1./ay_lim_mps2]');
[~, ub_tire4] = calcBoundsPlot(zeros(sys.N_hor+1, 1), UncertaintyTube, true, ...
    P_VDC_VirtualController, sys.N_hor+1, [-1./(P_VDC_PositiveAxLimScale*ax_lim_mps2), 1./ay_lim_mps2]');

% calculate limits for ax depending on positive accelerations
idx_pos = ax_traj > 0;
ax_lim_mps2_traj = ax_lim_mps2;
ax_lim_mps2_traj(idx_pos) = P_VDC_PositiveAxLimScale*ax_lim_mps2(idx_pos)';
idx_pos = ax_tire_pred > 0;
ax_lim_mps2_pred = ax_lim_mps2;
ax_lim_mps2_pred(idx_pos) = P_VDC_PositiveAxLimScale*ax_lim_mps2(idx_pos)';
idx_pos = ax_tire_pred_log > 0;
ax_lim_mps2_pred_log = ax_lim_mps2;
ax_lim_mps2_pred_log(idx_pos) = P_VDC_PositiveAxLimScale*ax_lim_mps2(idx_pos)' ;

figure;
grid on; hold on;
plot(x_traj, y_traj);
plot(x_pred, y_pred);
plot(x_pred_log, y_pred_log, '*');
plot(x_pred_left, y_pred_left, 'k--');
plot(x_pred_right, y_pred_right, 'k--', 'HandleVisibility','off');
grid on; axis equal;
legend('Target', 'Optimized', 'Logged', 'Tube');
xlabel('x East in m');
ylabel('y North in m');

% compare target and reoptimized trajectory
figure;
ax11 = subplot(2, 2, 1);
grid on; hold on;
plot(v_traj);
plot(vx_pred);
plot(vx_pred_log, '*');
plot(vx_pred(1:sys.N_hor) + ub_v', 'k--');
plot(vx_pred(1:sys.N_hor) + lb_v', 'k--', 'HandleVisibility','off');
plot([sys.N_hor+1, sys.N_hor+3], [be_u_abs(1), be_u_abs(1)], 'k');
plot([sys.N_hor+1, sys.N_hor+3], [be_l_abs(1), be_l_abs(1)], 'k', 'HandleVisibility','off');
plot(vx_lin_mps);
xlabel('Discretization points');
ylabel('Velocity in mps');
legend('Target', 'Optimized', 'Logged', 'Tube', 'Terminal Set', 'Linearization');

ax12 = subplot(2, 2, 2);
grid on; hold on;
plot(ax_traj./ax_lim_mps2_traj + kappa_traj.*v_traj.^2./ay_lim_mps2);
plot(ax_tire_pred./ax_lim_mps2_pred + ay_pred./ay_lim_mps2);
plot(ax_tire_pred_log./ax_lim_mps2_pred_log + ay_pred_log./ay_lim_mps2, '*');
plot(ax_tire_pred./ax_lim_mps2_pred + ay_pred./ay_lim_mps2 + ub_tire1', 'k--');
plot(ax_tire_pred./ax_lim_mps2_pred + ay_pred./ay_lim_mps2 - ub_tire2', 'k--', 'HandleVisibility','off');
plot([0, sys.N_hor], [1, 1], 'k');
plot([0, sys.N_hor], [-1, -1], 'k');
grid on;
xlabel('Discretization points');
ylabel('Acceleration constraint normalized');
legend('Target', 'Optimized', 'Logged', 'Tube', 'Limit');

ax13 = subplot(2, 2, 3);
grid on; hold on;
plot(d_Target_m)
plot(d_pred);
plot(d_pred_log, '*');
plot(d_pred(1:sys.N_hor) + ub_d', 'k--');
plot(d_pred(1:sys.N_hor) + lb_d', 'k--', 'HandleVisibility','off');
plot(d_lim_ub_m, 'k');
plot(d_lim_lb_m, 'k');
grid on;
xlabel('Discretization points');
ylabel('Lateral deviation in m');
legend('Target', 'Optimized', 'Logged', 'Tube', 'Limit');

ax14 = subplot(2, 2, 4);
grid on; hold on;
plot(-ax_traj./ax_lim_mps2 + kappa_traj.*v_traj.^2./ay_lim_mps2);
plot(-ax_tire_pred./ax_lim_mps2_pred + ay_pred./ay_lim_mps2);
plot(-ax_tire_pred_log./ax_lim_mps2_pred_log + ay_pred_log./ay_lim_mps2, '*');
plot(-ax_tire_pred./ax_lim_mps2_pred + ay_pred./ay_lim_mps2 - ub_tire3', 'k--');
plot(-ax_tire_pred./ax_lim_mps2_pred + ay_pred./ay_lim_mps2 + ub_tire4', 'k--', 'HandleVisibility','off');
plot([0, sys.N_hor], [1, 1], 'k');
plot([0, sys.N_hor], [-1, -1], 'k');
grid on;
xlabel('Discretization points');
ylabel('Acceleration constraint normalized');
legend('Target', 'Optimized', 'Logged', 'Tube', 'Limit');

linkaxes([ax11, ax12, ax13, ax14], 'x');

figure;
ax21 = subplot(2, 3, 1);
grid on; hold on;
plot(ax_traj);
plot(ax_pred);
plot(ax_pred_log, '*');
plot(-u_opt_total(1:2:2*(sys.N_hor+1)));
plot(ax_lim_mps2, 'k');
plot(-ax_lim_mps2, 'k');
grid on;
xlabel('Discretization points');
ylabel('Acceleration x in mps2');
legend('Target', 'Optimized', 'Logged', 'delta ax', 'Limit');

ax22 = subplot(2, 3, 2);
grid on; hold on;
plot(kappa_traj.*v_traj.^2);
plot(ay_pred);
plot(ay_pred_log, '*');
plot(u_opt_total(2:2:2*(sys.N_hor+1)));
plot(ay_lim_mps2, 'k');
plot(-ay_lim_mps2, 'k');
grid on;
xlabel('Discretization points');
ylabel('Acceleration y in mps2');
legend('Target', 'Optimized', 'Logged', 'delta ay', 'Limit');

ax23 = subplot(2, 3, 3);
grid on; hold on;
plot(dot_d_Target_mps)
plot(dot_d_pred);
plot(dot_d_pred_log, '*');
plot(dot_d_pred_log(1:sys.N_hor) + ub_dot_d', 'k--');
plot(dot_d_pred_log(1:sys.N_hor) + lb_dot_d', 'k--', 'HandleVisibility','off');
grid on;
xlabel('Discretization points');
ylabel('Lateral deviation derivative in mps');
legend('Target', 'Optimized', 'Logged', 'Tube');

ax26 = subplot(2, 3, 4);
grid on; hold on;
plot(u_opt_total(2*(sys.N_hor+1)+3:sys.n_slacks:end), 'b');
plot(u_opt_total_sim(2*(sys.N_hor+1)+3:sys.n_slacks:end), 'b*');
plot(u_opt_total(2*(sys.N_hor+1)+4:sys.n_slacks:end), 'c');
plot(u_opt_total_sim(2*(sys.N_hor+1)+4:sys.n_slacks:end), 'c*');
plot([0, sys.N_hor], [0, 0], 'k');
plot([0, sys.N_hor], [1.5, 1.5]/2, 'k');
grid on;
xlabel('Discretization points');
ylabel('Slacks lateral');
legend('Optimized upper', 'Logged upper', 'Optimized lower', 'Optimized lower', 'Limit');

ax27 = subplot(2, 3, 5);
grid on; hold on;
plot(u_opt_total(2*(sys.N_hor+1)+1:sys.n_slacks:end));
plot(u_opt_total_sim(2*(sys.N_hor+1)+1:sys.n_slacks:end), '*');
plot([0, sys.N_hor], [0, 0], 'k');
plot([0, sys.N_hor], [sys.slack_lim_rel, sys.slack_lim_rel], 'k');
grid on;
xlabel('Discretization points');
ylabel('Slacks tire 1 lower');
legend('Optimized upper', 'Logged', 'Limit');

ax28 = subplot(2, 3, 6);
grid on; hold on;
plot(u_opt_total(2*(sys.N_hor+1)+2:sys.n_slacks:end));
plot(u_opt_total_sim(2*(sys.N_hor+1)+2:sys.n_slacks:end), '*');
plot([0, sys.N_hor], [0, 0], 'k');
plot([0, sys.N_hor], [sys.slack_lim_rel, sys.slack_lim_rel], 'k');
grid on;
xlabel('Discretization points');
ylabel('Slacks tire 2 lower');
legend('Optimized', 'Logged', 'Limit');

linkaxes([ax21, ax22, ax23, ax26, ax27, ax28], 'x');

%% store data in external file for further visualization
if nargin > 3
    save(file_name);
end

end


function b = ContrastChange(img,level)

img = im2double(img)*255;
img= img*level;
b = uint8(img);
end


function [mimgR,mimgG] = regRedGreenChannel(ops)

% numPlanes = length(ops.planesToProcess);

% build file list with red channel

if (isfield(ops, 'SubDirsRed') && ~isempty(ops.SubDirsRed))
    subDirsRed = ops.SubDirsRed;
else
    if (isfield(ops, 'expred') && ~isempty(ops.expred))
        for i = 1:length(ops.expred)
            subDirsRed{i} = sprintf('%d', ops.expred(i));
        end
    else
        warning('could not find red channel info, returning...')
        return;
    end
end
%
% build file list
for i = 1:length(ops.expred)
    fsRED = dir(fullfile(ops.RootDir, subDirsRed{i}, '*.tif'));
    for k = 1:length(fsRED)
        fsRED(k).name = fullfile(ops.RootDir, subDirsRed{i}, fsRED(k).name);
    end
end

root = ops.ResultsSavePath;
fregops =  sprintf('regops_%s_%s.mat', ops.mouse_name, ops.date);
if exist(fullfile(root, fregops), 'file')
    load(fullfile(root, fregops))
else
    ops1 = cell(ops.nplanes, 1);
    for j = 1:ops.nplanes

        fname = sprintf('regops_%s_%s_plane%d.mat', ops.mouse_name, ops.date, j);
        dat = load(fullfile(root, fname));
        ops1{j} = dat.ops;
        ops1{j}.useGPU = ops.useGPU;
    end
end

%
ntf0 = 0;
numPlanes = ops.nplanes;
%iplane0 = 1:1:ops.nplanes;

totFrames=0;
for k = 1:length(fsRED)
    %iplane0 = mod(iplane0-1, numPlanes) + 1;
    startPlane=((mod(totFrames+1,ops.nplanes*2)-1)/2)+1;

    nFr = nFramesTiff(fsRED(k).name);
    totFrames=totFrames+nFr;
    data = loadFramesBuff(fsRED(k).name, 1, nFr, 1, ops.temp_tiff);

    if ~exist('mimgR', 'var')
        [Ly, Lx, ~] = size(data);
        mimgR = zeros(Ly, Lx, ops.nplanes);
    end
    if ~exist('mimgG', 'var')
        [Ly, Lx, ~] = size(data);
        mimgG = zeros(Ly, Lx, ops.nplanes);
    end
    %

    for iPlane=1:ops.nplanes

        idx0=mod((ops.nplanes-startPlane+iPlane)*2,ops.nplanes*2);
        planesG=(idx0+1):(2*ops.nplanes):nFr;
        planesR=(idx0+2):(2*ops.nplanes):nFr;
        dataG0=data(:,:,planesG);
        dataR0=data(:,:,planesR);

        BiDiPhase = ops1{iPlane}.BiDiPhase;
        if abs(BiDiPhase) > 0
            yrange = 2:2:Ly;
            if BiDiPhase>0
                dataG0(yrange,(1+BiDiPhase):Lx,:,:) = dataG0(yrange, 1:(Lx-BiDiPhase),:,:);
                dataR0(yrange,(1+BiDiPhase):Lx,:,:) = dataR0(yrange, 1:(Lx-BiDiPhase),:,:);
            else
                dataG0(yrange,1:Lx+BiDiPhase,:,:)   = dataG0(yrange, 1-BiDiPhase:Lx,:,:);
                dataR0(yrange,1:Lx+BiDiPhase,:,:)   = dataR0(yrange, 1-BiDiPhase:Lx,:,:);
            end
        end

        [ds, ~]  = regoffKriging(dataG0, ops1{iPlane}, 0);
        %[ds, ~]  = registration_offsets(dataG0, ops1{iPlane}, 0);

        if k==1
            ds(1,:) = 0;
        end
        dataR       = ...
            register_movie(dataR0, ops1{iPlane}, ds);
        dataG     = ...
            register_movie(dataG0, ops1{iPlane}, ds);

        mimgR(:,:,iPlane) = mimgR(:,:,iPlane) + mean(dataR, 3);
        mimgG(:,:,iPlane) = mimgG(:,:,iPlane) + mean(dataG, 3);

    end

    ntf0 = ntf0 + 1;

    %iplane0 = iplane0 - nFr/ops.nchannels_red;
    fprintf('processing tiff %d/%d\n',k,length(fsRED))
end

mimgR = mimgR/ntf0;
mimgG = mimgG/ntf0;


classdef PTKVentilationMask < PTKPlugin
    % PTKVentilationMask. Plugin for segmenting ventilation values from
    %     hyperpolarised gas MRI
    %
    %     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.
    %
    %
    %
    %     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 = 'Ventilation <BR>Mask'
        ToolTip = ''
        Category = 'Lungs'

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

    methods (Static)
        function results = RunPlugin(dataset, reporting)
            original_image = dataset.GetResult('PTKOriginalImage');
            noise_roi = original_image.RawImage(1, 20:220, 10:60); % Kaushik et al
            roi = dataset.GetResult('PTKLungROI');
            std_noise = std(double(noise_roi(:)));
            mean_signal = mean(double(noise_roi(:)));
            threshold = mean_signal + 2*std_noise;

            threshold_image = logical(roi.RawImage >= threshold);
            results = roi.BlankCopy;
            results.ChangeRawImage(threshold_image);

            results.BinaryMorph(@imopen, 6);

            results.ChangeRawImage(3*uint8(results.RawImage));

            results.ImageType = PTKImageType.Colormap;
        end
    end
end


% =========================================================================
% =========================================================================
% ================================CHESS=================================
% =========================================================================
% =========================================================================
%
% Author:
%   Muhammad Suleman Shafqat
%   Started on:     19Jan, 2011 (1200hrs)
%   Completed on:   20Jan, 2011 (1130hrs)
%
% Version:
%   01
%
% ---Functions---------Used for
%   Chess               main function
%   playerturn          player's turn
%   checkfp             check final position, it checks position and kills
%   wholoses            to check who loses and if no body return (loses=0)
%   reqmark             converts black to white backgrounds if necessary
%   whichpiece          reads the selected piece and converts it from icon to integer
%
% ---Structures----------Used for
%
%   h                   structure for varialbes
%   ha                  global for components of GUI
%
% ---Variables----------Used for
%
%   box                 to represent position of pieces
%   ipr                 initial position in row
%   ipc                 initial position in column
%   fpr                 final position in row
%   fpc                 final position in column
%   r                   row number of selected button
%   c                   column number of selected button
%   background            to upload a background of board
%   bg                  background image is uploaded here
%   plrmark             an axis to show whose turn is this
%   check               binary variable to check whether a turn is correct or not
%   loses               checked after each turn, whether anybody loses or not
%   plr                 player who needs to turn
%   otherplr            other player
%   ed                  eventdata
% =========================================================================

% simple chess:
%       started on 19/1/2011 at 1200hrs
%       ended on 20/1/2011 at 1130hrs
% changing into symbols:
%       started on 28/1/2011 and completed by 1230hrs
function varargout = CHESS_on_MATLAB(varargin)
% CHESS M-file for CHESS.fig
% Last Modified by GUIDE v2.5 28-Jan-2011 12:16:36
% Begin initialization code
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @CHESS_OpeningFcn, ...
                   'gui_OutputFcn',  @CHESS_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(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

% --- Executes just before CHESS is made visible.
function CHESS_OpeningFcn(hObj, ed, h, varargin)
% Choose default command line output for CHESS
h.output = hObj;
global ha
clc
% initialization gui components
ha(1)  = h.plrturn;
ha(11) = h.box11;ha(12) = h.box12;ha(13) = h.box13;ha(14) = h.box14;
ha(15) = h.box15;ha(16) = h.box16;ha(17) = h.box17;ha(18) = h.box18;
ha(21) = h.box21;ha(22) = h.box22;ha(23) = h.box23;ha(24) = h.box24;
ha(25) = h.box25;ha(26) = h.box26;ha(27) = h.box27;ha(28) = h.box28;
ha(31) = h.box31;ha(32) = h.box32;ha(33) = h.box33;ha(34) = h.box34;
ha(35) = h.box35;ha(36) = h.box36;ha(37) = h.box37;ha(38) = h.box38;
ha(41) = h.box41;ha(42) = h.box42;ha(43) = h.box43;ha(44) = h.box44;
ha(45) = h.box45;ha(46) = h.box46;ha(47) = h.box47;ha(48) = h.box48;
ha(51) = h.box51;ha(52) = h.box52;ha(53) = h.box53;ha(54) = h.box54;
ha(55) = h.box55;ha(56) = h.box56;ha(57) = h.box57;ha(58) = h.box58;
ha(61) = h.box61;ha(62) = h.box62;ha(63) = h.box63;ha(64) = h.box64;
ha(65) = h.box65;ha(66) = h.box66;ha(67) = h.box67;ha(68) = h.box68;
ha(71) = h.box71;ha(72) = h.box72;ha(73) = h.box73;ha(74) = h.box74;
ha(75) = h.box75;ha(76) = h.box76;ha(77) = h.box77;ha(78) = h.box78;
ha(81) = h.box81;ha(82) = h.box82;ha(83) = h.box83;ha(84) = h.box84;
ha(85) = h.box85;ha(86) = h.box86;ha(87) = h.box87;ha(88) = h.box88;

%uploading symbols of chess pieces to structure 'h'
h.blackpawn1=imread(strcat('pieces\blackpawn1','.png'));
h.blackpawn2=imread(strcat('pieces\blackpawn2','.png'));
h.whitepawn1=imread(strcat('pieces\whitepawn1','.png'));
h.whitepawn2=imread(strcat('pieces\whitepawn2','.png'));
h.blackrook1=imread(strcat('pieces\blackrook1','.png'));
h.blackrook2=imread(strcat('pieces\blackrook2','.png'));
h.whiterook1=imread(strcat('pieces\whiterook1','.png'));
h.whiterook2=imread(strcat('pieces\whiterook2','.png'));
h.blackbishop1=imread(strcat('pieces\blackbishop1','.png'));
h.blackbishop2=imread(strcat('pieces\blackbishop2','.png'));
h.whitebishop1=imread(strcat('pieces\whitebishop1','.png'));
h.whitebishop2=imread(strcat('pieces\whitebishop2','.png'));
h.blackknight1=imread(strcat('pieces\blackknight1','.png'));
h.blackknight2=imread(strcat('pieces\blackknight2','.png'));
h.whiteknight1=imread(strcat('pieces\whiteknight1','.png'));
h.whiteknight2=imread(strcat('pieces\whiteknight2','.png'));
h.blackqueen1=imread(strcat('pieces\blackqueen1','.png'));
h.blackqueen2=imread(strcat('pieces\blackqueen2','.png'));
h.whitequeen1=imread(strcat('pieces\whitequeen1','.png'));
h.whitequeen2=imread(strcat('pieces\whitequeen2','.png'));
h.blackking1=imread(strcat('pieces\blackking1','.png'));
h.blackking2=imread(strcat('pieces\blackking2','.png'));
h.whiteking1=imread(strcat('pieces\whiteking1','.png'));
h.whiteking2=imread(strcat('pieces\whiteking2','.png'));
h.black=imread(strcat('pieces\black','.png'));
h.white=imread(strcat('pieces\white','.png'));
% deletion of extra rows and colomns
h.blackpawn1(:,60,:)=[];
h.blackpawn2(:,60,:)=[];
h.whitepawn2(:,60,:)=[];
h.blackrook1(:,60,:)=[];
h.blackrook2(:,60,:)=[];
h.whiterook1(:,60,:)=[];
h.whiterook2(:,60,:)=[];
h.blackbishop1(:,60,:)=[];
h.blackbishop2(:,60,:)=[];
h.whitebishop1(:,60,:)=[];
h.whitebishop2(:,60,:)=[];
h.blackknight2(:,60,:)=[];
h.whiteknight2(:,60,:)=[];
h.whitequeen2(:,60,:)=[];
h.black(:,60,:)=[];
h.blackrook1(60,:,:)=[];
h.blackrook2(60,:,:)=[];
h.whiterook1(60,:,:)=[];
h.whiterook2(60,:,:)=[];
h.blackbishop1(60,:,:)=[];
h.blackbishop2(60,:,:)=[];
h.whitebishop1(60,:,:)=[];
h.whitebishop2(60,:,:)=[];
h.blackknight1(60,:,:)=[];
h.blackknight2(60,:,:)=[];
h.whiteknight1(60,:,:)=[];
h.whiteknight2(60,:,:)=[];
h.blackqueen1(60,:,:)=[];
h.whitequeen2(60,:,:)=[];
h.blackking1(60,:,:)=[];
h.blackking2(60,:,:)=[];
h.whiteking1(60,:,:)=[];
h.whiteking2(60,:,:)=[];
h.black(60,:,:)=[];
h.white(60,:,:)=[];

% initializing box;  8x8 box
% rook=2
% horse=3
% bishop=4
% queen=5
% king=10
% pawn=1
h.box=[ ...
    2  3  4  5  10 4  3  2 ; ...
    1  1  1  1  1  1  1  1 ; ...
    0  0  0  0  0  0  0  0  ; ...
    0  0  0  0  0  0  0  0  ; ...
    0  0  0  0  0  0  0  0  ; ...
    0  0  0  0  0  0  0  0  ; ...
    -1 -1 -1 -1 -1 -1 -1 -1 ; ...
    -2 -3 -4 -5 -10 -4 -3 -2  ];
% position variables
h.ipr=0;
h.ipc=0;
h.fpr=0;
h.fpc=0;
h.r=0;
h.c=0;
% showing whose turn......initially player one's turn it can be changed
h.plr=1;
set(ha(1),'CData',h.blackking2);
i=2;
% now initializing figure with player marks
for x=1:8
    for y=1:8
% required when to convert pieces from numbers to uploaded symbols
        if h.box(x,y)==1
            if i==1
                mark=h.blackpawn1;
                i=2;
            elseif i==2
                mark=h.blackpawn2;
                i=1;
            end
        elseif h.box(x,y)==-1
            if i==1
                mark=h.whitepawn1;
                i=2;
            elseif i==2
                mark=h.whitepawn2;
                i=1;
            end
        elseif h.box(x,y)==2
            if i==1
                mark=h.blackrook1;
                i=2;
            elseif i==2
                mark=h.blackrook2;
                i=1;
            end
        elseif h.box(x,y)==-2
            if i==1
                mark=h.whiterook1;
                i=2;
            elseif i==2
                mark=h.whiterook2;
                i=1;
            end
        elseif h.box(x,y)==3
            if i==1
                mark=h.blackknight1;
                i=2;
            elseif i==2
                mark=h.blackknight2;
                i=1;
            end
        elseif h.box(x,y)==-3
            if i==1
                mark=h.whiteknight1;
                i=2;
            elseif i==2
                mark=h.whiteknight2;
                i=1;
            end
        elseif h.box(x,y)==4
            if i==1
                mark=h.blackbishop1;
                i=2;
            elseif i==2
                mark=h.blackbishop2;
                i=1;
            end
        elseif h.box(x,y)==-4
            if i==1
                mark=h.whitebishop1;
                i=2;
            elseif i==2
                mark=h.whitebishop2;
                i=1;
            end
        elseif h.box(x,y)==5
            if i==1
                mark=h.blackqueen1;
                i=2;
            elseif i==2
                mark=h.blackqueen2;
                i=1;
            end
        elseif h.box(x,y)==-5
            if i==1
                mark=h.whitequeen1;
                i=2;
            elseif i==2
                mark=h.whitequeen2;
                i=1;
            end
        elseif h.box(x,y)==10
            if i==1
                mark=h.blackking1;
                i=2;
            elseif i==2
                mark=h.blackking2;
                i=1;
            end
        elseif h.box(x,y)==-10
            if i==1
                mark=h.whiteking1;
                i=2;
            elseif i==2
                mark=h.whiteking2;
                i=1;
            end
        else
            if i==1
                mark=h.black;
                i=2;
            elseif i==2
                mark=h.white;
                i=1;
            end
        end
        rc=x*10+y;
        set(ha(rc),'CData',mark);
    end
%     first row starting from white next row starting from black
    if i==1
        i=2;
    else i=1;
    end

end
%set(CHESS,'Visible','on')
% Update h structure
guidata(hObj, h);

function varargout = CHESS_OutputFcn(hObj, ed, h)
% Get default command line output from h structure
varargout{1} = h.output;

% --- Executes on button press in exit.
function exit_Callback(hObj, ed, h)
% used to close the game anytime
close(gcbf)

% --- Executes during object creation, after setting all properties.
function plrturn_CreateFcn(hObj, ed, h)
if ispc && isequal(get(hObj,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObj,'BackgroundColor','white');
end

% --- Executes on button press in concede.
function concede_Callback(hObj, ed, h)
if h.plr==2
    msgbox('CHESS KING','Winner','custom',h.blackking2)
elseif h.plr==1
    msgbox('CHESS KING','Winner','custom',h.whiteking1)
end
close(gcbf);

function box11_Callback(hObj, ed, h)
global ha
h.r=1;h.c=1;
h=playerturn(ha,h);
guidata(hObj,h);

function box12_Callback(hObj, ed, h)
global ha
h.r=1;h.c=2;
h=playerturn(ha,h);
guidata(hObj,h);

function box13_Callback(hObj, ed, h)
global ha
h.r=1;h.c=3;
h=playerturn(ha,h);
guidata(hObj,h);

function box14_Callback(hObj, ed, h)
global ha
h.r=1;h.c=4;
h=playerturn(ha,h);
guidata(hObj,h);

function box15_Callback(hObj, ed, h)
global ha
h.r=1;h.c=5;
h=playerturn(ha,h);
guidata(hObj,h);

function box16_Callback(hObj, ed, h)
global ha
h.r=1;h.c=6;
h=playerturn(ha,h);
guidata(hObj,h);

function box17_Callback(hObj, ed, h)
global ha
h.r=1;h.c=7;
h=playerturn(ha,h);
guidata(hObj,h);

function box18_Callback(hObj, ed, h)
global ha
h.r=1;h.c=8;
h=playerturn(ha,h);
guidata(hObj,h);

function box21_Callback(hObj, ed, h)
global ha
h.r=2;h.c=1;
h=playerturn(ha,h);
guidata(hObj,h);

function box22_Callback(hObj, ed, h)
global ha
h.r=2;h.c=2;
h=playerturn(ha,h);
guidata(hObj,h);

function box23_Callback(hObj, ed, h)
global ha
h.r=2;h.c=3;
h=playerturn(ha,h);
guidata(hObj,h);

function box24_Callback(hObj, ed, h)
global ha
h.r=2;h.c=4;
h=playerturn(ha,h);
guidata(hObj,h);

function box25_Callback(hObj, ed, h)
global ha
h.r=2;h.c=5;
h=playerturn(ha,h);
guidata(hObj,h);

function box26_Callback(hObj, ed, h)
global ha
h.r=2;h.c=6;
h=playerturn(ha,h);
guidata(hObj,h);

function box27_Callback(hObj, ed, h)
global ha
h.r=2;h.c=7;
h=playerturn(ha,h);
guidata(hObj,h);

function box28_Callback(hObj, ed, h)
global ha
h.r=2;h.c=8;
h=playerturn(ha,h);
guidata(hObj,h);

function box31_Callback(hObj, ed, h)
global ha
h.r=3;h.c=1;
h=playerturn(ha,h);
guidata(hObj,h);

function box32_Callback(hObj, ed, h)
global ha
h.r=3;h.c=2;
h=playerturn(ha,h);
guidata(hObj,h);

function box33_Callback(hObj, ed, h)
global ha
h.r=3;h.c=3;
h=playerturn(ha,h);
guidata(hObj,h);

function box34_Callback(hObj, ed, h)
global ha
h.r=3;h.c=4;
h=playerturn(ha,h);
guidata(hObj,h);

function box35_Callback(hObj, ed, h)
global ha
h.r=3;h.c=5;
h=playerturn(ha,h);
guidata(hObj,h);

function box36_Callback(hObj, ed, h)
global ha
h.r=3;h.c=6;
h=playerturn(ha,h);
guidata(hObj,h);

function box37_Callback(hObj, ed, h)
global ha
h.r=3;h.c=7;
h=playerturn(ha,h);
guidata(hObj,h);

function box38_Callback(hObj, ed, h)
global ha
h.r=3;h.c=8;
h=playerturn(ha,h);
guidata(hObj,h);

function box41_Callback(hObj, ed, h)
global ha
h.r=4;h.c=1;
h=playerturn(ha,h);
guidata(hObj,h);

function box42_Callback(hObj, ed, h)
global ha
h.r=4;h.c=2;
h=playerturn(ha,h);
guidata(hObj,h);

function box43_Callback(hObj, ed, h)
global ha
h.r=4;h.c=3;
h=playerturn(ha,h);
guidata(hObj,h);

function box44_Callback(hObj, ed, h)
global ha
h.r=4;h.c=4;
h=playerturn(ha,h);
guidata(hObj,h);

function box45_Callback(hObj, ed, h)
global ha
h.r=4;h.c=5;
h=playerturn(ha,h);
guidata(hObj,h);

function box46_Callback(hObj, ed, h)
global ha
h.r=4;h.c=6;
h=playerturn(ha,h);
guidata(hObj,h);

function box47_Callback(hObj, ed, h)
global ha
h.r=4;h.c=7;
h=playerturn(ha,h);
guidata(hObj,h);

function box48_Callback(hObj, ed, h)
global ha
h.r=4;h.c=8;
h=playerturn(ha,h);
guidata(hObj,h);

function box51_Callback(hObj, ed, h)
global ha
h.r=5;h.c=1;
h=playerturn(ha,h);
guidata(hObj,h);

function box52_Callback(hObj, ed, h)
global ha
h.r=5;h.c=2;
h=playerturn(ha,h);
guidata(hObj,h);

function box53_Callback(hObj, ed, h)
global ha
h.r=5;h.c=3;
h=playerturn(ha,h);
guidata(hObj,h);

function box54_Callback(hObj, ed, h)
global ha
h.r=5;h.c=4;
h=playerturn(ha,h);
guidata(hObj,h);

function box55_Callback(hObj, ed, h)
global ha
h.r=5;h.c=5;
h=playerturn(ha,h);
guidata(hObj,h);

function box56_Callback(hObj, ed, h)
global ha
h.r=5;h.c=6;
h=playerturn(ha,h);
guidata(hObj,h);

function box57_Callback(hObj, ed, h)
global ha
h.r=5;h.c=7;
h=playerturn(ha,h);
guidata(hObj,h);

function box58_Callback(hObj, ed, h)
global ha
h.r=5;h.c=8;
h=playerturn(ha,h);
guidata(hObj,h);

function box61_Callback(hObj, ed, h)
global ha
h.r=6;h.c=1;
h=playerturn(ha,h);
guidata(hObj,h);

function box62_Callback(hObj, ed, h)
global ha
h.r=6;h.c=2;
h=playerturn(ha,h);
guidata(hObj,h);

function box63_Callback(hObj, ed, h)
global ha
h.r=6;h.c=3;
h=playerturn(ha,h);
guidata(hObj,h);

function box64_Callback(hObj, ed, h)
global ha
h.r=6;h.c=4;
h=playerturn(ha,h);
guidata(hObj,h);

function box65_Callback(hObj, ed, h)
global ha
h.r=6;h.c=5;
h=playerturn(ha,h);
guidata(hObj,h);

function box66_Callback(hObj, ed, h)
global ha
h.r=6;h.c=6;
h=playerturn(ha,h);
guidata(hObj,h);

function box67_Callback(hObj, ed, h)
global ha
h.r=6;h.c=7;
h=playerturn(ha,h);
guidata(hObj,h);

function box68_Callback(hObj, ed, h)
global ha
h.r=6;h.c=8;
h=playerturn(ha,h);
guidata(hObj,h);

function box71_Callback(hObj, ed, h)
global ha
h.r=7;h.c=1;
h=playerturn(ha,h);
guidata(hObj,h);

function box72_Callback(hObj, ed, h)
global ha
h.r=7;h.c=2;
h=playerturn(ha,h);
guidata(hObj,h);

function box73_Callback(hObj, ed, h)
global ha
h.r=7;h.c=3;
h=playerturn(ha,h);
guidata(hObj,h);

function box74_Callback(hObj, ed, h)
global ha
h.r=7;h.c=4;
h=playerturn(ha,h);
guidata(hObj,h);

function box75_Callback(hObj, ed, h)
global ha
h.r=7;h.c=5;
h=playerturn(ha,h);
guidata(hObj,h);

function box76_Callback(hObj, ed, h)
global ha
h.r=7;h.c=6;
h=playerturn(ha,h);
guidata(hObj,h);

function box77_Callback(hObj, ed, h)
global ha
h.r=7;h.c=7;
h=playerturn(ha,h);
guidata(hObj,h);

function box78_Callback(hObj, ed, h)
global ha
h.r=7;h.c=8;
h=playerturn(ha,h);
guidata(hObj,h);

function box81_Callback(hObj, ed, h)
global ha
h.r=8;h.c=1;
h=playerturn(ha,h);
guidata(hObj,h);

function box82_Callback(hObj, ed, h)
global ha
h.r=8;h.c=2;
h=playerturn(ha,h);
guidata(hObj,h);

function box83_Callback(hObj, ed, h)
global ha
h.r=8;h.c=3;
h=playerturn(ha,h);
guidata(hObj,h);

function box84_Callback(hObj, ed, h)
global ha
h.r=8;h.c=4;
h=playerturn(ha,h);
guidata(hObj,h);

function box85_Callback(hObj, ed, h)
global ha
h.r=8;h.c=5;
h=playerturn(ha,h);
guidata(hObj,h);

function box86_Callback(hObj, ed, h)
global ha
h.r=8;h.c=6;
h=playerturn(ha,h);
guidata(hObj,h);

function box87_Callback(hObj, ed, h)
global ha
h.r=8;h.c=7;
h=playerturn(ha,h);
guidata(hObj,h);

function box88_Callback(hObj, ed, h)
global ha
h.r=8;h.c=8;
h=playerturn(ha,h);
guidata(hObj,h);

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


function [IM_result]=display_clust_image(IM,input_mask,fig)
% [IMseg]=display_clust_image(IM,input_mask,fig)
% display image segmentation results:
% input :
%          IM = input image
%          input_mask = segmentation mask
%          fig = matlab figure number for display
%
%  output:
%          IMseg = image with segments marked by different colors
%
%

if( nargin < 3 )
   fig = 0;
end

[height,width,colors] = size(IM);
segNum = max(max(input_mask));

if( size(IM,3) == 1 )
    IM = cat(3,IM,IM,IM);
end

map = [0 0 255; 150 0 255; 255 0 255; 255 0 0; 0 255 255; 0 255 87; 255 255 0; ...
        255 140 0; 128 0 0; 0 0 140; 255 196 125; 170 107 68]/255;
if( size(map,1)<segNum )
    map = hsv(segNum);
end
map_yiq = rgb2ntsc(map);

YIQ = rgb2ntsc(IM);
Y = YIQ(:,:,1);
I = YIQ(:,:,2);
Q = YIQ(:,:,3);
IM_result = ntsc2rgb(cat(3,Y,I,Q));

for i=1:segNum,
    mask = zeros(height,width);
    ind = find(input_mask==i);
    mask(ind) = 1;
    mask = medfilt2(mask);
    mask = medfilt2(mask);
    mask = medfilt2(mask);
    ind = find(mask);
    %%% mark segment boundary in white
    E = edge(mask);
    se = strel('disk',2);
    E = imdilate(E,se,'same');
    ind = find(E);
    %%% white
    Y(ind) = 1;
    I(ind) = 0;
    Q(ind) = 0;
    %%% green
    Y(ind) = 0.587;
    I(ind) = -0.2744;
    Q(ind) = -0.5299;
    %%% red
    Y(ind) = 0.2989;
    I(ind) = 0.5959;
    Q(ind) = 0.2115;
end
IM_result = ntsc2rgb(cat(3,Y,I,Q));
if( fig>0 )
    figure(fig);
    clf;
    imshow(IM_result);
end


% This is a stub with an example of how to attach voxel data, which will
% trigger the calculation of derivatives (region averages)
% This function will likely not be necessary, as the functions can be accomplished
% with listeners - this is an example really.

% img = fmri_data('/Users/torwager/Downloads/smoothed_residual.nii.gz')
% b = brainpathway();

% Resample image space of data to the atlas space
% (We don't want to do it the other way around, because it will make it
% difficult to have a consistent atlas definition and aggregate across
% different datasets)

img_resampled = resample_space(img, b.region_atlas);

% Assign the resampled data to the brainpathway object
% This triggers several steps:
% Updating node and region averages, and node and region connectivity
b.voxel_dat = img_resampled.dat;

% Plot the inter-region connectivity
% plot_connectivity(b);

% Load a different atlas instead, with a different parcellation:
% This triggers updates of the regions and region connectivity
b.region_atlas = load_atlas('yeo17networks');

b = brainpathway(load_atlas('yeo17networks'));
b.voxel_dat = img_resampled.dat;


function test_bug2727

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY ft_clusterplot topoplot_common

%%

label = {
  'MLC11'    'MLC12'    'MLC13'    'MLC14'    'MLC15'    'MLC21'    'MLC22'    'MLC23'    'MLC24'    'MLC31'    'MLC32'    'MLC33'    'MLC41'    'MLC42' ...
  'MLC43'    'MLF11'    'MLF12'    'MLF21'    'MLF22'    'MLF23'    'MLF31'    'MLF32'    'MLF33'    'MLF34'    'MLF41'    'MLF42'    'MLF43'    'MLF44' ...
  'MLF45'    'MLF51'    'MLF52'    'MLO11'    'MLO12'    'MLO21'    'MLO22'    'MLO31'    'MLO32'    'MLO33'    'MLO41'    'MLO42'    'MLO43'    'MLP11' ...
  'MLP12'    'MLP13'    'MLP21'    'MLP22'    'MLP31'    'MLP32'    'MLP33'    'MLP34'    'MLT11'    'MLT12'    'MLT13'    'MLT14'    'MLT15'    'MLT16' ...
  'MLT21'    'MLT22'    'MLT23'    'MLT24'    'MLT25'    'MLT26'    'MLT31'    'MLT32'    'MLT33'    'MLT34'    'MLT35'    'MLT41'    'MLT42'    'MLT43' ...
  'MLT44'    'MRC11'    'MRC12'    'MRC13'    'MRC14'    'MRC15'    'MRC21'    'MRC22'    'MRC23'    'MRC24'    'MRC31'    'MRC32'    'MRC33'    'MRC41' ...
  'MRC42'    'MRC43'    'MRF11'    'MRF12'    'MRF21'    'MRF22'    'MRF23'    'MRF31'    'MRF32'    'MRF33'    'MRF34'    'MRF41'    'MRF42'    'MRF43' ...
  'MRF44'    'MRF45'    'MRF51'    'MRF52'    'MRO11'    'MRO12'    'MRO21'    'MRO22'    'MRO31'    'MRO32'    'MRO33'    'MRO41'    'MRO42'    'MRO43' ...
  'MRP11'    'MRP12'    'MRP13'    'MRP21'    'MRP22'    'MRP31'    'MRP32'    'MRP33'    'MRP34'    'MRT11'    'MRT12'    'MRT13'    'MRT14'    'MRT15' ...
  'MRT16'    'MRT21'    'MRT22'    'MRT23'    'MRT24'    'MRT25'    'MRT26'    'MRT31'    'MRT32'    'MRT33'    'MRT34'    'MRT35'    'MRT41'    'MRT42' ...
  'MRT43'    'MRT44'    'MZC01'    'MZC02'    'MZF01'    'MZF02'    'MZF03'    'MZO01'    'MZO02'    'MZP01'    'MZP02'
  };

stat = [];
stat.label = label;
stat.prob = rand(151,1);
stat.stat = stat.prob;
stat.dimord = 'chan';
stat.posclusterslabelmat = stat.prob<0.05;
stat.posclusters(1).prob = 0;
% stat.posclusters(1).clusterstat = nan;
% stat.posclusters(1).stddev      = nan;
% stat.posclusters(1).cirange     = nan;

statT = [];
statT.label = label;
statT.prob = rand(151,10);
statT.stat = statT.prob;
statT.time = (1:10)/10; % in seconds
statT.dimord = 'chan_time';
statT.posclusterslabelmat = statT.prob<0.05;
statT.posclusters(1).prob = 0;

statF = [];
statF.label = label;
statF.prob = rand(151,20);
statF.stat = statF.prob;
statF.freq = 1:20; % in Hz
statF.dimord = 'chan_freq';
statF.posclusterslabelmat = statF.prob<0.05;
statF.posclusters(1).prob = 0;

statTF = [];
statTF.label = label;
statTF.prob = rand(151,20,10);
statTF.stat = statTF.prob;
statTF.freq = 1:20; % in Hz
statTF.time = (1:10)/10; % in seconds
statTF.dimord = 'chan_freq_time';
statTF.posclusterslabelmat = statTF.prob<0.05;
statTF.posclusters(1).prob = 0;

statT1F = [];
statT1F.label = label;
statT1F.prob = rand(151,20,1);
statT1F.stat = statT1F.prob;
statT1F.freq = 1:20; % in Hz
statT1F.time = 0.5; % in seconds
statT1F.dimord = 'chan_freq_time';
statT1F.posclusterslabelmat = statT1F.prob<0.05;
statT1F.posclusters(1).prob = 0;

statTF1 = [];
statTF1.label = label;
statTF1.prob = rand(151,1,10);
statTF1.stat = statTF1.prob;
statTF1.freq = 1; % in Hz
statTF1.time = (1:10)/10; % in seconds
statTF1.dimord = 'chan_freq_time';
statTF1.posclusterslabelmat = statTF1.prob<0.05;
statTF1.posclusters(1).prob = 0;

%%

cfg = [];
cfg.layout = 'CTF151.lay';
ft_clusterplot(cfg, stat);
ft_clusterplot(cfg, statT);
ft_clusterplot(cfg, statF);
ft_clusterplot(cfg, statTF1); % single frequency
ft_clusterplot(cfg, statT1F); % single latency

try
  figure; ft_clusterplot(cfg, statTF);
  failed = false;
catch
  failed = true;
end
assert(failed==true, 'this should have failed');


function ROI(img, nroi)

% 1) Goal: Draw & process multiple ROIs interactively within an image.
%
% 2) Usage: ROI(img, nroi), where 'img' is your image, and 'nroi' is a
% total number to ROIs to be processed.  The opened image will be processed
% BY DEFAULT.  A prefered procedure is as follows: a) img = imread(...); b)
% imh = imshow(img) and c) ROI(img, nroi).
% Alternatively, if there is no image in your WorkSpace, you MUST use
% square brackets to occupy the argument space for img, such as, ROI([],5),
% will let you open a new image and process with 5 ROIs.
%
% 3) Since getline('closed') is used to get the polygon interactively,
% please click left mouse button to select, and right button to finish up a
% ROI (Backspace to delete the lastest click). You may repeat this process
% till all ROIs were processed.  For more infos, please may see help
% getline.
%
% 4) Results: ROI statistics are displayed on screen or output to a text
% file (optional).
%
% 5) The colors of line/text label are generated by 'jet' colormap,
% therefore, certain color may be too close to tell, especially when you
% select too many ROIs. In that case, you may need to edit the color after
% ROI processing. For more infos, please see help jet.
%
% 6) For your convenience, you may use the following m-scripts to clear
% your enviroments: 'dt', 'dl' and 'df' to delete all text characters,
% lines and figures, respectively.
%
% 7) This package includes 5 m-files: 'ROI.m', 'MultiROI', 'df.m', 'dl.m' and 'dt.m'.
%    MultiROI is similar to ROI. The only difference is that it uses spline
%    interprate to smooth the ROI edge.
%
% Shanrong Zhang
% Department of Radiology
% University of Washington
% 02/09/2004
%
% email: zhangs@u.washington.edu

if nargin == 2

    imh = findobj(0, 'Type', 'Image');

    % if no image opened, open a new one
    if isempty(imh)
        if length(img) == 0
            [infn inpn] = uigetfile('*.*','Please select an image file');
            if infn ~= 0
                img = imread([inpn infn]);
                imh = imshow(img);
                axis image; axis off;
            else
                disp('Cancel by user!')
                return
            end
        else
            imh = imshow(img);
        end
    end

    [nrows, ncols, ncolors] = size(img);

    % Save ROIs to a file (optional)
    SaveIt = questdlg('Do you want to save ROI outputs ?');
    switch SaveIt
        case 'Yes'
            [outfn, outpn] = uiputfile('*', 'Select an output file');
            if outfn == 0
                disp('Cancel by user !');
            else
                fid = fopen([outpn outfn], 'w+');
                fprintf(fid, '%20s\t %-50s\n', 'Date\time = ', datestr(now));
            end
        otherwise
            outfn = 0;
    end

    % generate a jet colormap according to nroi
    cmap = jet(nroi);
    rndp = randperm(nroi);

    hold on;

    croi = 1;

    while croi <= nroi
        [x,y] =getline('closed');

        XData = get(imh, 'XData');
        YData = get(imh, 'YData');
        xmingrid = max( XData(1), floor(min(x)) );
        xmaxgrid = min( XData(2),  ceil(max(x)) );
        ymingrid = max( YData(1), floor(min(y)) );
        ymaxgrid = min( YData(2),  ceil(max(y)) );
        xgrid = xmingrid : xmaxgrid;
        ygrid = ymingrid : ymaxgrid;
        [X, Y] = meshgrid(xgrid, ygrid);
        k_inside = inpolygon(X, Y, x, y);
        Xin = X(k_inside);
        Yin = Y(k_inside);

        cdata = get(imh, 'CData');
        smallcdata = double(cdata(ygrid, xgrid, :));

        roi.index = croi;
        roi.area = polyarea(x,y);
        roi.center =  [mean(Xin(:)), mean(Yin(:))];

        for i=1:ncolors
            roicidata     = smallcdata(:, :, i);
            roi.mean(i)   =   mean(roicidata(k_inside));
            roi.std(i)    =    std(roicidata(k_inside));
            roi.min(i)    =    min(roicidata(k_inside));
            roi.max(i)    =    max(roicidata(k_inside));
            roi.median(i) = median(roicidata(k_inside));
        end;

        plot(x,y,'Color',cmap(rndp(croi), :));
        text(roi.center(1), roi.center(2), num2str(croi), 'Color', cmap(rndp(croi), :), 'FontWeight','Bold');

        % write ROI statistics into file if necessary
        if outfn ~= 0
            fprintf(fid, '\n');
            fprintf(fid, '%20s\t %10.0f\n', 'ROI Index = ', roi.index);

            fprintf(fid, '%20s\t ', 'area = ');
            fprintf(fid, '%10.2f\t', roi.area);
            fprintf(fid, '\n');

            fprintf(fid, '%20s\t ', 'mean = ');
            fprintf(fid, '%10.2f\t', roi.mean);
            fprintf(fid, '\n');

            fprintf(fid, '%20s\t ', 'std = ');
            fprintf(fid, '%10.2f\t', roi.std);
            fprintf(fid, '\n');

            fprintf(fid, '%20s\t ', 'min = ');
            fprintf(fid, '%10.2f\t', roi.min);
            fprintf(fid, '\n');

            fprintf(fid, '%20s\t ', 'max = ');
            fprintf(fid, '%10.2f\t', roi.max);
            fprintf(fid, '\n');

            fprintf(fid, '%20s\t ', 'median = ');
            fprintf(fid, '%10.2f\t', roi.median);
            fprintf(fid, '\n');

            fprintf(fid, '%20s\t ', 'roicenter = ');
            fprintf(fid, '%10.2f\t', roi.center);
            fprintf(fid, '\n');
        end

        disp(' ');
        disp(sprintf('%20s\t %10.0f', 'ROI index = ', roi.index));
        disp(sprintf('%20s\t %10.2f', 'area = ', roi.area));
        disp(sprintf('%20s\t %10.2f\t %10.2f\t %10.2f', 'mean = ', roi.mean) );
        disp(sprintf('%20s\t %10.2f\t %10.2f\t %10.2f', 'std = ',  roi.std) );
        disp(sprintf('%20s\t %10.2f\t %10.2f\t %10.2f', 'min = ', roi.min) );
        disp(sprintf('%20s\t %10.2f\t %10.2f\t %10.2f', 'max = ', roi.max) );
        disp(sprintf('%20s\t %10.2f\t %10.2f\t %10.2f', 'median = ', roi.median) );
        disp(sprintf('%20s\t %10.2f\t %10.2f\t', 'roicenter [x,y] = ', roi.center));
        disp(' ');

        croi = croi + 1;

    end

    if outfn == 0
        disp('Done, but ROI statistics were not saved !!!');
        disp(' ' );
    else
        disp(['Done, ROI statistics been output to ', outfn]);
        disp('But the image with ROI lines/labels was not saved yet !!!');
        fclose(fid);
    end

else
    disp(' ')
    disp('  Number of arguments is incorrect !!!')
    disp(' ')
    help ROI
end

% end of code


function acpc_aligned_nifti = mrAnatAutoAlignAcpcNifti(anatomical_in, anatomical_out)
%
%  acpc_aligned_nifti = mrAnatAutoAlignAcpcNifti(anatomical_in, [anatomical_out])
%
% Generate a ac-pc aligned nifti image using Talairach coordinates
% converted to MNI space.
%
% INPUTS:
%   anatomical_in:	Full path to raw (unaligned) anatomical image
%   anatomical_out:	(optional) Full path for output file. Defaults to
%                   <anatomical_in> + '_acpc.nii.gz'
%
% OUTPUTS:
%   anatomical_out: Full path to the aligned nifti file.
%
% (C) Stanford Vista Lab, 2016
%

%% Handle I/O

if ~exist('anatomical_in','var') || isempty(anatomical_in) || ~exist(anatomical_in, 'file')
    error('No input file was defined.');
end

% If no output file was defined, set to input + '_acpc.nii.gz'
if ~exist('anatomical_out','var') || isempty(anatomical_out)
    base = strsplit(anatomical_in, '.nii');
    [p, f] = fileparts(base{1});
    anatomical_out = fullfile(p, [f, '_acpc.nii.gz']);
end

%% Perform acpc alignment

% The ACPC coordinates in Talairach
ACPC_COORDS = [0,0,0; 0,-16,0; 0,-8,40];

% Read in the file
ni = niftiRead(anatomical_in);

% Apply the cannonical transform
ni = niftiApplyCannonicalXform(ni);

% Use the MNI_T1 template
template =  fullfile(mrDiffusionDir, 'templates', 'MNI_T1.nii.gz');

% Compute the spatial normalization
sn = mrAnatComputeSpmSpatialNorm(ni.data, ni.qto_xyz, template);

% Get the iamge coordinates for the mid-line, ac, and pc
coords = mrAnatGetImageCoordsFromSn(sn, tal2mni(ACPC_COORDS)', true)';

% Use the coords to generate acpc-aligned image
mrAnatAverageAcpcNifti(ni, anatomical_out, coords, [], [], [], false);

%% Check for anatomical_out file

if ~exist(anatomical_out,'file')
    warning('Auto AC-PC Alignment failed.');
else
    acpc_aligned_nifti = anatomical_out;
end


function outputs=run_benchmark(imnames, topchosen, topscores, sptextdir, regspimgdir, sbddir, categids, refineddir)

%first compute all overlaps
overlaps=cell(numel(imnames),1);
for i=1:numel(imnames)
    if(rem(i-1,10)==0) fprintf('Computing overlaps:%d/%d\n',i, numel(imnames)); end
    %read the sprep
    [sp, reg2sp]=read_sprep(fullfile(sptextdir, [imnames{i} '.txt']), fullfile(regspimgdir, [imnames{i} '.png']));

    %load gt
    [cls, inst, categories]=load_gt(sbddir, imnames{i});

    %for each category of interest
    for j=1:numel(categids)
        categ_reg2sp=reg2sp(:,topchosen{categids(j)}{i});

        %if there is refined regions, read them
        if(exist('refineddir', 'var') & ~isempty(topchosen{categids(j)}{i}))
            tmp=load(fullfile(refineddir, int2str(categids(j)), [imnames{i} '.mat']));
            categ_reg2sp=tmp.newreg2sp;
        end

        %compute overlaps
        [overlap, pprecision, precall]=get_gt_overlaps(logical(categ_reg2sp), sp, double(inst));

        overlaps{j}{i}=overlap;
    end
    gt{i}=categories;

end

%now run the evaluation. This is relatively fast once overlaps are precomputed
ap_vol=zeros(9,numel(categids));
for j=1:numel(categids)
    for t=1:9
        outputs(t,j)=generalized_det_eval(imnames, topscores{categids(j)}, overlaps{j}, gt, categids(j), 0.1, 0.1*t);
        ap_vol(t,j)=outputs(t,j).PR.ap;
        fprintf('Evaluated threshold:%f for category:%d\n', 0.1*t, categids(j));
    end
end

%Print out ap_vol for all categories
categ_names_and_groups;
fprintf('Category name \t\t | AP^r\t | AP^r_{vol}\n');
fprintf('_______________________________________________________\n');
for j=1:numel(categids)
    fprintf('%s \t\t | %f\t | %f\n',categnames{categids(j)}, ap_vol(5,j), mean(ap_vol(:,j)));
end
fprintf('_______________________________________________________\n');
fprintf('Mean \t\t | %f\t | %f\n', mean(ap_vol(5,:)), mean(mean(ap_vol,2)));

%we will only work with the 0.5 threshold now
%produce the impact chart
produce_impact_chart_all(outputs(5,:));
output.ap_vol=ap_vol;


hb_setup();

res = rproc.read('scoresroot', ...
  fullfile(hb_path, 'matlab', 'scores', 'scores_all'));

norm_splits = {'c'};
norms_path = fullfile(hb_path, 'matlab', 'data', 'best_normalizations.csv');
norms = readtable(norms_path, 'delimiter', ',');
norms.Properties.RowNames = norms.descriptor;

%%
outpath = fullfile(hb_path, 'matlab', 'results', 'article');
vl_xmkdir(outpath);
addpath(fullfile(hb_path, '../matlab2tikz/src/'));

sequences = utls.listdirs(fullfile(hb_path, 'data', 'hpatches-release'));
illum_seq = cellfun(@(a) strcmp(a(1:2), 'i_'), sequences);
viewp_seq = cellfun(@(a) strcmp(a(1:2), 'v_'), sequences);

categories = cellfun(@(a) a(1), res.matching.sequence, 'Uni', false);
res.matching.category = categories;
% Compute the matching scores averages
res.matching_g = varfun(@mean, res.matching, ...
  'GroupingVariables', {'descriptor', 'geom_noise', 'category'}, ...
  'InputVariables', 'ap');

%% Separate the normalisation type and split out of descriptor name

res.verification_e = rproc.postproc_norm(res.verification);
res.matching_ge = rproc.postproc_norm(res.matching_g);
res.retrieval_e = rproc.postproc_norm(res.retrieval);

%% Compute average over the norm splits
res.verification_en = varfun(@mean, res.verification_e, ...
  'GroupingVariables', {'descriptor', 'split', 'negs', 'geom_noise', 'method', 'norm_type'}, ...
  'InputVariables', 'pr_ap');

res.matching_gen = varfun(@mean, res.matching_ge, ...
  'GroupingVariables', {'descriptor', 'geom_noise', 'category', 'norm_type'}, ...
  'InputVariables', 'mean_ap');

res.retrieval_en = varfun(@mean, res.retrieval_e, ...
  'GroupingVariables', {'descriptor', 'split', 'geom_noise', 'method', 'norm_type'}, ...
  'InputVariables', 'map');

%%

in_c = @(a, b) max(min(a.*b, 1), 0);

normname = 'none';
bnames = {}; cip = 1;  ls = {'EdgeColor', [1, 1, 1] * 0.2};
bnames{end+1} = struct('name', 'meanstd', 'printname', '\meanstd', 'texname', 'MStd', ...
  'color', in_c(utls.rgb('Silver'), cip), 'barargs', {ls}, ...
  'dim', 2, 'isbin', false, 'psize', 65, 'pps', 72479, 'gpu', false, 'normname', normname);
bnames{end+1} = struct('name', 'resize', 'printname', '\resize', 'texname', 'Resz', ...
  'color', in_c(utls.rgb('SlateGray'), cip), 'barargs', {ls}, ...
  'dim', 36, 'isbin', false, 'psize', 65, 'pps', 2583, 'gpu', false, 'normname', normname);

bnames{end+1} = struct('name', 'sift', 'printname', '\sift', 'texname', 'SIFT', ...
  'color', in_c(utls.rgb('SeaGreen'), cip), 'barargs', {ls}, ...
  'dim', 128, 'isbin', false, 'psize', 65, 'pps', 2251, 'gpu', false, 'normname', normname);
bnames{end+1} = struct('name', 'rootsift', 'printname', '\rootsift', 'texname', 'RSIFT', ...
  'color', in_c(utls.rgb('Olive'), cip), 'barargs', {ls}, ...
  'dim', 128, 'isbin', false, 'psize', 65, 'pps', 2157, 'gpu', false, 'normname', normname);

bnames{end+1} = struct('name', 'brief', 'printname', '\brief', 'texname', 'BRIEF', ...
  'color', in_c(utls.rgb('DarkCyan'), cip), 'barargs', {ls},...
  'dim', 256, 'isbin', true, 'psize', 32, 'pps', 1./3e-6, 'gpu', false, 'normname', normname);
bnames{end+1} = struct('name', 'binboost', 'printname', '\binboost', 'texname', 'BBoost', ...
  'color', in_c(utls.rgb('SteelBlue'), cip), 'barargs', {ls},...
  'dim', 256, 'isbin', true, 'psize', 32, 'pps', 1./700e-6, 'gpu', false, 'normname', normname);
bnames{end+1} = struct('name', 'orb', 'printname', '\orb', 'texname', 'ORB', ...
  'color', in_c(utls.rgb('SkyBlue'), cip), 'barargs', {ls}, ...
  'dim', 256, 'isbin', true, 'psize', 32, 'pps', 1./3e-6, 'gpu', false, 'normname', normname);

bnames{end+1} = struct('name', 'siam', 'printname', '\dcsiam', 'texname', 'DC-S', ...
  'color', in_c(utls.rgb('Salmon'), cip), 'barargs', {ls}, ...
  'dim', 256, 'isbin', false, 'psize', 64, 'pps', 1./100e-6, 'gpu', true, 'normname', normname);
bnames{end+1} = struct('name', 'siam2stream', 'printname', '\dcsiamts', 'texname', 'DC-S2S', ...
  'color', in_c(utls.rgb('LightSalmon'), cip), 'barargs', {ls},...
    'dim', 512, 'isbin', false, 'psize', 64, 'pps', 1./200e-6, 'gpu', true, 'normname', normname);
bnames{end+1} = struct('name', 'deepdesc', 'printname', '\deepdesc', 'texname', 'DDesc', ...
  'color', in_c(utls.rgb('BurlyWood'), cip), 'barargs', {ls}, ...
  'dim', 128, 'isbin', false, 'psize', 64, 'pps', 1./500e-6, 'gpu', true, 'normname', normname);
%bnames{end+1} = struct('name', 'tfeat-margin', 'printname', 'tfeat-margin');
bnames{end+1} = struct('name', 'tfeat-margin-star', 'printname', '\tfmargin', 'texname', 'TF-M', ...
  'color', in_c(utls.rgb('Sienna'), cip), 'barargs', {ls}, ...
  'dim', 128, 'isbin', false, 'psize', 32, 'pps', 1./10e-6, 'gpu', true, 'normname', normname);
%bnames{end+1} = struct('name', 'tfeat-ratio', 'printname', 'tf-ratio');
bnames{end+1} = struct('name', 'tfeat-ratio-star', 'printname', '\tfratio', 'texname', 'TF-R', ...
  'color', in_c(utls.rgb('Chocolate'), cip), 'barargs', {ls}, ...
  'dim', 128, 'isbin', false, 'psize', 32, 'pps', 1./10e-6, 'gpu', true, 'normname', normname);

bnames = cell2mat(bnames);

baselines = struct('name', {bnames.name}, 'printname', {bnames.printname}, ...
  'color', {bnames.color}, ...
  'bararg', {bnames.barargs}, 'normname', {bnames.normname});

baselines_chance = struct('name', 'chance', 'printname', '\chance', ...
  'color', in_c(utls.rgb('White'), cip), 'bararg', {ls});
clear normname;
bnames_pca = {}; cip = 1; ls = {'EdgeColor', [1, 1, 1] * 0, 'LineStyle', '--'};
%bnames_pca{end+1} = struct('name', 'meanstd_norm', 'printname', '+meanstd');
%bnames_pca{end+1} = struct('name', 'resize_norm', 'printname', '+resize');
bnames_pca{end+1} = struct('name', 'sift', 'printname', '\psift', 'texname', '+SIFT', ...
  'color', in_c(utls.rgb('SeaGreen'), cip), 'barargs', {ls}, 'normname', norms{'sift', 'normstr'}{1});
bnames_pca{end+1} = struct('name', 'rootsift', 'printname', '\prootsift', 'texname', '+RSIFT', ...
  'color', in_c(utls.rgb('Olive'), cip), 'barargs', {ls}, ...
  'normname', norms{'rootsift', 'normstr'}{1});

bnames_pca{end+1} = struct('name', 'siam', 'printname', '\pdcsiam', 'texname', '+DC-S', ...
  'color', in_c(utls.rgb('Salmon'), cip), 'barargs',{ls}, ...
  'normname', norms{'siam', 'normstr'}{1});
bnames_pca{end+1} = struct('name', 'siam2stream', ...
  'printname', '\pdcsiamts', 'texname', '+DC-S2S', ...
  'color', in_c(utls.rgb('LightSalmon'), cip), 'barargs', {ls}, ...
  'normname', norms{'siam2stream', 'normstr'}{1});
%bnames_pca{end+1} = struct('name', 'siam2stream_norm', 'printname', '+dc-siam2stream');
bnames_pca{end+1} = struct('name', 'deepdesc', ...
  'printname', '\pdeepdesc', 'texname', '+DDesc', ...
  'color', in_c(utls.rgb('BurlyWood'), cip), 'barargs', {ls}, ...
  'normname', norms{'deepdesc', 'normstr'}{1});
%bnames_pca{end+1} = struct('name', 'tfeat-margin_norm', 'printname', '+tf-margin');
bnames_pca{end+1} = struct('name', 'tfeat-margin-star', ...
  'printname', '\ptfmargin', 'texname', '+TF-M', ...
  'color', in_c(utls.rgb('Sienna'), cip), 'barargs', {ls}, ...
  'normname', norms{'tfeat-margin-star', 'normstr'}{1});
%bnames_pca{end+1} = struct('name', 'tfeat-ratio_norm', 'printname', '+tf-ratio');
bnames_pca{end+1} = struct('name', 'tfeat-ratio-star', 'printname', '\ptfratio', 'texname', '+TF-R', ...
  'color', in_c(utls.rgb('Chocolate'), cip), 'barargs', {ls}, ...
  'normname', norms{'tfeat-ratio-star', 'normstr'}{1});
bnames_pca = cell2mat(bnames_pca);

baselines_pca = struct('name', {bnames_pca.name}, 'printname', {bnames_pca.printname}, ...
  'color', {bnames_pca.color}, ...
  'bararg', {bnames_pca.barargs}, 'normname', {bnames_pca.normname});

det_sets = {};

%det_sets{end+1}.dets = baselines;
%det_sets{end}.detnames = {bnames.printname};
%det_sets{end}.name = 'baselines';

%det_sets{end+1}.dets = baselines_pca;
%det_sets{end}.detnames = {bnames_pca.printname};
%det_sets{end}.name = 'baselines-pca';

det_sets{end+1}.dets = [baselines, baselines_pca];
det_sets{end}.detnames = [{bnames.printname}, {bnames_pca.printname}];
det_sets{end}.name = 'baselines-all';

%det_sets{end+1}.dets = [baselines, baselines_pca, baselines_chance];
%det_sets{end}.detnames = [{bnames.printname}, {bnames_pca.printname}, {baselines_chance.printname}];
%det_sets{end}.name = 'baselines-all-chance';

det_sets = cell2mat(det_sets);

task_clrs = [0,136,55; 94,60,153; 202,0,32] ./ 256;
%cl_tasks = {'full_diffseq_easy', 'full_diffseq_hard', 'full_diffseq_tough', 'full_sameseq_easy', 'full_sameseq_hard', 'full_sameseq_tough'};
marker_opts = {'LineWidth', 0.5, 'MarkerSize', 3};
mop = 1; mfp = 0.4;
cl_tasks = {...
  struct('filter', struct('split', 'full', 'negs', 'inter', 'geom_noise', 'easy', 'method', 'imbalanced'), 'style', ...
    {{'Marker', '*', 'Color', in_c(task_clrs(1, :), mop), 'MarkerFaceColor', in_c(task_clrs(1, :), mfp), marker_opts{:}}}), ... % full_diffseq_easy
  struct('filter', struct('split', 'full', 'negs', 'inter', 'geom_noise', 'hard', 'method', 'imbalanced'), 'style', ...
    {{'Marker', '*', 'Color', in_c(task_clrs(2, :), mop), 'MarkerFaceColor', in_c(task_clrs(2, :), mfp), marker_opts{:}}}), ... % full_diffseq_hard
  struct('filter', struct('split', 'full', 'negs', 'inter', 'geom_noise', 'tough', 'method', 'imbalanced'), 'style', ...
    {{'Marker', '*', 'Color', in_c(task_clrs(3, :), mop), 'MarkerFaceColor', in_c(task_clrs(3, :), mfp), marker_opts{:}}}), ... % full_diffseq_tough
  struct('filter', struct('split', 'full', 'negs', 'intra', 'geom_noise', 'easy', 'method', 'imbalanced'), 'style', ...
    {{'Marker', 'd', 'Color', in_c(task_clrs(1, :), mop), 'MarkerFaceColor', in_c(task_clrs(1, :), mfp), marker_opts{:}, 'MarkerSize', 1.5}}), ... % full_sameseq_easy
  struct('filter', struct('split', 'full', 'negs', 'intra', 'geom_noise', 'hard', 'method', 'imbalanced'), 'style', ...
    {{'Marker', 'd', 'Color', in_c(task_clrs(2, :), mop), 'MarkerFaceColor', in_c(task_clrs(2, :), mfp), marker_opts{:}, 'MarkerSize', 1.5}}), ... % full_sameseq_hard
  struct('filter', struct('split', 'full', 'negs', 'intra', 'geom_noise', 'tough', 'method', 'imbalanced'), 'style', ...
    {{'Marker', 'd', 'Color', in_c(task_clrs(3, :), mop), 'MarkerFaceColor', in_c(task_clrs(3, :), mfp), marker_opts{:}, 'MarkerSize', 1.5}})  ... % full_sameseq_tough
};
cl_tasks = cell2mat(cl_tasks);
marker_opts = {'LineWidth', 0.5, 'MarkerSize', 4};

%m_tasks = {...
%  'full_easy_illum', 'full_easy_viewpoint', 'full_hard_illum', 'full_hard_viewpoint', ...
%  'full_tough_illum', 'full_tough_viewpoint'};
m_tasks = {...
  struct('filter', struct('geom_noise', 'easy', 'category', 'i'), 'style', ...
    {{'Marker', 'x', 'Color', in_c(task_clrs(1, :), mop), 'MarkerFaceColor', in_c(task_clrs(1, :), mfp), marker_opts{:}}}), ... % full_easy_illum
  struct('filter', struct('geom_noise', 'easy', 'category', 'v'), 'style', ...
    {{'Marker', '<', 'Color', in_c(task_clrs(1, :), mop), 'MarkerFaceColor', in_c(task_clrs(1, :), mfp), marker_opts{:}}}), ... % full_easy_viewpoint
  struct('filter', struct('geom_noise', 'hard', 'category', 'i'), 'style', ...
    {{'Marker', 'x', 'Color', in_c(task_clrs(2, :), mop), 'MarkerFaceColor', in_c(task_clrs(2, :), mfp), marker_opts{:}}}), ... % full_hard_illum
  struct('filter', struct('geom_noise', 'hard', 'category', 'v'), 'style', ...
    {{'Marker', '<', 'Color', in_c(task_clrs(2, :), mop), 'MarkerFaceColor', in_c(task_clrs(2, :), mfp), marker_opts{:}}}), ... % full_hard_viewpoint
  struct('filter', struct('geom_noise', 'tough', 'category', 'i'), 'style', ...
    {{'Marker', 'x', 'Color', in_c(task_clrs(3, :), mop), 'MarkerFaceColor', in_c(task_clrs(3, :), mfp), marker_opts{:}}}), ... % full_tough_illum
  struct('filter', struct('geom_noise', 'tough', 'category', 'v'), 'style', ...
    {{'Marker', '<', 'Color', in_c(task_clrs(3, :), mop), 'MarkerFaceColor', in_c(task_clrs(3, :), mfp), marker_opts{:}}})  ... % full_tough_viewpoint
  };
m_tasks = cell2mat(m_tasks);

marker_opts = {'LineWidth', 0.5, 'MarkerSize', 3};
%r_tasks = {'full_easy_5s', 'full_easy_40s', ...
%  'full_hard_5s', 'full_hard_40s', 'full_tough_5s', 'full_tough_40s'};
method = 'removequery';
%method = 'keepquery';

r_tasks = {...
%  struct('filter', struct('split', 'small', 'geom_noise', 'easy', 'method', method), 'style', ...
%    {{'Marker', '.', 'Color', in_c(task_clrs(1, :), mop), 'MarkerFaceColor', in_c(task_clrs(1, :), mfp), marker_opts{:}, 'MarkerSize', 4}}), ... % full_easy_5s
  struct('filter', struct('split', 'full', 'geom_noise', 'easy', 'method', method), 'style', ...
    {{'Marker', 'o', 'Color', in_c(task_clrs(1, :), mop), 'MarkerFaceColor', in_c(task_clrs(1, :), mfp), marker_opts{:}, 'MarkerSize', 3}}), ... % full_easy_40s
%  struct('filter', struct('split', 'small', 'geom_noise', 'hard', 'method', method), 'style', ...
%    {{'Marker', '.', 'Color', in_c(task_clrs(2, :), mop), 'MarkerFaceColor', in_c(task_clrs(2, :), mfp), marker_opts{:}, 'MarkerSize', 4}}), ... % full_hard_5s
  struct('filter', struct('split', 'full', 'geom_noise', 'hard', 'method', method), 'style', ...
    {{'Marker', 'o', 'Color', in_c(task_clrs(2, :), mop), 'MarkerFaceColor', in_c(task_clrs(2, :), mfp), marker_opts{:}, 'MarkerSize', 3}}), ... % full_hard_40s
%  struct('filter', struct('split', 'small', 'geom_noise', 'tough', 'method', method), 'style', ...
%    {{'Marker', '.', 'Color', in_c(task_clrs(3, :), mop), 'MarkerFaceColor', in_c(task_clrs(3, :), mfp), marker_opts{:}, 'MarkerSize', 4}}), ... % full_tough_5s
  struct('filter', struct('split', 'full', 'geom_noise', 'tough', 'method', method), 'style', ...
    {{'Marker', 'o', 'Color', in_c(task_clrs(3, :), mop), 'MarkerFaceColor', in_c(task_clrs(3, :), mfp), marker_opts{:}, 'MarkerSize', 3}})  ... % full_tough_40s
  };

r_tasks = cell2mat(r_tasks);
%% Export the Figures

% Verification
ps = 2;
for dsi = 1:numel(det_sets)
  figure(101); clf;
  detnames = det_sets(dsi).detnames;
  rproc.bar_plot(res.verification_en, 'mean_pr_ap', ...
    cl_tasks, det_sets(dsi).dets, 'detnames', detnames, ...
    'legend', false);
  xlabel('Patch Verification mAP [%]');
  %set(gcf, 'Position', get(0, 'Screensize')); % Maximize figure.
  drawnow;
  vl_printsize(ps);
  out_im_path = fullfile(outpath, sprintf('verif_%s.png', ...
      det_sets(dsi).name));
  %print('-dpng', out_im_path, '-r200');
  matlab2tikz(fullfile(outpath, sprintf('verif_%s.tikz', ...
      det_sets(dsi).name)), 'showInfo', false, ...
      'width', '\figW', 'height', '\figH', 'interpretTickLabelsAsTex', false);
end

%% Matching

for dsi = 1:numel(det_sets)
  figure(102); clf;
  detnames = det_sets(dsi).detnames;
  rproc.bar_plot(res.matching_gen, 'mean_mean_ap', ...
    m_tasks, det_sets(dsi).dets, 'detnames', detnames, ...
    'legend', false);
  xlabel('Image Matching mAP [%]');
  drawnow;
  vl_printsize(ps);
  out_im_path = fullfile(outpath, sprintf('matching_%s.png', ...
    det_sets(dsi).name));
  %print('-dpng', out_im_path, '-r200');
  matlab2tikz(fullfile(outpath, sprintf('matching_%s.tikz', ...
    det_sets(dsi).name)), 'showInfo', false, ...
    'width', '\figW', 'height', '\figH', 'interpretTickLabelsAsTex', false);
end

%% Retrieval
for dsi = 1:numel(det_sets)
  figure(103); clf;
  detnames = det_sets(dsi).detnames;
  rproc.bar_plot(res.retrieval_en, 'mean_map', ...
    r_tasks, det_sets(dsi).dets, 'detnames', detnames, ...
    'legend', false);
  xlabel('Patch Retrieval mAP [%]');
  drawnow;
  vl_printsize(ps);
  out_im_path = fullfile(outpath, ...
    sprintf('retr_patch_%s.png', det_sets(dsi).name));
  %print('-dpng', out_im_path, '-r200');
  matlab2tikz(fullfile(outpath, sprintf('retr_patch_%s.tikz', ...
    det_sets(dsi).name)), 'showInfo', false, ...
    'width', '\figW', 'height', '\figH', 'interpretTickLabelsAsTex', false);
end


% Shear Waves And Critical Angle Reflection Example
%
% This example illustrates Snell's law for elastic media using a weakly
% focused ultrasound transducer incident on a soft-tissue / bone interface.
% It builds on the Explosive Source In A Layered Medium and Snell's Law And
% Critical Angle Reflection examples.
%
% author: Bradley Treeby
% date: 14th Nov 2013
% last update: 15th February 2014
%
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009-2014 Bradley Treeby and Ben Cox

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

clear all;

% =========================================================================
% SIMULATION PARAMETERS
% =========================================================================

% change scale to 2 to reproduce the higher resolution figures used in the
% help file
scale = 1;

% create the computational grid
PML_size = 10;               % size of the PML in grid points
Nx = 128*scale - 2*PML_size; % number of grid points in the x direction
Ny = 192*scale - 2*PML_size; % number of grid points in the y direction
dx = 0.1e-3/scale;           % grid point spacing in the x direction [m]
dy = 0.1e-3/scale;           % grid point spacing in the y direction [m]
kgrid = makeGrid(Nx, dx, Ny, dy);

% define the medium properties
cp1 = 1540;         % compressional wave speed [m/s]
cs1 = 0;            % shear wave speed [m/s]
rho1 = 1000;        % density [kg/m^3]
alpha0_p1 = 0.1;    % compressional wave absorption [dB/(MHz^2 cm)]
alpha0_s1 = 0.1;    % shear wave absorption [dB/(MHz^2 cm)]

cp2 = 3000;         % compressional wave speed [m/s]
cs2 = 1400;         % shear wave speed [m/s]
rho2 = 1850;        % density [kg/m^3]
alpha0_p2 = 1;      % compressional wave absorption [dB/(MHz^2 cm)]
alpha0_s2 = 1;      % shear wave absorption [dB/(MHz^2 cm)]

% create the time array
cfl   = 0.1;
t_end = 12e-6;
kgrid.t_array= makeTime(kgrid, cp1, cfl, t_end);

% define position of heterogeneous slab
slab = zeros(Nx, Ny);
slab(Nx/2:Nx, :) = 1;

% define the source properties
source_freq = 2e6;              % [Hz]
source_strength = 1e6;          % [Pa]
source_cycles = 3;              % number of tone burst cycles
source_focus_dist = 5*scale;    % position of focus inside slab [grid points]
source_slab_dist = 5*scale;     % distance between source and slab [grid points]
source_mask = makeCircle(Nx, Ny, Nx/2 + source_focus_dist, Ny/2, 50*scale, pi/3);
source_mask(Nx/2 - source_slab_dist:end, :) = 0;

% define the sensor to record the maximum particle velocity everywhere
sensor.record = {'u_max_all'};

% set the input arguments
input_args = {'PMLSize', PML_size, 'PMLAlpha', 2, 'PlotPML', false, ...
    'PMLInside', false, 'PlotScale', [-1, 1]*source_strength, ...
    'DisplayMask', 'off', 'DataCast', 'single'};

% =========================================================================
% FLUID SIMULATION
% =========================================================================

% assign the medium properties
medium.sound_speed            = cp1*ones(Nx, Ny);
medium.sound_speed(slab == 1) = cp2;
medium.density                = rho1*ones(Nx, Ny);
medium.density(slab == 1)     = rho2;
medium.alpha_coeff            = alpha0_p1*ones(Nx, Ny);
medium.alpha_coeff(slab == 1) = alpha0_p2;
medium.alpha_power            = 2;

% assign the source
source.p_mask = source_mask;
source.p = source_strength*toneBurst(1/kgrid.dt, source_freq, source_cycles);

% run the fluid simulation
sensor_data_fluid = kspaceFirstOrder2D(kgrid, medium, source, sensor, input_args{:});

% =========================================================================
% ELASTIC SIMULATION
% =========================================================================

% define the medium properties
clear medium
medium.sound_speed_compression            = cp1*ones(Nx, Ny);
medium.sound_speed_compression(slab == 1) = cp2;
medium.sound_speed_shear                  = cs1*ones(Nx, Ny);
medium.sound_speed_shear(slab == 1)       = cs2;
medium.density                            = rho1*ones(Nx, Ny);
medium.density(slab == 1)                 = rho2;
medium.alpha_coeff_compression            = alpha0_p1*ones(Nx, Ny);
medium.alpha_coeff_compression(slab == 1) = alpha0_p2;
medium.alpha_coeff_shear                  = alpha0_s1*ones(Nx, Ny);
medium.alpha_coeff_shear(slab == 1)       = alpha0_s2;

% assign the source
clear source
source.s_mask = source_mask;
source.sxx = -source_strength*toneBurst(1/kgrid.dt, source_freq, source_cycles);
source.syy = source.sxx;

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

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

% define plot vector
x_vec = kgrid.x_vec(1 + PML_size:end - PML_size)*1e3;
y_vec = kgrid.y_vec(1 + PML_size:end - PML_size)*1e3;

% calculate square of velocity magnitude
u_e = sensor_data_elastic.ux_max_all.^2 + sensor_data_elastic.uy_max_all.^2;
u_f = sensor_data_fluid.ux_max_all.^2 + sensor_data_fluid.uy_max_all.^2;

% plot layout
figure;
imagesc(y_vec, x_vec, double(source_mask | slab));
xlabel('y [mm]');
ylabel('x [mm]');
axis image;
colormap(flipud(gray));

% plot beam patterns
figure;
subplot(2, 1, 1);
imagesc(y_vec, x_vec, 20*log10(u_f./max(u_f(:))));
xlabel('y [mm]');
ylabel('x [mm]');
axis image;
colorbar;
caxis([-50, 0]);
title('Fluid Model');

subplot(2, 1, 2);
imagesc(y_vec, x_vec, 20*log10(u_e./max(u_e(:))));
xlabel('y [mm]');
ylabel('x [mm]');
axis image;
colorbar;
caxis([-50, 0]);
title('Elastic Model');
colormap(jet(256));