function D = spm_eeg_contrast(S)
% Compute contrasts over trials or trial types
% FORMAT D = spm_eeg_contrast(S)
%
% S         - optional input struct
% fields of S:
% D         - filename of EEG mat-file with epoched data
% c         - contrast matrix, each row computes a contrast of the data
% label     - cell array of labels for the contrasts, the same size as
%             number of rows in c
% weighted  - flag whether average should be weighted by number of
%             replications (yes (1), no (0))
% prefix    - prefix for the output file [default: 'w']
%
% Output:
% D         - EEG data struct (also written to disk)
%__________________________________________________________________________
%
% spm_eeg_contrast computes contrasts of data, over epochs of data. The
% input is a single MEEG file. The argument c must have dimensions
% Ncontrasts X Nepochs, where Ncontrasts is the number of contrasts and
% Nepochs the number of epochs, i.e. each row of c contains one contrast
% vector. The output is a M/EEG file with Ncontrasts epochs. The typical
% use is to compute, for display purposes, contrasts like the difference or
% interaction between trial types in channel space.
%__________________________________________________________________________
% Copyright (C) 2008-2017 Wellcome Trust Centre for Neuroimaging

% Stefan Kiebel, Rik Henson
% $Id: spm_eeg_contrast.m 7132 2017-07-10 16:22:58Z guillaume $

SVNrev = '$Rev: 7132 $';

%-Startup
%--------------------------------------------------------------------------
spm('FnBanner', mfilename, SVNrev);
spm('FigName','M/EEG Contrast'); spm('Pointer','Watch');

%-Get MEEG object
%--------------------------------------------------------------------------
if ~isfield(S, 'prefix'),       S.prefix     = 'w';          end
if ~isfield(S, 'weighted'),     S.weighted   =  0;           end

if ~(isfield(S, 'c') && isfield(S, 'label') && numel(S.label)==size(S.c, 1))
    error('Invalid contrast specification.');
end

D = spm_eeg_load(S.D);

%-Compute contrasts
%--------------------------------------------------------------------------

c          = S.c;
Ncontrasts = size(c, 1);

% Pad with zeros as in the contrast manager
if size(c, 2) ~= D.ntrials
    error('The number of columns in the contrast matrix does not match the number of trials.');
end

if ~isempty(D.repl)
    weighted = S.weighted;
else
    weighted = 0;
end

if strncmp(D.transformtype, 'TF', 2)
    Dnew = clone(D, [S.prefix fname(D)], [D.nchannels D.nfrequencies D.nsamples Ncontrasts]);
else
    Dnew = clone(D,  [S.prefix fname(D)],[D.nchannels D.nsamples Ncontrasts]);
end

spm_progress_bar('Init', Ncontrasts, 'Contrasts computed');
if Ncontrasts > 100, Ibar = floor(linspace(1, Ncontrasts, 100));
else Ibar = 1:Ncontrasts; end

for i = 1:Ncontrasts

    if weighted
        p = find(c(i,:) == 1);
        if ~isempty(p)
            r = D.repl(p);
            c(i,p) = r/sum(r);
        end

        p = find(c(i,:) == -1);
        if ~isempty(p)
            r = D.repl(p);
            c(i,p) = -r/sum(r);
        end
    end

    disp(['Contrast ', mat2str(i),': ', mat2str(c(i,:),3)])

    if strncmp(D.transformtype, 'TF', 2)
        d = zeros(D.nchannels, D.nfrequencies, D.nsamples);

        for j = 1:D.nchannels
            for f = 1:D.nfrequencies
                d(j, f, :) = c(i,:) * spm_squeeze(D(j, f, :, :), [1 2 4])';
            end
        end

        Dnew(1:Dnew.nchannels, 1:D.nfrequencies, 1:Dnew.nsamples, i) = d;

    else

        d = zeros(D.nchannels, D.nsamples);

        for j = 1:D.nchannels
            d(j, :) = c(i,:) * squeeze(D(j, :, :))';
        end

        Dnew(1:Dnew.nchannels, 1:Dnew.nsamples, i) = d;
    end

    newrepl(i) = sum(D.repl(find(c(i,:)~=0)));

    if any(Ibar == i), spm_progress_bar('Set', i); end

end

spm_progress_bar('Clear');

%-
%--------------------------------------------------------------------------
Dnew = conditions(Dnew, ':', S.label);
Dnew = trialonset(Dnew, ':', []);
Dnew = trialtag(Dnew, ':', []);
Dnew = badtrials(Dnew, ':', 0);
Dnew = repl(Dnew, ':', newrepl);
Dnew = type(Dnew, 'evoked');

% remove previous source reconsructions
if isfield(Dnew,'inv')
    Dnew = rmfield(Dnew,'inv');
end

%-Save new M/EEG data
%--------------------------------------------------------------------------
D = Dnew;
D = D.history('spm_eeg_contrast', S);
save(D);

%-Cleanup
%--------------------------------------------------------------------------
spm('FigName','M/EEG Contrast: done'); spm('Pointer','Arrow');


% std_stat() - compute statistics for ERP/spectral traces or ERSP/ITC images
%              of a component or channel cluster in a STUDY.
% Usage:
%          >> std_stat( data, 'key', 'val', ...)
% Inputs:
%  data  -  [cell array] mean data for each subject group and/or data
%           condition. For example, to compute mean ERPs statistics from a
%           STUDY for epochs of 800 frames in two conditions from three
%           groups of 12 subjects:
%
%           >> data = { [800x12] [800x12] [800x12];... % 3 groups, cond 1
%                       [800x12] [800x12] [800x12] };  % 3 groups, cond 2
%           >> pcond = std_stat(data, 'condstats', 'on');
%
%           By default, parametric statistics are computed across subjects
%           in the three groups. See below and >> help statcond
%           for more information about the statistical computations.
%
% Statistics options:
%  'groupstats'  - ['on'|'off'] Compute (or not) statistics across groups.
%                  {default: 'off'}
%  'condstats'   - ['on'|'off'] Compute (or not) statistics across groups.
%                  {default: 'off'}
%  'statistics'  - ['param'|'perm'] Type of statistics to use: 'param' for
%                  parametric; 'perm' for permutations {default: 'param'}
%  'naccu'       - [integer] Number of surrogate averges fo accumulate when
%                  computing permutation-based statistics. For example, to
%                  test p<0.01 use naccu>=200; for p<0.001, use naccu>=2000.
%                  If a non-NaN 'threshold' is set (see below) and 'naccu'
%                  is too low, it will be automatically increased. This
%                  keyword available only from the command line {default:500}
%  'threshold'   - [NaN|p-value] threshold for computing p-value. In this
%                  function, it is only used to compute naccu above. NaN
%                  means that no threshold has been set.
%  'mcorrect'    - ['none'|'fdr'] apply correcting for multiple comparisons.
%
% Outputs:
%  pcond        - [cell] condition pvalues or mask (0 or 1). One element per group.
%  pgroup       - [cell] group pvalues or mask (0 or 1). One element per condition.
%  pinter       - [cell] three elements, condition pvalues (group pooled),
%                 group pvalues (condition pooled) and interaction pvalues.
%
% Author: Arnaud Delorme, CERCO, CNRS, 2006-
%
% See also: statcond()

%  'statmode'    - ['subjects'|'trials'] standard statistics are
%                  'subjects' where the statistics is performed accross
%                  the mean ERSP (or ITC) of single subjects. For 'trials'
%                  statistics, the single-trial data epochs of all subjects
%                  are pooled together. This requires that they were
%                  saved on disk using option 'savetrials', 'on' at the time
%                  of computation. Note that these single-trial data
%                  may use several GB of disk space and that computation
%                  of 'trials' statistics requires a lot of RAM.

function [pcond, pgroup, pinter] = std_stat(data, varargin)

pgroup = {};
pcond  = {};
pinter = {};
if nargin < 1
    help std_stat;
    return;
end;

% decode inputs
% -------------
opt = {};
if nargin > 1
    if isstruct(varargin{1})
        g = struct(varargin{2:end});
        if isfield(g, 'condstats'),  varargin{1} = rmfield(varargin{1}, 'condstats'); end;
        if isfield(g, 'groupstats'), varargin{1} = rmfield(varargin{1}, 'groupstats'); end;
        tmpparams      = fieldnames(varargin{1}); tmpparams = tmpparams';
        tmpparams(2,:) = struct2cell(varargin{1});
        varargin       = { tmpparams{:} varargin{2:end} };
    end;
end;
opt = finputcheck( varargin, { 'threshold'   'real'    []               NaN;
                               'mcorrect'    'string'  { 'none' 'fdr' } 'none';
                               'naccu'       'integer' []               [];
                               'groupstats'  'string'  { 'on' 'off' }   'off';
                               'paired'      'cell'    { 'on' 'off' }   { 'on' 'on' };
                               'condstats'   'string'  { 'on' 'off' }   'off';
                               'statistics'  'string'  { 'param' 'perm' 'bootstrap' }       'param' }, ...
                               'std_stat', 'ignore');

if isstr(opt), error(opt); end;
if ~isnan(opt.threshold(1)) && isempty(opt.naccu), opt.naccu = 1/opt.threshold(end)*2; end;
if any(any(cellfun('size', data, 2)==1)), opt.groupstats = 'off'; opt.condstats = 'off'; end;
if strcmpi(opt.mcorrect, 'fdr'), opt.naccu = opt.naccu*20; end;
if isempty(opt.naccu), opt.naccu = 2000; end;
if strcmpi(opt.statistics, 'param') && ~isreal(data{1})
    fprintf('*** Cannot use parametric statistics for single-trial ITC significance ***\n');
    return;
end;
nc = size(data,1);
ng = size(data,2);

% compute significance mask
% --------------------------
if strcmpi(opt.condstats, 'on') && nc > 1
    for g = 1:ng
        [F df pval] = statcond(data(:,g), 'mode', opt.statistics, 'naccu', opt.naccu, 'paired', opt.paired{1});
        pcond{g} = squeeze(pval);
    end;
else
    pcond = {};
end;
if strcmpi(opt.groupstats, 'on') && ng > 1
    for c = 1:nc
        [F df pval] = statcond(data(c,:), 'mode', opt.statistics, 'naccu', opt.naccu, 'paired', opt.paired{2});
        pgroup{c} = squeeze(pval);
    end;
else
    pgroup = {};
end;
if ( strcmpi(opt.groupstats, 'on') && strcmpi(opt.condstats, 'on') ) & ng > 1 & nc > 1
    opt.paired = sort(opt.paired); % put 'off' first if present
    [F df pval] = statcond(data, 'mode', opt.statistics, 'naccu', opt.naccu, 'paired', opt.paired{1});
    for index = 1:length(pval)
        pinter{index} = squeeze(pval{index});
    end;
else
    pinter = {};
end;

if ~isempty(opt.groupstats) || ~isempty(opt.condstats)
    if strcmpi(opt.mcorrect, 'fdr'),
        disp('Applying FDR correction for multiple comparisons');
        for ind = 1:length(pcond),  pcond{ind} = fdr( pcond{ind} ); end;
        for ind = 1:length(pgroup), pgroup{ind} = fdr( pgroup{ind} ); end;
        if ~isempty(pinter),
            pinter{1} = fdr(pinter{1});
            pinter{2} = fdr(pinter{2});
            pinter{3} = fdr(pinter{3});
        end;
    end;
    if ~isnan(opt.threshold)
        for ind = 1:length(pcond),  pcond{ind}  = applythreshold(pcond{ind},  opt.threshold); end;
        for ind = 1:length(pgroup), pgroup{ind} = applythreshold(pgroup{ind}, opt.threshold); end;
        for ind = 1:length(pinter), pinter{ind} = applythreshold(pinter{ind}, opt.threshold); end;
    end;
end;

function newdata = applythreshold(data, threshold)
    threshold = sort(threshold);
    newdata = zeros(size(data));
    for index = 1:length(threshold)
        inds = data < threshold(index);
        data(inds)    = 1;
        newdata(inds) = length(threshold)-index+1;
    end;


function gammaM = createGammaDose(doseNum1,doseNum2,strNum,doseAgreement,...
    distAgreement,thresholdPercentMax,maxDistanceFactor,doseDiffMethod,planC)
% function gammaM = createGammaDose(doseNum1,doseNum2,strNum,...
% doseAgreement,distAgreement,thresholdPercentMax,maxDistanceFactor,doseDiffMethod,planC);
%
% This function creates and adds a gamma dose to planC.
% 3D Gamma is calculated between doseNum1 and doseNum2.
% dosePercent is the dose criteria based on max(doseNum1).
% doseAgreement = max(doseNum1)*dosePercent/100;
% distAgreement is in cm.
%
% APA, 04/26/2012

if ~exist('planC','var')
    global planC
end

indexS = planC{end};

% Prepare inputs for gamma calculation
assocScan = getDoseAssociatedScan(doseNum1,planC);
if isempty(assocScan)
    assocScan = 1;
end
[newXgrid, newYgrid, newZgrid, doseArray1, doseArray2, interpMask3M] = ...
    prepareDosesForGamma(doseNum1,doseNum2,strNum,assocScan,planC);

deltaX = abs(newXgrid(2) - newXgrid(1));
deltaY = abs(newYgrid(2) - newYgrid(1));
deltaZ = abs(newZgrid(2) - newZgrid(1));

if doseDiffMethod == 1
    doseAgreement = doseAgreement*max(planC{indexS.dose}(doseNum1).doseArray(:))/100;
end

thresholdAbsolute = thresholdPercentMax*max(planC{indexS.dose}(doseNum1).doseArray(:))/100;

maxCalcDistance = distAgreement * maxDistanceFactor;

gammaM = gammaDose3d(doseArray1, doseArray2, interpMask3M, ...
    [deltaX deltaY deltaZ], doseAgreement, distAgreement, ...
    maxCalcDistance, thresholdAbsolute, doseDiffMethod);

% Assume doses within the filter threshold pass gamma
%gammaM(isnan(gammaM)) = 0;

newDoseNum = length(planC{indexS.dose}) + 1;

%Remove old caching info.
planC{indexS.dose}(newDoseNum).cachedMask = [];
planC{indexS.dose}(newDoseNum).cachedColor = [];
planC{indexS.dose}(newDoseNum).cachedTime = [];

%Set coordinates.
planC{indexS.dose}(newDoseNum).sizeOfDimension1 = length(newXgrid);
planC{indexS.dose}(newDoseNum).sizeOfDimension2 = length(newYgrid);
planC{indexS.dose}(newDoseNum).sizeOfDimension3 = length(newZgrid);
planC{indexS.dose}(newDoseNum).horizontalGridInterval = newXgrid(2)-newXgrid(1);
planC{indexS.dose}(newDoseNum).verticalGridInterval = newYgrid(2)-newYgrid(1);
planC{indexS.dose}(newDoseNum).depthGridInterval = newZgrid(2)-newZgrid(1);
planC{indexS.dose}(newDoseNum).coord1OFFirstPoint = newXgrid(1);
planC{indexS.dose}(newDoseNum).coord2OFFirstPoint = newYgrid(1);
planC{indexS.dose}(newDoseNum).coord3OfFirstPoint = newZgrid(1);
planC{indexS.dose}(newDoseNum).zValues = newZgrid;
planC{indexS.dose}(newDoseNum).doseUnits = 'Gy';
planC{indexS.dose}(newDoseNum).doseArray = gammaM;
planC{indexS.dose}(newDoseNum).doseUID = createUID('dose');
strName = planC{indexS.structures}(strNum).structureName;
planC{indexS.dose}(newDoseNum).fractionGroupID = ['Gamma_',...
    num2str(doseAgreement),'%_',num2str(distAgreement*10),'mm','_',strName];

%Switch to new dose
sliceCallBack('selectDose', num2str(newDoseNum));


function [ consumption ] = infer_consumption(result, evaluation_and_training_days, usage_duration, appliance, setup)

    %% infer consumption from average consumption of corresponding appliance
    num_measurements = size(evaluation_and_training_days{1},1) * 86400 / setup.granularity;
    consumption = zeros(1, num_measurements);

    %% Fridge, Freezer, TV, Stereo
    if strcmp(appliance, 'Fridge') == 1 ...
            || strcmp(appliance, 'Freezer') == 1 ...
            || strcmp(appliance, 'TV') == 1 ...
            || strcmp(appliance, 'Stereo') == 1

        warning('off');
        training_days = evaluation_and_training_days{2};
        [avg_runtime, plug_events] = get_average_runtime_from_plug_data(appliance, training_days, setup);
        average_power = get_average_power_from_plug_data(appliance, training_days, setup, plug_events);
        %% HERE

        times = result.events(:,1);
        on_events = result.events(:,3) > 0;
        times_on_events = times(on_events);
        times_off_events = times(~on_events);
        events_to_skip = [];
        for i = 1:length(times)
            if any(events_to_skip == i)
                continue;
            end
            % is on event
            % on event: check if off_event is within runtime
            % yes: on_event:off_event, increase by off_event
            % no: on_event:on_event+runtime, increase by runtime [ check boundaries ]
            if on_events(i) == 1
                switch_on = times(i);
                potential_off_events = times_off_events > switch_on & times_off_events < switch_on + avg_runtime;
                if any(potential_off_events)
                    off_idx = min(find(potential_off_events));
                    switch_off = times_off_events(off_idx);
                    consumption(switch_on:switch_off) = average_power;
                    % skip off event
                    idx_off_event = find(times == switch_off);
                    events_to_skip = [events_to_skip, i:idx_off_event];
                else
                    if switch_on + avg_runtime <= num_measurements
                        consumption(switch_on:switch_on+avg_runtime) = average_power;
                    else
                        consumption(switch_on:end) = average_power;
                    end
                end
            % off event: check if on_event is within runtime
            % yes: on_event:off_event;
            % [ not possible, this case is handled above ]
            % no: off_event-runtime:off_event [ check boundaries ]
            else
                switch_off = times(i);
                if switch_off - avg_runtime >= 1
                    consumption(switch_off-avg_runtime:switch_off) = average_power;
                else
                    consumption(1:switch_off) = average_power;
                end
            end
        end
        warning('on');

    elseif strcmp(appliance, 'Dishwasher') == 1
        for times = result.usage_times_start
            average_power = 1000; %1 kWh
            consumption(times:times+usage_duration-1) = average_power / usage_duration * 3600;
        end

    elseif strcmp(appliance, 'Water kettle') == 1
        average_power = 1800;
        times = result.events(:,1)
        on_events = result.events(:,3) > 0
        times_on_events = times(on_events);
        times_off_events = times(~on_events);

        for i = 1:length(times_on_events)
           switch_on = times_on_events(i);
           potential_off_events = times_off_events > switch_on & times_off_events < switch_on + usage_duration;
           if any(potential_off_events)
               switch_off = times_off_events(max(find(potential_off_events)));
               consumption(switch_on:switch_off) = average_power;
           end
        end

    else
        error('Determining consumption for appliance %s not implemented yet');
    end
end


function [x,p] = getLastState(stage,colloc,stageVars)
N = stage.N;
nx = stage.nx;
ni = colloc.num_i;
nu = stage.nu;
np = stage.np;

[X_indizes, ~, ~, P_indizes, ~] = ocl.simultaneous.indizes(N, nx, ni, nu, np);
x = stageVars(X_indizes(:,end));
p = stageVars(P_indizes(:,end));


function counts = numNeighbors(grains)
% returns the number of neighboring grains
%
% Input
%  grains - @grain2d
%
% Output
%  counts - number of neighbors per grain
%

% get list of neighbouring grains
pairs = grains.neighbors('full');

% get the number of neighbours per grain
ng = max(grains.id);
countIds = full(sparse(pairs(pairs<=ng),1,1,ng,1));

% rearange with respect to grain order
counts = countIds(grains.id);


function x = pad2minsize(x, minsize, v)
% PAD2MINSIZE pads INPUT with given VALUE so that both spatial sizes are at least MINSIZE.
%
%   X = pad2minsize(X, MINSIZE, V)
%     Default minimum image size MINSIZE is 70.
%     Default padding value V is 0.

	if ~exist('v'), v = 0; end
	if ~exist('minsize'), minsize = 70; end
	x = padarray(x, [max(minsize-size(x,1), 0), max(minsize-size(x,2), 0)], v, 'post');


function visualizeHOG(w)
% Visualize HOG features/weights.
%   visualizeHOG(w)

% AUTORIGHTS
% -------------------------------------------------------
% Copyright (C) 2011-2012 Ross Girshick
% Copyright (C) 2008, 2009, 2010 Pedro Felzenszwalb, Ross Girshick
% Copyright (C) 2007 Pedro Felzenszwalb, Deva Ramanan
%
% This file is part of the voc-releaseX code
% (http://people.cs.uchicago.edu/~rbg/latent/)
% and is available under the terms of an MIT-like license
% provided in COPYING. Please retain this notice and
% COPYING if you use this file (or a portion of it) in
% your project.
% -------------------------------------------------------

% Make pictures of positive and negative weights
bs = 20;
w = w(:,:,1:9);
scale = max(max(w(:)),max(-w(:)));
pos = HOGpicture(w, bs) * 255/scale;
neg = HOGpicture(-w, bs) * 255/scale;

% Put pictures together and draw
buff = 10;
pos = padarray(pos, [buff buff], 128, 'both');
if min(w(:)) < 0
  neg = padarray(neg, [buff buff], 128, 'both');
  im = uint8([pos; neg]);
else
  im = uint8(pos);
end
imagesc(im);
colormap gray;
axis equal;
axis off;


2*((x - x2)*((x - x1)^2 + (y - y1)^2)*(-r12^2 + (r11 -
    ((x - x1)^2 + (y - y1)^2)^(1/2))^2 + (z - z1)^2)*(-r22^2 + (y -
    y2)^2 + (r21 - ((x - x2)^2 + (z - z2)^2)^(1/2))^2) + (x -
    x2)*((x - x1)^2 + (y - y1)^2)*(-r12^2 + (r11 -
    ((x - x1)^2 + (y - y1)^2)^(1/2))^2 + (z - z1)^2)*(-r21 +
    ((x - x2)^2 + (z - z2)^2)^(1/2))*((x - x2)^2 + (z -
    z2)^2)^(1/2) + (x - x1)*(-r11 +
    ((x - x1)^2 + (y - y1)^2)^(1/2))*((x - x1)^2 + (y -
    y1)^2)^(1/2)*(-r22^2 + (y - y2)^2 + (r21 -
    ((x - x2)^2 + (z - z2)^2)^(1/2))^2)*((x - x2)^2 + (z -
    z2)^2) + (x - x1)*(-r12^2 + (r11 - ((x - x1)^2 + (y - y1)^2)^(1/2))^2 +
    (z - z1)^2)*(-r22^2 + (y - y2)^2 + (r21 -
    ((x - x2)^2 + (z - z2)^2)^(1/2))^(2))*((x - x2)^2 + (z - z2)^2));

2*(((x - x1)^2 + (y - y1)^2)*(y -
    y2)*(-r12^2 + (r11 - ((x - x1)^2 + (y - y1)^2)^(1/2))^2 +
    (z - z1)^2) + (-r11 + ((x - x1)^2 + (y - y1)^2)^(1/2))*
    ((x - x1)^2 + (y - y1)^2)^(1/2)*(y - y1)*(-r22^2 +
    (y - y2)^2 + (r21 - ((x - x2)^2 + (z - z2)^2)^(1/2))^2) +
    (y - y1)*(-r12^2 + (r11 - ((x - x1)^2 + (y - y1)^2)^(1/2))^2 +
    (z - z1)^2)*(-r22^2 + (y - y2)^2 + (r21 -
    ((x - x2)^2 + (z - z2)^2)^(1/2))^2))*((x - x2)^2 + (z - z2)^2);

2*((x - x1)^2 + (y - y1)^2)*((z - z1)*(-r22^2 + (y - y2)^2 +
    (r21 - ((x - x2)^2 + (z - z2)^2)^(1/2))^2)*((x - x2)^2 +
    (z - z2)^2) + (-r12^2 + (r11 - ((x - x1)^2 + (y - y1)^2)^(1/2))^2 +
    (z - z1)^2)*(-r22^2 + (y - y2)^2 + (r21 - ((x - x2)^2 + (z - z2)^2)^(1/2))^2)*
    (z - z2) + (-r12^2 + (r11 - ((x - x1)^2 + (y - y1)^2)^(1/2))^2+
    (z - z1)^2)*(-r21 + ((x - x2)^2 + (z - z2)^2)^(1/2))*
    ((x - x2)^2 + (z - z2)^2)^(1/2)*(z - z2));


function testFinalModelsAerts_HN_Old(pathExperiments,nExp,fSetNames)
% - paramCells: One cell of parameters for each fSet
% - nameCells: One cell of names for each fSet

startpath = pwd;
nFset = numel(fSetNames);
for exp = 1:nExp
    cd(fullfile(pathExperiments,['Experiment',num2str(exp)])), pathExperiment = pwd;
    load('training'), load('testing')
    nameOutcomes = fieldnames(training); nOutcomes = numel(nameOutcomes);
    cd('AertsSign'), pathFinalModels = pwd;
    for o = 1:nOutcomes
        for f = 1:nFset
            results = []; results = struct;
            cd(fullfile(pathFinalModels,nameOutcomes{o},fSetNames{f}))
            load('finalModel'), load('coeff'), load('response'), order = 4;
            results.model.Name = finalModel.Name; results.model.coeff = coeff; results.model.order = order;
            results.trainData.data = finalModel.Data; results.trainData.response = response; results.trainData.outcome = training.(nameOutcomes{o}).outcome;

            % TESTING MODEL
            outcome = testing.(nameOutcomes{o}).outcome;
            resp = zeros(numel(outcome),1);
            data = zeros(numel(outcome),order);
            for n = 1:order
                data(:,n) = testing.(nameOutcomes{o}).sign.(fSetNames{f})(:,n);
                resp = resp + coeff(n)*data(:,n);
            end
            resp = resp + coeff(end);
            results.testData.data = data; results.testData.response = resp; results.testData.outcome = outcome;
            [AUC,sensitivity,specificity,accuracy] = calcPerformMetrics(resp,outcome,0);
            results.AUC = AUC;
            results.Sensitivity = sensitivity;
            results.Specificity = specificity;
            results.Accuracy = accuracy;
            cd(pathExperiment), save(['testResultsAerts_',fSetNames{f},'_',nameOutcomes{o}],'results')
        end
    end
end

cd(startpath)
end


function one_result=seg_eva_gen_result_from_con_mat(one_con_mat, exclude_class_idxes)

        class_num=size(one_con_mat, 1);

        accuracy_classes=zeros(class_num, 1);
        inter_union_score_classes=zeros(class_num, 1);

        if nargin<2
            exclude_class_idxes=[];
        end

        valid_gt_class_sel=true(class_num, 1);

        global_pos_num=0;
        global_predict_num=0;

        for c_idx=1:class_num

            one_true_pos_num=one_con_mat(c_idx,c_idx);
            one_gt_pos_num=sum(one_con_mat(c_idx,:));
            one_predict_pos_num=sum(one_con_mat(:, c_idx));

            global_pos_num=global_pos_num+one_true_pos_num;
            global_predict_num=global_predict_num+one_predict_pos_num;

            if one_gt_pos_num>0
                one_accuracy=one_true_pos_num/(one_gt_pos_num+eps);
                one_inter_union_score=one_true_pos_num/...
                    (one_gt_pos_num+one_predict_pos_num-one_true_pos_num+eps);

                accuracy_classes(c_idx)=one_accuracy;
                inter_union_score_classes(c_idx)=one_inter_union_score;
            else
                valid_gt_class_sel(c_idx)=false;
            end

        end

        valid_class_sel=true(class_num, 1);
        valid_class_sel(exclude_class_idxes)=false;
        valid_class_sel=valid_class_sel & valid_gt_class_sel;

        accuracy_per_class=mean(accuracy_classes(valid_class_sel));
        inter_union_score_per_class=mean(inter_union_score_classes(valid_class_sel));
        accuracy_global=global_pos_num/global_predict_num;

        one_result.confusion_mat=one_con_mat;
        one_result.class_num=class_num;

        one_result.accuracy_global=accuracy_global;
        one_result.accuracy_per_class=accuracy_per_class;
        one_result.inter_union_score_per_class=inter_union_score_per_class;
        one_result.accuracy_classes=accuracy_classes;
        one_result.inter_union_score_classes=inter_union_score_classes;

        one_result.valid_class_num=nnz(valid_class_sel);
        one_result.valid_class_idxes=find(valid_class_sel);
        one_result.exclude_class_idxes=exclude_class_idxes;

end


function ffmsh_2d_data_print ( title, v_num, e_num, t_num, v_xy, v_l, e_v, ...
  e_l, t_v, t_l )

%*****************************************************************************80
%
%% FFMSH_2D_DATA_PRINT prints FFMSH data.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 December 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string TITLE, a title.
%
%    Input, integer V_NUM, the number of vertices.
%
%    Input, integer E_NUM, the number of boundary edges.
%
%    Input, integer T_NUM, the number of triangles.
%
%    Input, real V_XY(2,V_NUM), vertex coordinates.
%
%    Input, integer V_L(V_NUM), vertex labels.
%
%    Input, integer E_V(2,E_NUM), edge vertices.
%
%    Input, integer E_L(E_NUM), vertex labels.
%
%    Input, integer T_V(3,T_NUM), triangle vertices.
%
%    Input, integer T_L(T_NUM), triangle labels.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '%s\n', title );

  i4vec_print (              v_num, v_l,  '  Vertex labels:' );
  r8mat_transpose_print ( 2, v_num, v_xy, '  Vertex coordinates:' );
  i4vec_print (              e_num, e_l,  '  Edge labels:' );
  i4mat_transpose_print ( 2, e_num, e_v,  '  Edge vertices:' );
  i4vec_print (              t_num, t_l,  '  Triangle labels:' );
  i4mat_transpose_print ( 3, t_num, t_v,  '  Triangle vertices:' );

  return
end


function test_suite = test_createBasisTransform3d
%TEST_CREATEBASISTRANSFORM3D  Test case for the file createBasisTransform3d
%
%   Test case for the file createBasisTransform3d

%   Example
%   test_createBasisTransform3d
%
%   See also
%
%
% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2011-10-13,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

test_suite = functiontests(localfunctions);

function test_Translate(testCase) %#ok<*DEFNU>
% Basic test to check the function runs

p1 = [3 4 5];
p2 = [10 20 30];
basis1 = [p1 1 0 0 0 1 0];
basis2 = [p2 1 0 0 0 1 0];

dp = p1-p2;
exp = [eye(3) dp' ; 0 0 0 1];

trans = createBasisTransform3d(basis1, basis2);
testCase.assertEqual(exp, trans, 'AbsTol', .01);

function test_TransformPointTranslation(testCase) %#ok<*DEFNU>
% Basic test to check the function runs

% two bases with different origins and same directions
basis1 = [0 0 0     1 0 0  0 1 0];
basis2 = [10 20 30  1 0 0  0 1 0];

trans = createBasisTransform3d(basis1, basis2);

% pt1 = [0 0 0];
% pt1T = transformPoint3d(pt1, trans);
% exp1 = [0 0 0];
% testCase.assertEqual(exp1, pt1T, 'AbsTol', .01);

pt2 = [10 20 30];
pt2T = transformPoint3d(pt2, trans);
exp2 = [0 0 0];
testCase.assertEqual(exp2, pt2T, 'AbsTol', .01);

function test_Rotate(testCase) %#ok<*DEFNU>
% Basic test to check the function runs

p1 = [3 4 5];
basis1 = [p1  1 0 0   0 1 0];
basis2 = [p1  0 1 0  -1 0 0];

trans = createBasisTransform3d(basis1, basis2);

% restrict the test to the linear part
exp = [0 1 0; -1 0 0; 0 0 1];
testCase.assertEqual(exp, trans(1:3, 1:3), 'AbsTol', .01);

function test_TransformedPoints(testCase) %#ok<*DEFNU>
% test a combination of translation and axis permutation

% origin basis
basis1 = [10 10 10   1 0 0   0 1 0];
% translation and permutation
basis2 = [0 0 0   0 1 0   0 0 1];

trans = createBasisTransform3d(basis1, basis2);

pt1 = [0 0 0];
pt1T = transformPoint3d(pt1, trans);

exp1 = [10 10 10];
testCase.assertEqual(exp1, pt1T, 'AbsTol', .01);


function varargout = plotcoeffs(f, varargin)
%PLOTCOEFFS   Display coefficients of the columns, rows and tubes of a
%   CHEBFUN3 object.
%
% See also CHEBFUN/PLOTCOEFFS and CHEBFUN2/PLOTCOEFFS.

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

% Empty check.
if ( isempty(f) )
    varargout = { [] };
    return
end

% Store the hold state of the current axis:
holdState = ishold;

% Get low rank representation of f:
[~, fCols, fRows, fTubes] = tucker(f);

% PLOTCOEFFS of cols:
ax1 = subplot(1, 3, 1);
plotcoeffs(fCols, varargin{:});
ylim1 = ylim(gca);
% Remove labels from 1D plotcoeff:
xlabel(gca, '')
ylabel(gca, 'Magnitude of coefficient')
title('Cols')

% PLOTCOEFFS of rows:
ax2 = subplot(1, 3, 2);
plotcoeffs(fRows, varargin{:});
ylim2 = ylim(gca);
% Put an xlabel only for the plot in the middle:
if isa(f.cols.funs{1}.onefun,'trigtech')
    xlabel(gca, 'Wave number')
else
    xlabel(gca, 'Degree of Chebyshev polynomial')
end
ylabel(' ')
title('Rows')

% PLOTCOEFFS of tubes:
ax3 = subplot(1, 3, 3);
plotcoeffs(fTubes, varargin{:});
ylim3 = ylim(gca);
xlabel(' ')
ylabel(' ')
title('Tubes')

% Find a proper ylim for all the three subplots:
yLims = [ylim1; ylim2; ylim3];
ylimNew = [min(yLims(:, 1)), max(yLims(:, 2))];

% Set the ylim of the plots again to be similar.
ylim(ax1, ylimNew);
ylim(ax2, ylimNew);
ylim(ax3, ylimNew);

% Return hold state to what it was before:
if ( ~holdState )
    hold off
end

end


function test_ft_plot_patch

% MEM 1gb
% WALLTIME 00:10:00
% DEPENDENCY ft_plot_patch

hdat = [1:10 10:-1:1];
vdat = rand(1,10);
vdat = [vdat vdat(end:-1:1)+1];
ft_plot_patch(hdat, vdat)


function as_m_i(A)
%
%  Generates of the data used in 'as_m'. Data are stored in global
%  variables.
%
%  Calling sequence:
%
%    as_m_i(A)
%
%  Input:
%
%    A         real, symmetric matrix.
%
%
%  LYAPACK 1.0 (Thilo Penzl, May 1999)

if nargin~=1
  error('Wrong number of input arguments.');
end

if norm(A-A','fro')~=0
  error('A is not symmetric!');
end

global LP_A

LP_A = A;


classdef TestCopyMakeBorder
    %TestCopyMakeBorder

    methods (Static)
        function test_1
            src = imread(fullfile(mexopencv.root(),'test','img001.jpg'));
            [h,w,~] = size(src);
            border = [10, 20, 30, 40];
            types = {'Default', 'Reflect', 'Reflect101', 'Replicate', 'Wrap'};
            for i=1:numel(types)
                dst = cv.copyMakeBorder(src, border, 'BorderType',types{i});

                [hh,ww,~] = size(dst);
                assert(hh == (h+border(1)+border(2)));
                assert(ww == (w+border(3)+border(4)));
                assert(ndims(src) == ndims(dst));

                src2 = dst((1:h)+border(1), (1:w)+border(3), :);
                assert(isequal(src2, src));
            end
        end

        function test_2
            src = magic(5);
            dst = cv.copyMakeBorder(src, [1 2 3 4], ...
                'BorderType','Constant', 'Value',0);
        end

        function test_3
            src = magic(5);
            dst = cv.copyMakeBorder(src, 1, 2, 3, 4);
            dst = cv.copyMakeBorder(src, [1 2 3 4]);
        end

        function test_error_argnum
            try
                cv.copyMakeBorder();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function test_bug1998

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY ft_preprocessing ft_read_data read_neuralynx_ncs

% this bug is detailled on http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=1998
% and the workaround is explained on http://www.fieldtriptoolbox.org/getting_started/neuralynx?&#discontinuous_recordings

cd(dccnpath('/home/common/matlab/fieldtrip/data/test/bug1998'));

% start with normal preprocessing of a single channel
cfg         = [];
cfg.dataset = 'CSC1.Ncs';
data        = ft_preprocessing(cfg);

% Warning: discontinuous recording, predicted number of timestamps and observed number of timestamps differ by 1693523717.00
%  Please consult the wiki on http://www.fieldtriptoolbox.org/getting_started/neuralynx?&#discontinuous_recordings
% > In fileio/private/read_neuralynx_ncs at 94
%   In ft_read_header at 1196
%   In ft_preprocessing at 394
%
%
% >> disp(data)
%            hdr: [1x1 struct]
%          label: {'CSC1'}
%           time: {[1x12902912 double]}
%          trial: {[1x12902912 double]}
%        fsample: 1893
%     sampleinfo: [1 12902912]
%            cfg: [1x1 struct]

figure
plot(data.time{1})
xlabel('sample number')
ylabel('time (s)')

ts = ft_read_data(cfg.dataset, 'timestamp', 'true'); % raw timestamps
ts = double(ts); % convert from uint64 into double

figure
plot(ts)
xlabel('sample number')
ylabel('timestamp (a.u.)')

% determine the actual timestamps per sample and interpolate the data
dts       = median(diff(ts));
tsinterp  = ts(1):dts:ts(end);
datinterp = interp1(ts, data.trial{1}, tsinterp);

% you can use NaN to replace the data in the gaps
gaps     = find(diff(ts)>2*dts); % skips at least a sample
for igap = 1:length(gaps)
  sel = tsinterp < ts(gaps(igap)+1) & tsinterp > ts(gaps(igap));
  datinterp(:,sel) = NaN;
end

% update the FieldTrip data structure
data.trial{1} = datinterp;
data.time{1}  = (tsinterp - ts(1)) / (data.hdr.Fs .* dts);


function [g1, g2] = simXsimKernDiagGradient(simKern1, simKern2, t, covDiag)

% SIMXSIMKERNDIAGGRADIENT Gradient for the diagonal between two SIM kernels.
% FORMAT
% DESC computes cross gradient of parameters in the diagonal of a cross
% kernel between two sim kernels for the multiple output kernel.
% ARG simKern1 : the kernel structure associated with the first SIM
% kernel.
% ARG simKern2 : the kernel structure associated with the second SIM
% kernel.
% ARG t : inputs for which kernel is to be computed.
% ARG covDiag : gradient of the objective function with respect to
% the elements of the cross kernel matrix.
% RETURN g1 : gradient of the parameters of the first kernel, for
% ordering see simKernExtractParam.
% RETURN g2 : gradient of the parameters of the second kernel, for
% ordering see simKernExtractParam.
%
% SEEALSO : simXsimKernDiagCompute.m, simKernParamInit, simKernExtractParam
%
% COPYRIGHT : Mauricio A. Alvarez, 2010

% KERN

if size(t, 2) > 1
  error('Input can only have one column');
end

if simKern1.inverseWidth ~= simKern2.inverseWidth
  error('Kernels cannot be cross combined if they have different inverse widths.')
end
% The normalisation in the SIM kernel arises from the use of the normalised
% version of the RBF kernel. Hence, both have to be normalised or not.
if ~isfield(simKern1, 'isNormalised')
    isSim1Normalised = false;
else
    isSim1Normalised = simKern1.isNormalised;
end
if ~isfield(simKern2, 'isNormalised')
    isSim2Normalised = false;
else
    isSim2Normalised = simKern2.isNormalised;
end
if isSim1Normalised ~= isSim2Normalised
    error('Both SIM kernels have to be either normalised or not.');
end

sigma = sqrt(2/simKern1.inverseWidth);

if (~simKern1.isStationary || ~ simKern2.isStationary)
    [h1, dh1_dD1, dh1_dD2, dh1_dsigma] = ...
        simXsimComputeDiagH(t, simKern1.decay, simKern2.decay, simKern1.delay, simKern2.delay, sigma);
else
    [h1, dh1_dD1, dh1_dD2, dh1_dsigma] = ...
        simXsimComputeDiagHStat(t, simKern1.decay, simKern2.decay, simKern1.delay, simKern2.delay, sigma);
end

% Avoid making the expensive call twice unless really necessary
if ((simKern1.decay == simKern2.decay) && (simKern1.delay == simKern2.delay)),
  h2 = h1;
  dh2_dD2 = dh1_dD1;
  dh2_dD1 = dh1_dD2;
  dh2_dsigma = dh1_dsigma;
elseif (~simKern1.isStationary) || (~simKern2.isStationary)
  [h2, dh2_dD2, dh2_dD1, dh2_dsigma] = ...
      simXsimComputeDiagH(t, simKern2.decay, simKern1.decay, simKern2.delay, simKern1.delay, sigma);
else
    [h2, dh2_dD2, dh2_dD1, dh2_dsigma] = ...
      simXsimComputeDiagHStat(t, simKern2.decay, simKern1.decay, simKern2.delay, simKern1.delay, sigma);
end

dK_dsigma = dh1_dsigma + dh2_dsigma;

if isfield(simKern1, 'isVarS') && (simKern1.isVarS)
    K = 0.5 * (h1 + h2);
    if ~isSim1Normalised
        K = sqrt(pi) * K;
        dk_dD1 = (sum(covDiag.*dh1_dD1) + sum(covDiag.*dh2_dD1))*0.5*sqrt(pi)*sigma;
        dk_dD2 = (sum(covDiag.*dh1_dD2) + sum(covDiag.*dh2_dD2))*0.5*sqrt(pi)*sigma;
        dk_dsigma = sum(covDiag.*(dK_dsigma*0.5*sqrt(pi)*sigma + K));
    else
        dk_dD1 = (sum(covDiag.*dh1_dD1) + sum(covDiag.*dh2_dD1))*0.5;
        dk_dD2 = (sum(covDiag.*dh1_dD2) + sum(covDiag.*dh2_dD2))*0.5;
        dk_dsigma = 0.5 * sum(covDiag.*dK_dsigma);
    end
    dk_dinvWidth = -0.5*sqrt(2)/(simKern1.inverseWidth* ...
        sqrt(simKern1.inverseWidth))*dk_dsigma;
    % only pass the gradient with respect to the inverse width to one
    % of the gradient vectors ... otherwise it is counted twice.
    g1 = real([dk_dD1 dk_dinvWidth]);
    g2 = real([dk_dD2 0]);
else
    if isfield(simKern1, 'isNegativeS') && (simKern1.isNegativeS == true)
        C1 = simKern1.sensitivity;
        C2 = simKern2.sensitivity;
    else
        C1 = sqrt(simKern1.variance);
        C2 = sqrt(simKern2.variance);
    end
    K = 0.5 * (h1 + h2);
    var2 = C1*C2;
    if ~isSim1Normalised
        K = sqrt(pi) * K;
        dk_dD1 = (sum(covDiag.*dh1_dD1) + sum(covDiag.*dh2_dD1))*0.5*sqrt(pi)*sigma*var2;
        dk_dD2 = (sum(covDiag.*dh1_dD2) + sum(covDiag.*dh2_dD2))*0.5*sqrt(pi)*sigma*var2;
        dk_dsigma = sum(covDiag.*(dK_dsigma*0.5*sqrt(pi)*sigma + K))*var2;
        dk_dC1 = sigma * C2 * sum(covDiag.*K);
        dk_dC2 = sigma * C1 * sum(covDiag.*K);
    else
        dk_dD1 = (sum(covDiag.*dh1_dD1) + sum(covDiag.*dh2_dD1))*0.5*var2;
        dk_dD2 = (sum(covDiag.*dh1_dD2) + sum(covDiag.*dh2_dD2))*0.5*var2;
        dk_dsigma = 0.5 * var2 * sum(covDiag.*dK_dsigma);
        dk_dC1 = C2 * sum(covDiag.*K);
        dk_dC2 = C1 * sum(covDiag.*K);
    end
    if isfield(simKern1, 'isNegativeS') && simKern1.isNegativeS
        dk_dSim1Variance = dk_dC1;
    else
        dk_dSim1Variance = dk_dC1*0.5/C1;
    end
    if isfield(simKern2, 'isNegativeS') && simKern2.isNegativeS
        dk_dSim2Variance = dk_dC2;
    else
        dk_dSim2Variance = dk_dC2*0.5/C2;
    end
    dk_dinvWidth = -0.5*sqrt(2)/(simKern1.inverseWidth* ...
        sqrt(simKern1.inverseWidth))*dk_dsigma;
    % only pass the gradient with respect to the inverse width to one
    % of the gradient vectors ... otherwise it is counted twice.
    g1 = real([dk_dD1 dk_dinvWidth dk_dSim1Variance]);
    g2 = real([dk_dD2 0 dk_dSim2Variance]);
end


function x= rectwin(N)
% Function RECTWIN(N) creates the N-point Rectangular window.

x(1 : N)=ones(1, N);


function p06_story ( )

%*****************************************************************************80
%
%% P06_STORY prints the "story" for problem p06.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 August 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Carl DeBoor, John Rice,
%    Least-squares cubic spline approximation II - variable knots.
%    Technical Report CSD TR 21,
%    Purdue University, Lafayette, Indiana, 1968.
%
%    Carl DeBoor,
%    A Practical Guide to Splines,
%    Springer, 2001,
%    ISBN: 0387953663,
%    LC: QA1.A647.v27.
%
%  Parameters:
%
%    None
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The data is due to deBoor and Rice.\n' );
  fprintf ( 1, '  The data represents a temperature dependent property of titanium.\n' );
  fprintf ( 1, '  The data has been used extensively as an example in spline\n' );
  fprintf ( 1, '  approximation with variably-spaced knots.\n' );
  fprintf ( 1, '  DeBoor considers two sets of knots:\n' );
  fprintf ( 1, '  (595,675,755,835,915,995,1075)\n' );
  fprintf ( 1, '  and\n' );
  fprintf ( 1, '  (595,725,850,910,975,1040,1075).\n' );

  return
end


Network UNet {
	Layer CONV1_1 {
		Type: CONV
		Dimensions { K: 64, C:1, R: 3, S: 3, Y: 572, X: 572 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(7,7) R;
			TemporalMap(7,7) S;
			TemporalMap(7,1) Y;
			TemporalMap(7,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV1_2 {
		Type: CONV
		Dimensions { K: 64, C: 64, R: 3, S: 3, Y: 570, X: 570 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV2_1 {
		Type: CONV
		Dimensions { K: 128, C: 64, R: 3, S: 3, Y: 284, X: 284 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV2_2 {
		Type: CONV
		Dimensions { K: 128, C: 128, R: 3, S: 3, Y: 282, X: 282 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV3_1 {
		Type: CONV
		Dimensions { K: 256, C: 128, R: 3, S: 3, Y: 140, X: 140 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV3_2 {
		Type: CONV
		Dimensions { K: 256, C: 256, R: 3, S: 3, Y: 138, X: 138 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV4_1 {
		Type: CONV
		Dimensions { K: 512, C: 256, R: 3, S: 3, Y: 68, X: 68 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV4_2 {
		Type: CONV
		Dimensions { K: 512, C: 512, R: 3, S: 3, Y: 66, X: 66 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV5_1 {
		Type: CONV
		Dimensions { K: 1024, C: 512, R: 3, S: 3, Y: 32, X: 32 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV5_2 {
		Type: CONV
		Dimensions { K: 1024, C: 1024, R: 3, S: 3, Y: 30, X: 30 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer TRCONV1 {
		Type: TRCONV
		Dimensions { K: 512, C: 1024, R: 2, S: 2, Y: 28, X: 28 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(2,2) R;
			TemporalMap(2,2) S;
			TemporalMap(2,1) Y;
			TemporalMap(2,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV4_3 {
		Type: CONV
		Dimensions { K: 512, C: 1024, R: 3, S: 3, Y: 56, X: 56 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV4_4 {
		Type: CONV
		Dimensions { K: 512, C: 512, R: 3, S: 3, Y: 54, X: 54 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer TRCONV2 {
		Type: TRCONV
		Dimensions { K: 512, C: 512, R: 2, S: 2, Y: 52, X: 52 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(2,2) R;
			TemporalMap(2,2) S;
			TemporalMap(2,1) Y;
			TemporalMap(2,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV3_3 {
		Type: CONV
		Dimensions { K: 256, C: 512, R: 3, S: 3, Y: 104, X: 104 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV3_4 {
		Type: CONV
		Dimensions { K: 256, C: 256, R: 3, S: 3, Y: 102, X: 102 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer TRCONV3 {
		Type: TRCONV
		Dimensions { K: 128, C: 256, R: 2, S: 2, Y: 100, X: 100 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(2,2) R;
			TemporalMap(2,2) S;
			TemporalMap(2,1) Y;
			TemporalMap(2,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV2_3 {
		Type: CONV
		Dimensions { K: 128, C: 256, R: 3, S: 3, Y: 200, X: 200 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV2_4 {
		Type: CONV
		Dimensions { K: 128, C: 128, R: 3, S: 3, Y: 198, X: 198 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer TRCONV4 {
		Type: TRCONV
		Dimensions { K: 64, C: 128, R: 2, S: 2, Y: 196, X: 196 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(2,2) R;
			TemporalMap(2,2) S;
			TemporalMap(2,1) Y;
			TemporalMap(2,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV1_3 {
		Type: CONV
		Dimensions { K: 64, C: 128, R: 3, S: 3, Y: 392, X: 392 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV1_4 {
		Type: CONV
		Dimensions { K: 64, C: 64, R: 3, S: 3, Y: 390, X: 390 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(3,3) R;
			TemporalMap(3,3) S;
			TemporalMap(3,1) Y;
			TemporalMap(3,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}

	Layer CONV1_5 {
		Type: CONV
		Dimensions { K: 2, C: 64, R: 1, S: 1, Y: 388, X: 388 }
		Dataflow {
			SpatialMap(1,1) K;
			TemporalMap(64,64) C;
			TemporalMap(1,1) R;
			TemporalMap(1,1) S;
			TemporalMap(1,1) Y;
			TemporalMap(1,1) X;
			Cluster(64, P);
			SpatialMap(1,1) C;
		}
	}
}

// Accelerator {
//  PE { NumPEs: 128; VectorWidth: 4; MultPrecision: INT8, AddPrecision: INT16 }
//  Buffer { GlobalL2: 2048, LocalL1: 64}
//  NoC {Bandwidth: 64; AvgLatency: 2}
// }


function LU = getbounds(F,avoidequalitybounds,LU)

K.f = 0;
K.l = 0;
L = [];
U = [];
if nargin < 3
    LU =  yalmip('getbounds',1:yalmip('nvars'));
end
binary = yalmip('binvariables');
LU(binary,1) = 0;
LU(binary,2) = 1;
F = flatten(F);
simplex = [];
is_interval = is(F,'interval');
for i = 1:length(F.LMIid)
    if F.clauses{i}.type == 2
        X = F.clauses{i}.data;
        AB = getbase(X);
        K.l = prod(size(X));
        variables = getvariables(X);
        if is_interval(i)
            [lb,ub,cand_rows] = find_lp_bounds_interval(AB,K);
        else
            [lb,ub,cand_rows] = find_lp_bounds(AB,K);
        end
        LU(variables,1) = max([lb LU(variables,1)]')';
        LU(variables,2) = min([ub LU(variables,2)]')';
    elseif  F.clauses{i}.type == 55
        X = F.clauses{i}.data;X = X(:);
        AB = getbase(X);
        K.l = prod(size(X));
        variables = getvariables(X);
        if is_interval(i)
            [lb,ub,cand_rows] = find_lp_bounds_interval(AB,K);
        else
            [lb,ub,cand_rows] = find_lp_bounds(AB,K);
        end
        LU(variables,1) = max([lb LU(variables,1)]')';
        LU(variables,2) = min([ub LU(variables,2)]')';

    elseif F.clauses{i}.type == 3 && (nargin==1 || (nargin > 1 && isempty(avoidequalitybounds)))
        % FIX : Extract from equalities and binary constraints
        X = F.clauses{i}.data;
        AB = getbase(X);
        if size(AB,1)==1 && (AB(1) > 0) && all(AB(2:end)<0)
            % Save this simplex sum a_ix_i == b for later
            % and extract when as many variables as possible have been
            % fixed. Common in portfolio models
            simplex = [simplex i];
        end
        AB = [AB;-AB];
        K.l = 2*prod(size(X));
        variables = getvariables(X);
        if is_interval(i)
            [lb,ub,cand_rows] = find_lp_bounds_interval(AB,K);
        else
            [lb,ub,cand_rows] = find_lp_bounds(AB,K);
        end
        LU(variables,1) = max([lb LU(variables,1)]')';
        LU(variables,2) = min([ub LU(variables,2)]')';
    end
end

semicont = yalmip('semicontvariables');
if ~isempty(semicont)
    for i = 1:length(semicont)
        if LU(semicont(i),1) > 0
            LU(semicont(i),1) = 0;
        end
        if LU(semicont(i),2) < 0
            LU(semicont(i),2) = 0;
        end
    end
end

% Go through the simplex models with as much bounded as possible
for i = simplex
    X = F.clauses{i}.data;
    AB = getbase(X);
    variables = getvariables(X);
    if all(LU(variables,1)>=0)
        simplex_bound = AB(1)./(-AB(2:end));
        LU(variables,2) = min([simplex_bound(:) LU(variables,2)]')';
    end
end

% Try to bound some nonlinear terms
% FIX: complete code
[mt,variable_type] = yalmip('monomtable');
quadratic = find(variable_type == 2);
if ~isempty(quadratic)
    M = mt(quadratic,:);
    [ii,jj,kk] = find(M);
    LU(quadratic,1) = max([LU(quadratic,1) zeros(length(quadratic),1)],[],2);
    LU(quadratic,2) = max([LU(quadratic,1).^2 LU(quadratic,2).^2],[],2);
end


function Obs = projectLmk(Rob,Sen,Lmk,Obs,Opt)

% PROJECTLMK  Project landmark estimate into sensor's measurement space.
%   Obs = PROJECTLMK(Rob,Sen,Lmk,Obs) projects the landmark Lmk into sensor
%   Sen mounted on robot Rob, and updates the information of the
%   observation structure Obs. The observation model is determined from
%   Sen.type and Lmk.type. It is an error if no model exists for the chosen
%   Sen-Lmk pair.
%
%   The updated fields in Obs are:
%       .sid        % sensor ID
%       .lid        % landmark ID
%       .ltype      % landmark type
%       .vis        % flag: true if landmark is visible
%       .meas.R     % measurement noise cov. matrix
%       .exp.e      % expectation's mean
%       .exp.E      % expectation's covariances matrix
%       .exp.um     % expectation's uncertainty measure
%       .Jac.E_r    % Jacobian wrt robot frame
%       .Jac.E_s    % Jacobian wrt sensor frame
%       .Jac.E_l    % Jacobian wrt landmark state
%
%   See also OBSERVEKNOWNLMKS.

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

global Map

% PREVIOUS TASKS
% get landmark range and mean
lr = Lmk.state.r ;        % lmk range in Map
switch Map.type
    case 'ekf'
        l  = Map.x(lr);   % lmk mean
    case 'graph'
        l = Lmk.state.x;  % lmk mean
    otherwise
        error('??? Unknown Map type ''%s''.',Map.type)
end

% PROJECTION FUNCTION
% explore all sensor and landmark types
switch Sen.type

    case {'pinHole'} % camera pinHole

        switch Lmk.type

            case {'eucPnt'} % euclidean point

                % Point3D --> pixel -(value and Jacobians)-
                [e, depth, E_rf, E_sf, E_k, E_d, E_l] = ...
                    projEucPntIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    Sen.par.d, ...
                    l) ;

                vis = isVisible(e,depth,Sen.par.imSize);

            case {'idpPnt'} % inverse depth point

                % IDP --> pixel -(value and Jacobians)-
                [e, depth, E_rf, E_sf, E_k, E_d, E_l] = ...
                    projIdpPntIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    Sen.par.d, ...
                    l) ;

                vis = isVisible(e,depth,Sen.par.imSize);

            case {'hmgPnt'} % euclidean point

                % Point3D --> pixel -(value and Jacobians)-
                [e, depth, E_rf, E_sf, E_k, E_d, E_l] = ...
                    projHmgPntIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    Sen.par.d, ...
                    l) ;

                vis = isVisible(e,depth,Sen.par.imSize);

            case {'ahmPnt'}

                % Point3D --> pixel -(value and Jacobians)-
                [e, depth, E_rf, E_sf, E_k, E_d, E_l] = ...
                    projAhmPntIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    Sen.par.d, ...
                    l);

                vis = isVisible(e,depth,Sen.par.imSize);

            case {'fhmPnt'}

                % Point3D --> pixel -(value and Jacobians)-
                [e, depth, E_rf, E_sf, E_k, E_d, E_l] = ...
                    projFhmPntIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    Sen.par.d, ...
                    l);

                vis = isVisible(e,depth,Sen.par.imSize);

            case {'plkLin'}

                % Plucker line --> homogeneous line (value and Jacs)
                [e, v, E_rf, E_sf, E_k, E_l] = ...
                    projPlkLinIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    l); % expectation e is a homogeneous line

                % normalize wrt director vector e(1:2):
                ine12 = 1/norm(e(1:2));
                e     = e    * ine12;
                E_rf  = E_rf * ine12;
                E_sf  = E_sf * ine12;
                % E_k   = E_k  * ine12;
                E_l   = E_l  * ine12;

                % 3d Segment from Plucker line and abscissas
                [si,SI_l] = pluckerSegment(l,[Lmk.par.endp.t]);

                % projected segment
                [s, d, S_rf, S_sf, S_k, S_si] = projSegLinIntoPinHoleOnRob(...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    si);

                % segment visibility
                [s,vis] = visibleSegment(s,d,Sen.par.imSize);

            case 'aplLin'

                % Anchored Plucker line --> homogeneous line (value and Jacs)
                [e, v, E_rf, E_sf, E_k, E_l] = ...
                    projAplLinIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    l); % expectation e is a homogeneous line

                % normalize wrt director vector e(1:2):
                ine12 = 1/norm(e(1:2));
                e     = e    * ine12;
                E_rf  = E_rf * ine12;
                E_sf  = E_sf * ine12;
                % E_k   = E_k  * ine12;
                E_l   = E_l  * ine12;

                % 3d Segment from Plucker line and abscissas
                [si,SI_l] = aPluckerSegment(l,[Lmk.par.endp.t]);

                % projected segment
                [s, d, S_rf, S_sf, S_k, S_si] = projSegLinIntoPinHoleOnRob(...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    si);

                % segment visibility
                [s,vis] = visibleSegment(s,d,Sen.par.imSize);

            case 'idpLin'

                % IDP line --> homogeneous line (value and Jacs)
                [s, v, S_rf, S_sf, S_k, S_l] = ...
                    projIdpLinIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    l); % expectation s is a 2d segment
                [e, E_s] = seg2hmgLin(s); % expectation e is a homogeneous line
                E_rf = E_s*S_rf;
                E_sf = E_s*S_sf;
                E_l  = E_s*S_l;

                % normalize wrt director vector e(1:2):
                ine12 = 1/norm(e(1:2));
                e     = e    * ine12;
                E_rf  = E_rf * ine12;
                E_sf  = E_sf * ine12;
                % E_k   = E_k  * ine12;
                E_l   = E_l  * ine12;

                % 3d Segment from Plucker line and abscissas
                [si,SI_l] = idpLinSegment(l,[Lmk.par.endp.t]);

                % projected segment
                [s, d, S_rf, S_sf, S_k, S_si] = projSegLinIntoPinHoleOnRob(...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    si);

                % segment visibility
                [s,vis] = visibleSegment(s,d,Sen.par.imSize,0,Opt.obs.lines.minLength);

            case 'hmgLin'

                % HMG line --> homogeneous line (value and Jacs)
                [s, v, S_rf, S_sf, S_k, S_l] = ...
                    projHmgLinIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    l); % expectation s is a 2d segment
                [e, E_s] = seg2hmgLin(s); % expectation e is a homogeneous line
                E_rf = E_s*S_rf;
                E_sf = E_s*S_sf;
                E_l  = E_s*S_l;

                % normalize wrt director vector e(1:2):
                ine12 = 1/norm(e(1:2));
                e     = e    * ine12;
                E_rf  = E_rf * ine12;
                E_sf  = E_sf * ine12;
                % E_k   = E_k  * ine12;
                E_l   = E_l  * ine12;

                % 3d Segment from Plucker line and abscissas
                [si,SI_l] = hmgLinSegment(l,[Lmk.par.endp.t]);

                % projected segment
                [s, d, S_rf, S_sf, S_k, S_si] = projSegLinIntoPinHoleOnRob(...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    si);

                % segment visibility
                [s,vis] = visibleSegment(s,d,Sen.par.imSize,0,Opt.obs.lines.minLength);

            case 'ahmLin'

                % AHM line --> homogeneous line (value and Jacs)
                [s, v, S_rf, S_sf, S_k, S_l] = ...
                    projAhmLinIntoPinHoleOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    l); % expectation s is a 2d segment
                [e, E_s] = seg2hmgLin(s); % expectation e is a homogeneous line
                E_rf = E_s*S_rf;
                E_sf = E_s*S_sf;
                E_l  = E_s*S_l;

                % normalize wrt director vector e(1:2):
                ine12 = 1/norm(e(1:2));
                e     = e    * ine12;
                E_rf  = E_rf * ine12;
                E_sf  = E_sf * ine12;
                % E_k   = E_k  * ine12;
                E_l   = E_l  * ine12;

                % 3d Segment from Plucker line and abscissas
                [si,SI_l] = ahmLinSegment(l,[Lmk.par.endp.t]);

                % projected segment
                [s, d, S_rf, S_sf, S_k, S_si] = projSegLinIntoPinHoleOnRob(...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    si);

                % segment visibility
                [s,vis] = visibleSegment(s,d,Sen.par.imSize,0,Opt.obs.lines.minLength);

            otherwise % unknown landmark type for pin hole sensor
                error('??? Unknown landmark type ''%s'' for sensor ''%s''.', Lmk.type, Sen.type);

        end

    case 'pinHoleDepth'  % Pin hole sensor with depth information
        switch Lmk.type
            case 'eucPnt'

                % Point3D --> pixel+depth -(value and Jacobians)-
                [e, E_rf, E_sf, E_k, E_d, E_l] = ...
                    projEucPntIntoPhdOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    Sen.par.d, ...
                    l) ;

                vis = isVisible(e(1:2,:),e(3,:),Sen.par.imSize);

            otherwise
                error('??? Unknown landmark type ''%s'' for sensor ''%s''.',Lmk.type,Sen.type);
        end

    case {'omniCam'} % Omnidirectional camera

        switch Lmk.type

            case {'eucPnt'} % euclidean point

                % Point3D --> pixel -(value and Jacobians)-
                [e, depth, E_rf, E_sf, E_k, E_d, E_l] = ...
                    projEucPntIntoOmniCamOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    Sen.par.d, ...
                    l) ;

                vis = isVisible(e,depth,Sen.par.imSize);

            case {'ahmPnt'}

                % Point3D --> pixel -(value and Jacobians)-
                [e, depth, E_rf, E_sf, E_k, E_d, E_l] = ...
                    projAhmPntIntoOmniCamOnRob( ...
                    Rob.frame, ...
                    Sen.frame, ...
                    Sen.par.k, ...
                    Sen.par.d, ...
                    l);

                vis = isVisible(e,depth,Sen.par.imSize);

            otherwise % unknown landmark type for pin hole sensor
                error('??? Unknown landmark type ''%s'' for sensor ''%s''.',Lmk.type,Sen.type);

        end

    otherwise % unknown Sensor type
        error('??? Unknown sensor type ''%s''.',Sen.type);

end % sensor type

% COVARIANCES
if strcmp(Map.type,'ekf')

    % Rob-Sen-Lmk range and Jacobian
    if Sen.frameInMap
        rslr  = [Rob.frame.r ; Sen.frame.r ; lr]; % range of robot, sensor, and landmark
        E_rsl = [E_rf E_sf E_l];
    else
        rslr  = [Rob.frame.r ; lr];               % range of robot and landmark
        E_rsl = [E_rf E_l];
    end

    % Expectation covariances matrix
    E = E_rsl*Map.P(rslr,rslr)*E_rsl' ;

else
    E = [];
end

% Other parameters
switch Lmk.type(4:6)
    case 'Lin'
        % for lines, project endpoints with covariances:

        % compute endpoints
        Obs.par.endp(1).e = s(1:2);
        Obs.par.endp(2).e = s(3:4);

        if Map.type == 'ekf'
            % Rob-Sen-Lmk Jacobian of projected segment
            if Sen.frameInMap
                S_rsl = [S_rf S_sf S_si*SI_l];
            else
                S_rsl = [S_rf S_si*SI_l];
            end
            % compute covariances
            S = S_rsl*Map.P(rslr,rslr)*S_rsl'; % segment covariance
            Obs.par.endp(1).E = S(1:2,1:2);
            Obs.par.endp(2).E = S(3:4,3:4);
        end

end

% UPDATE OBS STRUCTURE
Obs.sid     = Sen.id ;
Obs.lid     = Lmk.id ;
Obs.ltype   = Lmk.type ;
Obs.vis     = vis ;
Obs.exp.e   = e ;
Obs.exp.E   = E ;
Obs.exp.um  = det(E);  % uncertainty measure proportional to ellipsoid area
Obs.Jac.E_r = E_rf;
Obs.Jac.E_s = E_sf;
Obs.Jac.E_l = E_l;

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

%   # START GPL LICENSE

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

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

%   # END GPL LICENSE


% batch run full-clustering on all fish, sweep param with 2-fold CV

data_masterdir = GetCurrentDataDir();

% range_fish = [5,6,7];
% M_ClusGroup = [2,2,2,2];
% M_Cluster = [1,1,1,1];
range_fish = 8:9;
% M_ClusGroup = 2;
% M_Cluster = 3;
M_stim = 1;
% M_fish_set = [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2];

%%
M_param = 5:5:100;%0.3:0.1:0.8;

Param_nClus = zeros(length(M_param),length(range_fish));
Param_CVscore = zeros(length(M_param),length(range_fish));
Param_CVscore_raw = cell(length(M_param),length(range_fish));

%     thres_split = M_param(k_param);
%     setappdata(hfig,'thres_split',thres_split);

for k_fish = 1:length(range_fish),
    i_fish = range_fish(k_fish);
    disp(i_fish);
    LoadFullFish(hfig,i_fish,0);
    absIX = getappdata(hfig,'absIX');

    %% partitions for CV
    timelists = getappdata(hfig,'timelists');
    timelists_names = getappdata(hfig,'timelists_names');
    periods = getappdata(hfig,'periods');
    if length(periods)>1,
        timelistsCV = cell(length(M_stim),2);

        k_stim = 1;
%         for k_stim = 1:length(M_stim),
        i_stim = M_stim(k_stim);
        TL = timelists{i_stim};
        period = periods(i_stim);
        nrep = size(TL,2)/periods(i_stim); % integer
        n = floor(nrep/2);
        timelistsCV{k_stim,1} = TL(1):TL(n*period);
        timelistsCV{k_stim,2} = TL(1+n*period):TL(2*n*period);
%           end
    end

    for k_param = 1:length(M_param),
        numK2 = M_param(k_param);

        Score = zeros(1,2);%(length(M_stim),2);
        %%
        NumClus = zeros(1,2);
        CIX = cell(1,2);
        GIX = cell(1,2);
        for k = 1:2, % CV halves
            i_ClusGroup = 2;
            i_Cluster = k+4;
            [cIX,gIX] = LoadCluster_Direct(i_fish,i_ClusGroup,i_Cluster,absIX);

            tIX = timelistsCV{k_stim,k};
            M_0 = GetTimeIndexedData_Default_Direct(hfig,[],tIX,'isAllCells');

            isWkmeans = 0;
            [cIX,gIX] = AutoClustering(cIX,gIX,absIX,i_fish,M_0,isWkmeans,numK2);

            NumClus(k) = length(unique(gIX));
            CIX{k} = cIX;
            GIX{k} = gIX;
        end
        % plot cell-matching figure
        Score(1) = HungarianCV(NumClus(1),NumClus(2),CIX{1},CIX{2},GIX{1},GIX{2});% true,timelists_names{i_stim});
        Score(2) = HungarianCV(NumClus(2),NumClus(1),CIX{2},CIX{1},GIX{2},GIX{1});% true,timelists_names{i_stim});
        Param_CVscore(k_param,k_fish) = mean(Score);
        Param_CVscore_raw{k_param,k_fish} = Score;

        nClus1 = length(unique(GIX{1}));
        nClus2 = length(unique(GIX{2}));
        Param_nClus(k_param,k_fish) = mean([nClus1,nClus2]);

    end
end

%%
figure;
subplot(2,1,1)
plot(M_param*20,Param_nClus)
% legend('Fish8','Fish9');
xlabel('total k for kmeans')
ylabel('# of auto-clusters')
subplot(2,1,2)
plot(M_param*20,Param_CVscore)
ylim([0,1])
legend('Fish8','Fish9');
xlabel('total k for kmeans')
ylabel('CV (overlapping cell %)')


function [x,pca_x,pca_coeff] = preprocess(x)
    [pca_coeff,pca_x,latent] = pca(x);
end


filename='Chair_Tetrahedra';
 ptype = 'MACRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'holes';
cost = {'compliance'};
weights = [1];
constraint = {'volume'};
optimizer = 'HAMILTON-JACOBI'; incrementFactor = 1;
filterType = 'P1';
line_search_initiator = 'STANDARD';

HJiter0 = 1;
e2 = 100;
N_holes = [24 11 11];
R_holes = 0.4;
phase_holes = [0 0 0];
nsteps = 5;

Vfrac_final = 0.2;
Perimeter_target = 1;
optimality_final = 1e-3;
constr_final =1e-3;

Vfrac_initial = 0.4;
optimality_initial = 5e-2;
constr_initial = 5e-2;
TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;


function [res min_cs] = tracking_dp(dres, c_en, c_ex, c_ij, betta, thr_cost, max_it, nms_in_loop)

if ~exist('max_it')
  max_it = 1e5;
end
if ~exist('thr_cost')
  thr_cost = 0;
end

thr_nms = 0.5;

dnum = length(dres.x);

dres.c = betta - dres.r;

dres.dp_c     = [];
dres.dp_link  = [];
dres.orig     = [];

min_c     = -inf;
it        = 0;
k         = 0;
inds_all  = zeros(1,1e5);
id_s      = zeros(1,1e5);
redo_nodes = [1:dnum]';
while (min_c < thr_cost) && (it < max_it)
  it = it+1;

  dres.dp_c(redo_nodes,1) = dres.c(redo_nodes) + c_en;
  dres.dp_link(redo_nodes,1) = 0;
  dres.orig(redo_nodes,1) = redo_nodes;

  for ii=1:length(redo_nodes)
    i = redo_nodes(ii);
    f2 = dres.nei(i).inds;
    if isempty(f2)
      continue
    end

    [min_cost j] = min(c_ij + dres.c(i) + dres.dp_c(f2));
    min_link = f2(j);
    if dres.dp_c(i,1) > min_cost
      dres.dp_c(i,1) = min_cost;
      dres.dp_link(i,1) = min_link;
      dres.orig(i,1) = dres.orig(min_link);
    end
  end

  [min_c ind] = min(dres.dp_c + c_ex);

  inds = zeros(dnum,1);

  k1 = 0;
  while ind~=0
    k1 = k1+1;
    inds(k1) = ind;
    ind = dres.dp_link(ind);
  end
  inds = inds(1:k1);

  inds_all(k+1:k+length(inds)) = inds;
  id_s(k+1:k+length(inds)) = it;
  k = k+length(inds);

  if nms_in_loop
    supp_inds = nms_aggressive(dres, inds, thr_nms);
    origs = unique(dres.orig(supp_inds));
    redo_nodes = find(ismember(dres.orig, origs));
  else
    supp_inds = inds;
    origs = inds(end);
    redo_nodes = find(dres.orig == origs);
  end
  redo_nodes = setdiff(redo_nodes, supp_inds);
  dres.dp_c(supp_inds) = inf;
  dres.c(supp_inds) = inf;

  min_cs(it) = min_c;
end
inds_all = inds_all(1:k);
id_s = id_s(1:k);

res = sub(dres, inds_all);
res.id = id_s';


function Z = jacobiansparsityfromnonlinear(model,includeLinear)

if nargin == 1
    % IPOPT appends linear constraints, and that sparsity structure should
    % thus be included. KNITRO does not append linears to the structure
    includeLinear = 1;
end

m = length(model.lb);
allA=[model.Anonlinineq];
if any(model.K.q)
    top = startofSOCPCone(model.K);
    allQ = [];
    for i = 1:length(model.K.q)
        allQ = [allQ;any(model.F_struc(top:top+model.K.q(i)-1,2:end))];
        top = top + model.K.q(i);
    end
    allA = [allA;allQ];
end
if any(model.K.e)
    top = startofEXPCone(model.K);
    allQ = [];
    for i = 1:(model.K.e)
        allQ = [allQ;any(model.F_struc(top:top+3-1,2:end))];
        top = top + 3;
    end
    allA = [allA;allQ];
end
if any(model.K.p)
    top = startofPOWCone(model.K);
    allQ = [];
    for i = 1:length(model.K.p)
        allQ = [allQ;any(model.F_struc(top:top+model.K.p(i)-1,2:end))];
        top = top + model.K.p(i);
    end
    allA = [allA;allQ];
end
if any(model.K.s)
    top = startofSDPCone(model.K);
    allQ = [];
    for i = 1:length(model.K.s)
        s = any(model.F_struc(top:top+model.K.s(i)^2-1,2:end));
        allQ = [allQ;repmat(s,model.K.s(i),1)];
        top = top + model.K.s(i)^2;
    end
    allA = [allA;allQ];
end

allA = [allA;model.Anonlineq];
depends = allA | allA;
if length(model.linearindicies) == size(allA,2)
    % It is linear + possibly linear cone
    jacobianstructure = double(depends);
else
    jacobianstructure = spalloc(size(allA,1),m,0);
    for i = 1:size(depends,1)
        vars = find(depends(i,:));
        [ii,vars] = find(model.deppattern(vars,:));
        vars = unique(vars);
        s = size(jacobianstructure,1);
        if 0
        [~,loc] = ismember(vars,model.linearindicies);
        jacobianstructure(i,find(loc)) = 1;
        else
        for j = 1:length(vars)
            jacobianstructure(i,find(vars(j) == model.linearindicies)) = 1;
        end
        end
    end
end
if includeLinear
    allA=[model.A; model.Aeq];
    depends = allA | allA;
    jacobianstructure = [jacobianstructure;depends];
end
Z = sparse(jacobianstructure);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% A heuristic way to further refine the output windows
%
% For each small output window, we run our method on the
% this ROI again and extract the output that has the
% largest IOU with the orignal window for replacement.
%
% NMS is further applied to remove duplicate windows.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function res = refineWin(I, res, net, param)

imsz = [size(I,1) size(I,2)];
param.lambda = 0.05;
for i = 1:size(res,2)
    bb = res(:,i);
    bbArea = (bb(3)-bb(1))*(bb(4)-bb(2));
    % only refine small windows
    if bbArea < 0.125*imsz(1)*imsz(2)
        margin = (bb(3)-bb(1)+bb(4)-bb(2))*0.2;
        bb = round(expandROI(bb, imsz, margin));
        Itmp = I(bb(2):bb(4), bb(1):bb(3) , :);
        [Ptmp, Stmp] = getProposals(Itmp, net, param);
        restmp = propOpt(Ptmp, Stmp, param);
        if ~isempty(restmp)
            restmp = getROIBBox(restmp, bb);
            [~,ii] = max(getIOUFloat(restmp', res(:,i)));
            res(:,i) = restmp(:,ii);
        end
    end
end
res = doNMS(res, 0.5);


function [aw,ae,ap,su]=abc

global dx n2 ta tb
warning off
b=n2*(dx^2);

i=1;
aw(i)=0;
ae(i)=1;
su(i)=b*ta+2*tb;
sp(i)=-b-2;
ap(i)=aw(i)+ae(i)-sp(i);

i=2;
aw(i)=1;
ae(i)=1;
su(i)=b*ta;
sp(i)=-b;
ap(i)=aw(i)+ae(i)-sp(i);

i=3;
aw(i)=1;
ae(i)=0;
su(i)=b*ta;
sp(i)=-b;
ap(i)=aw(i)+ae(i)-sp(i);


function u = sqr(a)
%SQR          Slope square  sqr(a)
%

% written  12/06/98     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
% modified 08/26/12     S.M. Rump  global variables removed
%

  e = 1e-30;
  if 1+e==1-e                           % fast check for rounding to nearest
    rndold = 0;
  else
    rndold = getround;
    setround(0)
  end

  INTLAB_SLOPE = getappdata(0,'INTLAB_SLOPE');

  u = a;

  u.r = sqr(a.r);
  indexc = 1:INTLAB_SLOPE.NUMVAR;
  indexr = 2:INTLAB_SLOPE.NUMVAR+1;
  u.s = a.s .* (a.r(:,indexc)+a.r(:,indexr));

  if rndold
    setround(rndold)
  end


function [saveampname]=ps_load_mean_amp()
%PS_LOAD_MEAN_AMP Load mean_amp file into a matlab workspace
%
%   Andy Hooper, June 2006
%
%   ======================================================================
%   02/2010 AH: Reduce memory needs by reading in chunks
%   11/2010 AH: Do amplitude merge here instead of ps_merge_patches.m
%   11/2010 MA: Fix when length(amp_bit) returns zero at the end
%   ======================================================================

if exist('patch.in','file')
    patch=load('patch.in');
    width=patch(2)-patch(1)+1;
else
    widthname='width.txt';
    if ~exist(widthname,'file')
        widthname= ['../',widthname];
    end
    width=load(widthname);
end

ampname=['./mean_amp.flt'];
saveampname=['./amp_mean.mat'];

if ~exist(ampname,'file')
    ampname=['../mean_amp.flt'];
    saveampname=['../amp_mean.mat'];
end

if ~exist(ampname,'file')
  ampname=['./mean_amp.flt'];
  saveampname=['./amp_mean.mat'];
  fprintf('   Merging mean amplitude files\n')
  widthname='width.txt';
  if ~exist(widthname,'file')
      widthname= ['../',widthname];
  end
  width=load(widthname);
  amp=zeros(width,1,'single');

  if exist('./patch.list','file')
    dirname=struct;
    fid=fopen('patch.list','r');
    i=0;
    while feof(fid)==0
        i=i+1;
        dirname(i).name=fgetl(fid);
    end
    fclose(fid);
  else
    dirname=dir('PATCH_*');
  end
  n_patch=length(dirname);
  for i=1:n_patch
   if ~isempty(dirname(i).name)
    cd(dirname(i).name);
    if exist('./mean_amp.flt','file')
        pxy=load('patch.in');
        fid=fopen('mean_amp.flt');
        amp(pxy(1):pxy(2),pxy(3):pxy(4))=fread(fid,[pxy(2)-pxy(1)+1,inf],'float=>single');
        fclose(fid);
    end
    cd ..
   end
  end

  fid=fopen('./mean_amp.flt','w');
  fwrite(fid,amp,'float');
  fclose(fid);
  clear amp

%error('Cannot find mean_amp.flt in this directory or parent')
end

amp_high=[];
amp_low=[];
fid=fopen(ampname,'r');
while ~feof(fid) % first read through
  amp_bit=fread(fid,[width,1000],'float');
  amp_bit(isnan(amp_bit))=1;
  amp_bit=sort(amp_bit(:));
  if length(amp_bit)==0  % MA fix
    break                % length(amp_bit) returns zero at the end
  end
  amp_high=[amp_high;amp_bit(round(length(amp_bit)*0.91):end)];
  amp_low=[amp_low;amp_bit(round(length(amp_bit)*0.01):end)];
end
fclose(fid);

amp_low=min(amp_low);
amp_high=sort(amp_high);
amp_min=min(amp_low);
amp_max=log(amp_high(ceil(length(amp_high)/2))-amp_min);
clear amp_high amp_low

fid=fopen(ampname,'r');
amp_mean=[];
while ~feof(fid) % second read through
  amp_bit=fread(fid,[width,1000],'float');
  amp_bit=amp_bit'-amp_min;
  amp_bit(amp_bit<1)=1;
  amp_bit=log(amp_bit);
  amp_bit(isnan(amp_bit))=0;
  amp_bit(amp_bit>amp_max)=amp_max;
  amp_bit=uint8(amp_bit*255/amp_max);
  amp_mean=[amp_mean;amp_bit];
  if length(amp_bit)==0  % MA fix
  break
  end
end

save(saveampname,'amp_mean');


function result = applyToNonNan(data,func)
% Apply the given function columnwise to all non NaN values in the given
% data.
%
% USAGE:
%
%    result = applyToNonNan(data,func)
%
% INPUTS:
%    data:          Matrix of data (individuals x variables)
%    func:          function handle that takes an vector of data and
%                   computes single value result.
%
% OUTPUTS:
%
%    result:        A Vector of with dimensions (size(data,2) x 1) where
%                   the supplied function was applied to all columns
%                   ignoring NaN values.

result = zeros(1,size(data,2));

for i = 1:size(data,2)
    result(i) = func(data(~isnan(data(:,i)),i));
end


function calcAllFeatureSets_HN(pathSet,training,pathMINE,param,setSize,alpha,delta,nBoot,seed,batchNum)
% -------------------------------------------------------------------------
% function calcAllFeatureSets_HN(pathExperiment,trainingStruct,pathMINE,setSize,alpha,delta,nBoot,batchNum)
% -------------------------------------------------------------------------
% DESCRIPTION:
% This function computes feature set reduction for a given feature set type
% and for all experiments with different degrees of freedom. See ref. [1,2]
% for more details.
% -------------------------------------------------------------------------
% REFERENCES:
% [1] Vallieres, M. et al. (2015). FDG-PET/CT radiomics models for the
%     early prediction of different tumour outcomes in head and neck cancer.
%     The Journal of Nuclear Medicine, aa(bb), xxx-yyy.
%     doi:
% [2] Vallieres, M. et al. (2015). A radiomics model from joint FDG-PET and
%     MRI texture features for the prediction of lung metastases in soft-tissue
%     sarcomas of the extremities. Physics in Medicine and Biology, 60(14),
%     5471-5496. doi:10.1088/0031-9155/60/14/5471
% -------------------------------------------------------------------------
% INPUTS:
% 1. pathSet: Full path to the Feature Set folder of the corresponding experiment.
%             --> Ex: '/myProject/WORKSPACE/COHORT-BASED-RESULTS/Experiment1/FSET'
% 2. training: Structure defining all parameters for the given experiment
%              to perform. See masterScript_HN.m for more details.
% 3. pathMINE: Full path to the MINE.jar executable. The executable can be
%              downloaded at: <http://www.exploredata.net/>.
%              --> Ex: '/myProject/radiomics/MultivariableModeling/MINE'
% 4. param: Cell of two strings, defining 1) The feature set type/name; and
%           2) the outcome to model
% 4. setSize: Size of the output feature set (typically set to 25 in ref. [1]).
%             --> Ex: 25
% 5. alpha: Numerical values specifying the coefficient of the first part of
%           the Gain equation, as defined in ref. [1,2].
%           --> Ex: 0.5
% 6. delta: Numerical values specifying the coefficient of the second part
%           of the Gain equation, as defined in ref. [1,2] (third part is set
%           to 0 in this function).
%           --> Ex: 0.5
% 7. nBoot: Number of bootstrap samples to use.
%           --> Ex: 100
% 8. seed: Numerical number to use as seed for bootstrapping experiment
%          --> Ex: 54288
%
% See <https://github.com/mvallieres/radiomics/tree/master/STUDIES/HNstudy/Functions>
% to find computeAllNonTextureFeatures_HN.m, organizeSeparateTextures_HN.m
% and organizeFusedTextures_HN.m. See masterScript_HN.m for a complete
% example of how to utilize the current function.
% -------------------------------------------------------------------------
% OUTPUTS: Feature sets are saved in a folder named 'FSET' in the
% corresponding folder of "pathExperiment"
% -------------------------------------------------------------------------
% AUTHOR(S): Martin Vallieres <mart.vallieres@gmail.com>
% -------------------------------------------------------------------------
% HISTORY:
% - Creation: March 2016
%--------------------------------------------------------------------------
% STATEMENT:
% This file is part of <https://github.com/mvallieres/radiomics/>,
% a package providing MATLAB programming tools for radiomics analysis.
% --> Copyright (C) 2015  Martin Vallieres
%
%    This package is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    This package is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this package.  If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------

startpath = pwd;
warning off
if nargin < 10
    batchNum = 1;
end

fSetName = param{1};
outcomeName = param{2};
outcome = training.(outcomeName).outcome;
nonText = training.(outcomeName).nonText;
% if strcmp(outcomeName,'Death'), nonText = rmfield(nonText,'PercentInactive'); end % Creates problem for that outcome, this needs to be solved
textCellsName = fieldnames(training.(outcomeName).text.(fSetName)); textCellsName(1:4) = []; % Removing 'param', 'baseline', 'freedom', 'paramName'
nTextCell = numel(textCellsName);
textCells = cell(1,nTextCell);
for i = 1:nTextCell
    textCells{i} = training.(outcomeName).text.(fSetName).(textCellsName{i});
end
paramAll = training.(outcomeName).text.(fSetName).param;
freedomMat = training.(outcomeName).text.(fSetName).freedom;
baseline = training.(outcomeName).text.(fSetName).baseline;

if strcmp(fSetName,'CT')
    nonText = rmfield(nonText,{'SUVmax','SUVpeak','SUVmean','aucCSH','TLG','PercentInactive','gETU'}); % These features were calculated from PET.
end

tic
fprintf(['\n--> COMPUTING "',fSetName,'" FEATURE SET FOR "',outcomeName,'" OUTCOME ... '])
[fSet] = featureSetReduction_HN(pathMINE,fSetName,outcome,setSize,nonText,textCells,textCellsName,paramAll,freedomMat,baseline,alpha,delta,nBoot,seed,batchNum);
cd(pathSet), save(['FSET_',fSetName,'_',outcomeName],'fSet')
fprintf('DONE!\n'), toc

cd(startpath)
end


function [ polyg, Features] = getcandboxlayoutSingle( layout, vp, h, w, integData )
% getcandoxlayout Get box layout candidates and their features.
%
% INPUT:
%    vp- vanishing points h,w- height width of image
%    integData - integral images for features.

%OUTPUT:
% polyg - box layout candidates, each candidate as five polygons corresponding to left/middle/right walls, floor and ceiling
% Features -for each box layout candidate

%Features:-
%line-membership features:1:20
%correct label confidence: 21-25
%label entropy :26 -30
%weighted line-memership features:31-40
%surface label confidence :41 -75

numf=75;

samps=10;gtexist=0;
% [layout]=getLayouts(vp,h,w,samps);

numL=size(layout,1);

Features=zeros(numL,numf);
polyg=cell(numL,5);

cnt=1;quantsiz=500;
if numL > 0
    for lay=1:size(layout,1)
        Ra=[layout(lay,1) layout(lay,2)];
        Rb=[layout(lay,3) layout(lay,4)];
        Rc=[layout(lay,5) layout(lay,6)];
        Rd=[layout(lay,7) layout(lay,8)];
        Polyg=[];
        tot_area = 0;

        cond1=inpolygon(vp(3,1),vp(3,2),[Ra(1); Rb(1); Rc(1); Rd(1); Ra(1)],[Ra(2); Rb(2); Rc(2); Rd(2);Ra(2)]) & ...
            ~(inpolygon(vp(2,1),vp(2,2),[Ra(1); Rb(1); Rc(1); Rd(1);Ra(1)],[Ra(2); Rb(2); Rc(2); Rd(2);Ra(2)])) & ...
            ~(inpolygon(vp(1,2),vp(1,2),[Ra(1); Rb(1); Rc(1); Rd(1);Ra(1)],[Ra(2); Rb(2); Rc(2); Rd(2);Ra(2)]));

        lines1=[Ra(1) Rb(1) Ra(2) Rb(2);...
            Rc(1) Rd(1) Rc(2) Rd(2);...
            Rb(1) Rc(1) Rb(2) Rc(2);...
            Ra(1) Rd(1) Ra(2) Rd(2)];
        lines2=[vp(2,1) vp(3,1) vp(2,2) vp(3,2);...
            [vp(2,1) vp(3,1) vp(2,2) vp(3,2)];...
            [vp(1,1) vp(3,1) vp(1,2) vp(3,2)];...
            [vp(1,1) vp(3,1) vp(1,2) vp(3,2)]];
        [inxs inys]=IntersectLines(lines1,lines2);

        cond2=inxs(1) < vp(3,1) & inxs(2) > vp(3,1) & inys(3) < vp(3,2) & inys(4) > vp(3,2);

        %1 floor
        [tempimg tpolyg parea]=getface(Rd,Ra,vp,w,h,0,1,0);
        Polyg{1}=[tpolyg];
        if numel(find(isnan(tpolyg))) >0
            error('debug me');
        end
        tot_area = tot_area+parea;

        %2 middlewall
        [tempimg tpolyg trapez parea]=getmiddlewall(Ra,Rb,Rc,Rd,vp,w,h,0,1,0);
        Polyg{2}=[tpolyg];
        if numel(find(isnan(tpolyg))) >0
            error('debug me');
        end
        tot_area = tot_area+parea;

        %3 right wall
        [tempimg tpolyg parea]=getface(Rc,Rd,vp,w,h,0,1,0);
        Polyg{3}=[tpolyg];
        if numel(find(isnan(tpolyg))) >0
            error('debug me');
        end
        tot_area = tot_area+parea;

        %4 left wall
        [tempimg tpolyg parea]=getface(Ra,Rb,vp,w,h,0,1,0);
        Polyg{4}=[tpolyg];
        if numel(find(isnan(tpolyg))) >0
            error('debug me');
        end
        tot_area = tot_area+parea;

        %5 ceiling
        [tempimg tpolyg parea]=getface(Rb,Rc,vp,w,h,0,1,0);
        Polyg{5}=[tpolyg];
        if numel(find(isnan(tpolyg))) >0
            error('debug me');
        end
        tot_area = tot_area+parea;
        cond3=(numel(Polyg{1})+numel(Polyg{2})+numel(Polyg{3})+numel(Polyg{4})+numel(Polyg{5})) > 0;

        % zyd new code
        if cond1 & cond2 & ~cond3
            Polyg{2} = [640 1; 640 640; 1 640; 1 1];
            cond3 = 1;
            tot_area = w*h;
        end

        if (tot_area/w/h)<0.8 | (tot_area/w/h) > 1.2 | ~cond1 | ~cond2 | ~cond3
            continue;
        else

            for f=1:5
                polyg{cnt,f}=Polyg{f};
            end
            [Polyg]=clipPolyg(Polyg,h,w);
            if numel(Polyg)>0
                %                     tic
                [features] =getLayoutfeats(Polyg,integData,vp,h,w,0,quantsiz);
                %                     toc
            end

            Features(cnt,:)=features;

            cnt=cnt+1;
        end

    end

    Features(cnt:end,:)=[];
    polyg(cnt:end,:)=[];

    if size(Features,1)~=size(polyg,1)
        disp('stop');
        keyboard;
    end

end
end