function varargout = setdiff(varargin)
% Adds support for 'stable' input flag with one output
if iscell(varargin{1}) && ~iscell(varargin{2}), varargin{2} = {varargin{2}}; end
if iscell(varargin{2}) && ~iscell(varargin{1}), varargin{1} = {varargin{1}}; end
if nargin>=3 && strcmp(varargin{end},'stable')
    if strcmp(varargin{3},'rows')
        y = [varargin{1}; varargin{2}];
        [a, ~, x] = unique(y,'rows');
        x1 = x(1:size(varargin{1},1));
        x2 = x(size(varargin{1},1)+1:end);
    else
        y = [varargin{1}(:); varargin{2}(:)];
        [a, ~, x] = unique(y);
        x1 = x(1:numel(varargin{1}));
        x2 = x(numel(varargin{1})+1:end);
    end
    ind = ~ismember(x1, x2);
    x = x1(ind);
    if ~isempty(x)
        x = x(~any(triu(bsxfun(@eq, x, x.'),1)));
    end
    if strcmp(varargin{3},'rows')
        y = a(x,:);
    else
        y = a(x);
    end
    if ~strcmp(varargin{3},'rows') && isrow(varargin{1}) % row output if first input is row
        y = reshape(y,1,[]);
    end
    varargout{1} = y;
else
    if strcmp(varargin{end},'sorted'), varargin(end) = []; end
    varargout = cell(1,max(nargout,1)); % if called without outputs, nargout will be zero. In that case we return one output
    [varargout{:}] = builtin('setdiff', varargin{:});
end
end


function [A,b,c,lb,ub] = ls_preprocess(A,b,c,lb,ub,opts)
% PREPROCESS  - Preprocessing input data.
% Usage:  [A,b,c,lb,ub,probData] = preprocess(A,b,c,lb,ub,probData)

% Yin Zhang, last updated April, 1995
% Department of Mathematics and Statistics
% University of Maryland  Baltimore County
% Modified J.Currie AUT May 2013

global probData

verb = opts.verb;

if(verb), fprintf('LIPSOL Preprocessing ...\n'); end

%Ensure columns
if(size(b,2) > 1), b = b'; end
if(size(c,2) > 1), c = c'; end
if(size(lb,2) > 1), lb = lb'; end
if(size(ub,2) > 1), ub = ub'; end

%Check problem sizes
[m,n] = size(A);
if(m ~= size(b,1)), error('A does not have the same number of rows as b'); end
if(n ~= size(c,1)), error('A does not have the same number of colums as c'); end
if(n ~= size(lb,1)), error('lb does not have the same number of elements as c'); end
if(n ~= size(ub,1)), error('ub does not have the same number of elements as c'); end

if any(lb > ub)
   if(verb), fprintf('\nPreprocessor: Lower bound exceeds upper bound\n'); end
   probData.isFeasible = 0;
   return;
end

%Convert Infinite Bounds to "BIG"
ub(isinf(ub)) = opts.big;
%Check for infinite lower bounds (should be allowed, but no goood...)
if(any(isinf(lb))), throwAsCaller(MException('OPTI:LIPSOLINFLB','LIPSOL only solves problems with Finite Lower Bounds')); end

if(~issparse(A)), A = sparse(A); end;
b = sparse(b); c = sparse(c);
lb = sparse(lb);

%----- delete fixed variables -----
fixed = lb == ub;
probData.Fixed_exist = any(fixed);
if (probData.Fixed_exist)
   ifix = find(fixed);
   infx = find(1 - fixed);
   xfix = lb(ifix);
   c    = c(infx);
   b    = b - A(:,ifix)*sparse(xfix);
   A    = A(:,infx);
   lb = lb(infx);
   ub = ub(infx);
   if(verb), fprintf(' - %i fixed vars\n', length(ifix)); end
   probData.data_changed = 1;
   probData.ifix = ifix;
   probData.infx = infx;
   probData.xfix = xfix;
end

%----- delete zero rows -----
rnnzct = sum(spones(A'));
if any(rnnzct == 0)
   izrows = find(rnnzct == 0);
   if any(b(izrows) ~= 0)
      if(verb), fprintf('\nPreprocessor: problem infeasible\n'); end
      probData.isFeasible = 0;
      return;
   end;
   inzrows = find(rnnzct > 0);
   A = A(inzrows,:); b = b(inzrows);
   rnnzct = rnnzct(inzrows);
   if(verb), fprintf(' - %i 0-rows', length(izrows)); end
   probData.data_changed = 1; m = size(A,1);
end

%----- make A structurally "full rank" -----
sprk = sprank(A');
if (sprk < m)
   [dmp, ~] = dmperm(A);
   irow = dmp(1:sprk);
   A = A(irow,:); b = b(irow);
   rnnzct = rnnzct(irow);
   if(verb), fprintf(' - %i dep-rows\n', m-sprk); end
   probData.data_changed = 1;
end

%----- delete zero columns -----
zrcol = (max(abs(A)) == 0)';
if any(zrcol == 1)
   probData.Zrcols_exist = 1;
   izrcol = find(zrcol);
   if any(c(izrcol) < 0 & ub(izrcol) > opts.big-1)
      if(verb), fprintf('\nPreprocessor: problem unbounded below\n'); end
      probData.isFeasible = 0;
      return;
   end
   xzrcol = zeros(size(izrcol))...
          + (c(izrcol) < 0).*ub(izrcol)...
          + (c(izrcol) > 0).*lb(izrcol);
   inzcol = find(1 - zrcol);
   A = A(:,inzcol);
   c = c(inzcol);
   lb = lb(inzcol);
   ub = ub(inzcol);
   if(verb), fprintf(' - %i 0-columns\n', nnz(zrcol)); end
   probData.data_changed = 1;
   probData.izrcol = izrcol;
   probData.xzrcol = xzrcol;
   probData.inzcol = inzcol;
end

%----- solve singleton rows -----
singleton = (rnnzct == 1);
nsgrows = nnz(singleton);
if nsgrows >= max(1, .01*size(A,1))
   probData.Sgtons_exist = 1;
   isgrows = find(singleton);
   iothers = find(1 - singleton);
   if(verb), fprintf(' - %i singletons\n',nsgrows); end

   Atmp = A(isgrows,:); Atmp1 = spones(Atmp); btmp = b(isgrows);
   if nsgrows == 1
      isolved  = find(Atmp1);
      insolved = find(Atmp1 == 0);
      xsolved  = b(isgrows)/Atmp(isolved);
   else
      colnnzct = sum(Atmp1);
      isolved  = find(colnnzct);
      insolved = find(colnnzct == 0);
      [ii, jj] = find(Atmp);
      Atmp = Atmp(ii,jj); btmp = btmp(ii);
      xsolved  = btmp./diag(Atmp);
      if any(colnnzct >  1)
         repeat = diff([0; jj]) == 0;
         for i = 1:length(xsolved) - 1
             if repeat(i+1) && xsolved(i+1) ~= xsolved(i)
                if(verb), fprintf('\nPreprocessor: problem infeasible\n'); end
                probData.isFeasible = 0;
                return;
             end;
         end;
         ii = find(~repeat); jj = ii;
         Atmp = Atmp(ii,jj); btmp = btmp(ii);
         xsolved  = btmp./diag(Atmp);
      end;
   end;

   if (any(xsolved < lb(isolved)) || any(xsolved > ub(isolved)))
      if(verb), fprintf('\nPreprocessor: problem infeasible\n'); end
      probData.isFeasible = 0;
      return;
   end;

   b = b(iothers) - A(iothers,isolved)*xsolved;
   A = A(iothers, insolved);
   c = c(insolved);
   lb = lb(insolved);
   ub = ub(insolved);
   probData.data_changed = 1;
   probData.isolved = isolved;
   probData.insolved = insolved;
   probData.xsolved = xsolved;
end

%----- shift nonzero lower bounds -----
probData.Lbounds_non0 = any(lb ~= 0);
if (probData.Lbounds_non0)
   b = b - A*lb;
   probData.data_changed = 1;
end

%----- find upper bounds -----
iubounds = ub < opts.big - 1;
probData.Ubounds_exist = full(any(iubounds));
if (probData.Ubounds_exist)
   ub = sparse(iubounds.*(ub-lb));
   probData.nub = nnz(ub);
end

[m, n] = size(A); probData.NNZA = nnz(A);
if(verb), fprintf('[m n] = [%d %d]\n',m,n); end


% put a vector in selected positions of a matrix.
%
function [output] = F_copyVec2Mat(input_layer, curr_layer)
input = input_layer.a;

[D,T,N] = size(input);
D1 = curr_layer.targetDims(1);
D2 = curr_layer.targetDims(2);
index2copy = curr_layer.index2copy;

if IsInGPU(input(1))
    output = gpuArray.zeros(D1, D2, T, N);
    tmp = gpuArray.zeros(D1,D2);
else
    output = zeros(D1, D2, T, N);
    tmp = zeros(D1,D2);
end

for t=1:T
    for n = 1:N
        tmp(index2copy) = input(:,t,n);
        output(:,:,t,n) = tmp;
    end
end

end


function output = callsdpnal(interfacedata)

% Retrieve needed data
options = interfacedata.options;
F_struc = interfacedata.F_struc;
c       = interfacedata.c;
K       = interfacedata.K;
x0      = interfacedata.x0;
ub      = interfacedata.ub;
lb      = interfacedata.lb;

% Bounded variables converted to constraints
if ~isempty(ub)
    [F_struc,K] = addStructureBounds(F_struc,K,ub,lb);
end

[blk,A,C,b,oldKs]=sedumi2sdpt3(F_struc(:,1),F_struc(:,2:end),c,K,1);

if options.savedebug
    ops = options.sdpnal;
    save sdpnaldebug blk A C b ops -v6
end

if options.showprogress;showprogress(['Calling ' interfacedata.solver.tag],options.showprogress);end
solvertime = tic;
if options.verbose==0
    evalc('[obj,X,s,y,Z,Z2,y2,v,info,runhist] = sdpnalplus(blk,A,C,b,[],[],[],[],[],options.sdpnal);');
else
    [obj,X,s,y,Z,Z2,y2,v,info,runhist] = sdpnalplus(blk,A,C,b,[],[],[],[],[],options.sdpnal);
end
solvertime = toc(solvertime);

% Create YALMIP dual variable and slack
Dual = [];
Slack = [];
top = 1;
if K.f>0
    Dual = [Dual;X{top}(:)];
    Slack = [Slack;Z{top}(:)];
    top = top+1;
end
if K.l>0
    Dual = [Dual;X{top}(:)];
    Slack = [Slack;Z{top}(:)];
    top = top + 1;
end
if K.q(1)>0
    Dual = [Dual;X{top}(:)];
    Slack = [Slack;Z{top}(:)];
    top = top + 1;
end
if K.s(1)>0
    % Messy format in SDPT3 to block and sort small SDPs
    u = blk(:,1);
    u = find([u{:}]=='s');
    s = 1;
    for top = u
        ns = blk(top,2);ns = ns{1};
        k = 1;
        for i = 1:length(ns)
            Xi{oldKs(s)} = X{top}(k:k+ns(i)-1,k:k+ns(i)-1);
            Zi{oldKs(s)} = Z{top}(k:k+ns(i)-1,k:k+ns(i)-1);
            s = s + 1;
            k = k+ns(i);
        end
    end
    for i = 1:length(Xi)
        Dual = [Dual;Xi{i}(:)];
        Slack = [Slack;Zi{i}(:)];
    end
end
Primal = -y;  % Primal variable in YALMIP

% No error code available
if isfield(info,'termcode')
    switch info.termcode
        case -1
            problem = 4;
        case -2
            problem = 3;
        case 0
            problem = 0;
        case 1
            problem = 5;
        case 2
            problem = 3;
        otherwise
            problem = 11;
    end
else
    if isfield(info,'msg')
        if isequal(info.msg,'maximum iteration reached')
            problem = 3;
        else
            problem = 9;
        end
    end
end

infostr = yalmiperror(problem,interfacedata.solver.tag);

if options.savesolveroutput
    solveroutput.obj = obj;
    solveroutput.X = X;
    solveroutput.y = y;
    solveroutput.Z = Z;
    solveroutput.info = info;
    solveroutput.runhist = runhist;
 else
    solveroutput = [];
end

if options.savesolverinput
    solverinput.blk = blk;
    solverinput.A   = A;
    solverinput.C   = C;
    solverinput.b   = b;
    solverinput.options   = options.sdpnal;
else
    solverinput = [];
end

% Standard interface
output = createOutputStructure(Primal,Dual,[],problem,infostr,solverinput,solveroutput,solvertime);

function [F_struc,K] = deblock(F_struc,K);
X = any(F_struc(end-K.s(end)^2+1:end,:),2);
X = reshape(X,K.s(end),K.s(end));
[v,dummy,r,dummy2]=dmperm(X);
blks = diff(r);

lint = F_struc(1:end-K.s(end)^2,:);
logt = F_struc(end-K.s(end)^2+1:end,:);

newlogt = [];
for i = 1:size(logt,2)
    temp = reshape(logt(:,i),K.s(end),K.s(end));
    temp = temp(v,v);
    newlogt = [newlogt temp(:)];
end
logt = newlogt;

pattern = [];
for i = 1:length(blks)
    pattern = blkdiag(pattern,ones(blks(i)));
end

F_struc = [lint;logt(find(pattern),:)];
K.s(end) = [];
K.s = [K.s blks];
K.m = blks;


function [ IDX,timestamps ] = bz_INTtoIDX(INT,varargin)
%[IDX] = bz_INTtoIDX(INT) Converts state on/offsets to vector of indices
%
%INPUT
%   INT:    {nstates} cell array of [nintervals x 2] start and end times.
%                       (optional) can be TSObject intervalSet
%           -or-
%           structure with fields: INT.NAMEstate
%   (optional)
%   'statenames'    cell array of state names (position correponds to state number)
%   'sf'            desired sampling frequency of the output vector (default: 1s)
%   'length'        desired length of the index vector (default: max end time)
%
%OUTPUT
%   IDX:    [len x 1] vector of state indices, where states are identified by
%           integers starting from 1, 0 are unmarked.
%           -or-
%           structure with fields:  IDX.statenames
%           (see buzcode wiki)      IDX.states
%                                   IDX.timestamps
%   timestamps
%
%DLevenstein 2015
%Updated 2018 for buzcode
%% DEV
%INT = SleepState.ints;
%statenames = {'WAKE','','NREM','','REM'};
%%
p = inputParser;
addParameter(p,'statenames',[],@iscell)
addParameter(p,'sf',1)
addParameter(p,'length',Inf)
parse(p,varargin{:})
statenames = p.Results.statenames;
sf = p.Results.sf;
len = p.Results.length;
%% Deal with Input Types
%For Buzcode ints structure
if isstruct(INT)
    STRUCTIN = true;
    %Get the NAMEs of the states from the structure (INT.NAMEstate)
    fields = fieldnames(INT);
    endState = cellfun(@(X) contains(X,'state'),fields)';
    fieldstates = cellfun(@(X) char(extractBefore(X,'state')),fields(endState),'uniformoutput',false)';

    if ~isempty(statenames) %Check if there are any states the user didn't put in
        samestates = ismember(fieldstates,statenames);
        %Here: if you find any states in struct not in input, prompt user
        for ss = 1:length(samestates); if samestates(ss)==0
                statenum = inputdlg(['What number would you like state ''',fieldstates{ss},''' to be']);
                statenum = str2num(statenum{1});
                statenames{statenum} = fieldstates{ss};
        end; end
    else
        statenames = fieldstates;
    end

    %Convert to the cell array format needed for this function
    for ss = 1:length(statenames)
        if isempty(statenames{ss})
            continue;
        elseif  ~ismember(statenames{ss},fieldstates)
            INTtemp{ss} = [];
            continue;
        end
        INTtemp{ss} = INT.([statenames{ss},'state']);
    end
    INT = INTtemp;
else
    STRUCTIN = false;
end

%TSToolbox
if isa(INT,'intervalSet')
    INT = {[Start(INT,'s'), End(INT,'s')]};
end

%%

%Convert from seconds to dt = 1/sf
INT = cellfun(@(X) X*sf,INT,'UniformOutput',false);

%Getting the length of the output
if isinf(len)
    allints = cat(1,INT{:});
    len = ceil(max(allints(:,2)));
end

%%

IDX = zeros(len,1);

numstates = length(INT);
statenums = 1:numstates; %for possible later implementation of non 1:numstates nums
for ss = statenums
    if isempty(INT{ss}); continue; end
    stateints = round(INT{ss});

    stateints(stateints==0)=1;
    stateints(isinf(stateints))=len;

    numints = length(stateints(:,1));
    for ii = 1:numints
        IDX(stateints(ii,1):stateints(ii,2))=ss;
    end
end

switch numstates
    case 1
        IDX = logical(IDX);
    otherwise
end

timestamps = [1:length(IDX)]'./sf;

%% Convert to structure
if STRUCTIN
    IDXstruct.states = IDX;
    IDXstruct.timestamps = timestamps;
    IDXstruct.statenames = statenames;
    IDX = IDXstruct;
end

end


function [dat, volInfo, cl] = iimg_threshold(image_names, varargin)
% Thresholds images to be at least thresh(1) and at most thresh(2)
%
% :Usage:
% ::
%
%     function [dat, volInfo, cl] = iimg_threshold(image_names, varargin)
%
% :Input types for image names:
%   1) String matrix of filenames
%   2) 4-D array of 3-D data volumes
%   3) voxels x images 2-D index array
%   4) image_vector object
%
% :Outputs:
%
%   **imdat:**
%        index vector of thresholded data
%
%   **volInfo:**
%        structure of info about volume
%
%   **cl:**
%        optional (slower) clusters structure from dat
%
% :Command strings:
%
%   **'imgtype':**
%        followed by 't', 'p', or 'data' (default)
%       specify type of values in image
%
%   **'threshtype':**
%        followed by 't' or 'p'
%
%   **'df':**
%        followed by degrees of freedom, for p- and t-image threshold calc
%
%   **'k':**
%        followed by extent threshold in voxels (slower)
%
%   **'abs':**
%        absolute value must be > threshold.  Use to get both pos. and neg.
%        results in two-tailed test.
%
%   **'intersect:**
%        Create intersection of images; uses abs, so + and - values
%        count as yesses for intersection
%
%   **'contrast':**
%        followed by contrasts across images
%
%   **'volInfo:**
%        followed by volInfo structure.  Necessary for extended output
%
% :Examples:
% ::
%
%    % Threshold an image set (p) to be at least zero
%    image_names =
%    /Users/tor/Documents/Tor_Documents/CurrentExperiments/Lab/Pre-appraisal/Results/rscalped_avg152T1_graymatter_smoothed.img
%    /Users/tor/Documents/Tor_Documents/CurrentExperiments/Lab/Pre-appraisal/Results/t_intercept.img
%
%    [dat, volInfo] = iimg_threshold(image_names, 'thr', 0);
%
%    % Do the same, but take the intersection and write an output image
%    [dat, volInfo] = iimg_threshold(image_names, 'thr', 3, 'outnames', 'intersct', 'masked_t.img');
%
%
%    % Threshold a t-image based on a p-value and a df
%    image_names = '/Users/tor/Documents/Tor_Documents/CurrentExperiments/Lab/Pre-appraisal/Results/t_intercept.img'
%    [dat, volInfo] = iimg_threshold(image_names, 'thr', .005, 'imgtype', 't', 'threshtype', 'p', 'df', 28, 'outnames', 'thresh_t.img');
%
%    cl = mask2clusters('masked_t.img');
%    cluster_orthviews(cl);
%
%    % The same, but threshold based on absolute value (+ and - values)
%    [dat, volInfo] = iimg_threshold(image_names, 'thr', .005, 'abs', 'imgtype', 't', 'threshtype', 'p', 'df', 28, 'outnames', 'thresh_t.img');
%
%    % Threshold a p-value image directly
%    [dat, volInfo] = iimg_threshold('X-M-Y_pvals.img', 'thr', [0 .05], 'outnames', 'X-M-Y_pvals_thresh.img');
%    [dat, volInfo, cl] = iimg_threshold(inname, 'thr', [0 .05], 'outnames', outname);
%
%    % Threshold a p-value image, with cluster sizes
%    [dat, volInfo, cl] = iimg_threshold(inname, 'thr', [0 .05], 'k', 10);
%
%    % Threshold and display a t-image using FDR, getting both positive and negative results
%    [dat, volInfo, cl] = iimg_threshold('contrast_t.img', 'imgtype', 't', 'df', 37, 'thr', .2, 'threshtype', 'fdr', 'k', 3, 'abs');
%    cluster_orthviews(cl);
%    spm_orthviews_hotcool_colormap(cat(2,cl.Z), 1.52);
%
% ..
%    Authorship and Updates:
%    Created by Tor Wager, edited by Matthew Davidson
%    Update April 2007 by TW : correct FDR-thresholding bug
% ..

    % ..
    %    Set up arguments
    % ..

    df = []; % defaults
    % maskname = deblank(image_names(1, :));
    thr = [0 Inf];                  % must be > 0, < Inf
    imgtype = 'data';               % could be data, t, p, or F
    threshtype = 'none';
    mask = [];
    k = 1;
    dointersect = 0;
    con = [];
    outnames = [];
    doabs = 0;                      % absolute value thresholding
    extended_output_flag = 2;    %*(nargout > 2); % yes if we've requested clusters to be created needed for extent also

    % inputs
    for i = 1:length(varargin)
        arg = varargin{i};
        if ischar(arg)
            switch lower(arg)
                case 'imgtype', imgtype = varargin{i+1};
                case 'threshtype', threshtype = varargin{i+1};
                case 'df', df = varargin{i+1};
                case {'thr', 'threshold'}, thr = varargin{i+1};
                case 'k', k = varargin{i+1};
                case 'intersect', dointersect = 1;
                case 'mask', mask = varargin{i+1};
                case 'contrast', con = varargin{i+1};
                case 'outnames', outnames = varargin{i+1};
                case 'abs', doabs = 1;
                case 'volinfo', volInfo = varargin{i+1};
            end
        end
    end

    % Make upper threshold infinity if not entered
    if(length(thr) < 2)
        switch threshtype
            case 'p'
                thr = [0 thr];
            case 'fdr'
                % threshold should be a single p-value, which is converted
                % to [0 fdr_thresh] by convert_threshold, below
                % check and make sure p-value
                if thr < eps || thr > 1
                    error('Invalid threshold (thr) for FDR: must be p-value threshold.');
                end

            case 't'
                thr = [thr Inf];

            case 'none'
                % we should have a data image
                if ~strcmp(imgtype, 'data'), error('You must use imgtype ''data'' (default) if you do not enter a threshold type (''t'' or ''p'')'); end

                thr = [thr Inf];

            otherwise
                error('Unknown threshold type (''threshtype'').');
        end
    end

    %% --------------------------------------
    % * Read image data
    % --------------------------------------
    if isa(image_names, 'statistic_image')
        tmpVolInfo = image_names.volInfo;
        image_names = replace_empty(image_names);
        dat = image_names.dat(:, 1);
    else
        [tmpVolInfo, dat] = iimg_read_img(image_names, extended_output_flag);
    end

    if issparse(dat), dat = full(dat); end
    clear image_names

    % use input volInfo if entered; this is so you can input an indexed image
    % instead of a filename and get extended output (cluster sizes)
    if ~exist('volInfo', 'var'), volInfo = tmpVolInfo; end
    clear tmpVolInfo

    if ~isempty(mask)
        dat = iimg_mask(mask,dat,volInfo);
    end

    if dointersect
        % If any of the input images has a zero (the designated "no value") for a voxel, then clear it out for all images
        wh = any(dat==0,2);
        dat(wh,:) = 0;
    end

    % --------------------------------------
    % * Convert and apply threshold
    % --------------------------------------
    thr = convert_threshold(imgtype, threshtype, thr, df, dat);

    if doabs
        whzero = abs(dat) < thr(1) | abs(dat) > thr(2);  % remove these values
    else
        whzero = dat < thr(1) | dat > thr(2);
    end
    dat(whzero) = 0;

    %% --------------------------------------
    % * Apply size threshold
    % --------------------------------------
    [dat, nvox] = iimg_cluster_extent(dat, volInfo, k);

    %% --------------------------------------
    % special operations
    % --------------------------------------
    if ~isempty(con)
        % Apply contrast(s) across images
        dat = apply_contrast(dat, con);
    end

    %% --------------------------------------
    % * Write out image names, if asked
    % --------------------------------------
    if ~isempty(outnames)
        iimg_write_images(dat, volInfo, outnames);
    end

    %% --------------------------------------
    % * clusters output
    % --------------------------------------
    if extended_output_flag

        % could enter u and k here, but don't need to because it's already
        % thresholded; also, neg. elements will be removed in some cases if
        % threshold is re-applied here.

        %cl = iimg_indx2clusters(dat, volInfo, thr, k);
        cl = iimg_indx2clusters(dat, volInfo);
    end
end

% Sub-functions

function thr = convert_threshold(imgtype, threshtype, thr, df, dat)
    % handle FDR
    switch imgtype
        case 'data'
            if(strcmp(threshtype, 'fdr'))
                error('FDR thresholding has no meaning for data images. Try using a t- or a p-image');
            end
        case 't'
            switch threshtype
                case 't'
                case 'p'
                    % convert p-value threshold to t-value threshold
                    if ~exist('df', 'var') || isempty(df)
                        error('You must enter df to use p-value based thresholding with a t img.');
                    end
                    thr(~isinf(thr)) = tinv(1-thr(~isinf(thr)), df);
                case 'fdr'
                    % convert t-values in image to p-values for FDR
                    % thresholding
                    if ~exist('df', 'var') || isempty(df)
                        error('You must enter df to use p-value based thresholding with a t img.');
                    end
                    pdat = 1 - tcdf(dat(dat ~= 0 & ~isnan(dat)), df); % zero is a special invalid value

                    fdr_threshold = FDR(pdat, thr); % get p-value threshold
                    if isempty(fdr_threshold), fdr_threshold = 0; end

                    fprintf('Computed FDR threshold. For p < %.3f corrected, p-threshold is %.7f, ', thr, fdr_threshold);
                    thr = [tinv(1-fdr_threshold, df) Inf];

                    fprintf('t-threshold is %.2f\n', thr(1));

                otherwise
                    error('Threshold type must be t or p values for t-images')
            end

        case 'p'
            switch threshtype
                case 't'
                    if ~exist('df', 'var') || isempty(df)
                        error('You must enter df to use t-value based thresholding with a p img.');
                    end
                    thr = 1 - tcdf(thr, df);
                case 'p' % do nothing
                case 'fdr'

                    dat = dat(dat ~= 0 & ~isnan(dat)); % zero is a special invalid value

                    fdr_threshold = FDR(dat, thr);
                    if isempty(fdr_threshold), fdr_threshold = 0; end

                    %thr(isinf(thr)) = fdr_threshold;
                    fprintf('Computed FDR threshold. For p < %.3f corrected, p-threshold is %.7f, ', thr, fdr_threshold);

                    thr = [0 fdr_threshold];  % from zero to new thresh
                otherwise
                    error('Threshold type must be t or p values for p-images')
            end
    end
end

function condat = apply_contrast(dat, con)
    if size(con, 2) ~= size(dat, 2)
        error('Contrast matrix must have as many columns as images.');
    end

    condat(:, i) = dat * con';
end


function test_bug1514

% WALLTIME 00:10:00
% MEM 1gb
% DEPENDENCY ft_spike_select ft_selectdata

% the following structure corresponds to the one explained in
% ft_datatype_spike

spike = [];
spike.label = {'unit1' 'unit2' 'unit3'};
spike.timestamp = {randn(1,504) randn(1,50) randn(1,101)};
spike.time = {randn(1,504) randn(1,50) randn(1,101)};
spike.trial = {ceil(rand(1,504)*100) ceil(rand(1,50)*100) ceil(randn(1,101)*100)};
spike.trialtime = 3*randn(100,2);
spike.waveform = {randn(1,32,504) randn(1,32,50) randn(1,32,101)};
spike.waveformdimord = '{chan}_lead_time_spike';
spike.fourierspctrm = {randn(504,2,20), randn(50,2,20), randn(101,2,20)};
spike.fourierspctrmdimord = '{chan}_spike_lfplabel_freq';
spike.lfplabel = {'lfpchan1', 'lfpchan2'};
spike.freq = 1:20;

cfg = [];
cfg.trials = 1:50;
output = ft_selectdata(cfg, spike);

cfg = [];
cfg.channel = 2;
output = ft_selectdata(cfg, spike);

cfg = [];
cfg.latency = 'prestim';
output = ft_selectdata(cfg, spike);

cfg = [];
cfg.trials = 1:50;
cfg.channel = 2;
cfg.latency = 'prestim';
output = ft_selectdata(cfg, spike);

assert(all(output.time{1}<=0));
assert(all(output.trial{1}>=1 & output.trial{1}<=50));
assert(isequal(output.label, {'unit2'}));


function[overlaps] = computeBlobOverlapSum(propBlobsA, propBlobsB, imageSize)
% [overlaps] = computeBlobOverlapSum(propBlobsA, propBlobsB, imageSize)
%
% Take Sel. Search regions and reconstruct which regions overlap by how many pixels.
% (result is a matrix)
%
% Copyright by Holger Caesar, 2015

if numel(imageSize) == 3,
    imageSize = imageSize(1:2);
end;
propCountA = numel(propBlobsA);
propCountB = numel(propBlobsB);
overlaps = zeros(propCountA, propCountB); %Dense is fine

% Precompute blob inds
blobsIndsA = cell(propCountA, 1);
for i = 1 : propCountA,
    blob = propBlobsA(i);
    blobsIndsA{i} = blobToImageInds(blob, imageSize);
end;

blobsIndsB = cell(propCountB, 1);
for i = 1 : propCountB,
    blob = propBlobsB(i);
    blobsIndsB{i} = blobToImageInds(blob, imageSize);
end;

for i = 1 : propCountA,
    for j = 1 : propCountB,
        % Compute the intersection / union
        % (Faster than ismember())
        overlaps(i, j) = sum(builtin('_ismemberhelper', blobsIndsA{i}, blobsIndsB{j}));
%         assert(overlap == sum(ismember(blobsIndsA{i}, blobsIndsB{j})));
%         assert(sum(ismember(blobsIndsA{i}, blobsIndsB{j})) == sum(ismember(blobsIndsA{j}, blobsIndsB{i})));
    end;
end;


function [alignedSignal] = alignSignal(responseSignal, alignmentSignal,timeSeq,varargin)
	% Aligns values in a response signal (can be multiple response signals) to binary points in an alignment signal (e.g. 1=align to this time-point, 0=don't align).
	% Biafra Ahanonu
	% started: 2013.11.13 [23:47:34]
	% inputs
		% responseSignal = MxN matrix of M signals over N points
		% alignmentSignal = a 1xN vector of 0s and 1s, where 1s will be alignment points
		% timeSeq = 1xN sequence giving time around alignments points to process, e.g. -2:2.
	% options
		% overallAlign = align all response signals to alignmentSignal pts
	% outputs
		% alignedSignal = a matrix of size 1xlength(timeSeq) if sum all signals or Mxlength(timeSeq) if keep the sums for each signal separate

	[alignedSignal] = ciapkg.signal_processing.alignSignal(responseSignal, alignmentSignal,timeSeq,'passArgs', varargin);
end


function esvm_show_exemplar_frames(allmodels, N_PER_PAGE, dataset_params)
% Draw the initialized exemplar frames as a 1x3 row of 3 images
% Shows these 3 fields: input+gtbb+template, template mask+gtbb, HOG descriptor
% The visualization really shows what the template region is, and
% its relation to the ground-truth selection region
%
% Copyright (C) 2011-12 by Tomasz Malisiewicz
% All rights reserved.
%
% This file is part of the Exemplar-SVM library and is made
% available under the terms of the MIT license (see COPYING file).
% Project homepage: https://github.com/quantombone/exemplarsvm

if ~exist('dataset_params','var')
  dataset_params = [];
end

pinds = do_partition(1:length(allmodels),N_PER_PAGE);
for i = 1:length(pinds)
  models = allmodels(pinds{i});

  figure(i)
  clf
  N = length(models);
  for i = 1:N
    m = models{i};
    o = (i-1)*3;
    subplot(N,3,o+1)
    I = convert_to_I(m.I);
    imagesc(I)
    plot_bbox(m.model.bb(1,:),'',...
              [1 0 0], [0 1 0], 0 ,[1 3],...
              m.model.hg_size)
    plot_bbox(m.gt_box,'',[0 0 1])
    axis image
    axis off
    title(sprintf('Ex %s.%d %s',m.curid,m.objectid,m.cls))

    subplot(N,3,o+2)
    onimage = m.model.mask*1;
    onimage(onimage==0) = 2;
    colors = [1 0 0; 0 0 1];
    cim = colors(onimage(:),:);
    cim = reshape(cim,[size(m.model.mask,1) size(m.model.mask,2) 3]);
    imagesc(cim);
    fullimbox = [0 0 size(cim,2) size(cim,1)]+.5;
    xform = find_xform(m.model.bb(1,1:4), fullimbox);
    gtprime = apply_xform(m.gt_box,xform);
    plot_bbox(fullimbox,'',...
              [1 0 0], [0 1 0], 0 ,[1 3],...
              m.model.hg_size)
    plot_bbox(gtprime,'',[0 0 1])
    axis image
    axis off
    grid on
    [u,v] = find(m.model.mask);

    curselection = [min(v) min(u) max(v) max(u)];
    curos = getosmatrix_bb(curselection, gtprime);

    title(sprintf('%s: Template:[%d x %d] \ncuros=%.2f Mask: [%d x %d]',...
                  m.model.init_params.init_type,...
                  m.model.hg_size(1),m.model.hg_size(2),...
                  curos,range(u)+1,range(v)+1));

    subplot(N,3,o+3)
    hogim = HOGpicture(repmat(m.model.mask,[1 1 size(m.model.w,3)]).* ...
                       m.model.w);
    imagesc(hogim)
    axis image
    axis off
    grid on
    title('HOG features')
    drawnow
  end
end


function prob = yalmip2mosek(interfacedata);

% Retrieve needed data
options = interfacedata.options;
F_struc = interfacedata.F_struc;
c       = interfacedata.c;
Q       = interfacedata.Q;
K       = interfacedata.K;
x0      = interfacedata.x0;
integer_variables = interfacedata.integer_variables;
binary_variables = interfacedata.binary_variables;
extended_variables = interfacedata.extended_variables;
ub      = interfacedata.ub;
lb      = interfacedata.lb;
mt      = interfacedata.monomtable;

% *********************************
% What type of variables do we have
% *********************************
linear_variables = find((sum(abs(mt),2)==1) & (any(mt==1,2)));
nonlinear_variables = setdiff((1:size(mt,1))',linear_variables);
sigmonial_variables = find(any(0>mt,2) | any(mt-fix(mt),2));

if ~isempty(sigmonial_variables) | isequal(interfacedata.solver.version,'GEOMETRIC')
    prob = create_mosek_geometric(options,F_struc,c,Q,K,ub,lb,mt,linear_variables,extended_variables);
else
    prob = create_mosek_lpqp(options,F_struc,c,Q,K,ub,lb,mt,linear_variables,integer_variables);
end

function prob = create_mosek_lpqp(options,F_struc,c,Q,K,ub,lb,mt,linear_variables,integer_variables);

prob.c = c;
if ~isempty(F_struc)
    prob.a = -F_struc(:,2:end);
    prob.buc = full(F_struc(:,1));
    prob.blc = repmat(-inf,length(prob.buc),1);
else
    prob.a = sparse(ones(1,length(c))); % Dummy constraint
    prob.buc = inf;
    prob.blc = -inf;
end
if isempty(lb)
    prob.blx = repmat(-inf,1,length(c));
else
    prob.blx = lb;
end
if isempty(ub)
    prob.bux = repmat(inf,1,length(c));
else
    prob.bux = ub;
end

if K.f>0
    prob.blc(1:K.f) = prob.buc(1:K.f);
end

[prob.qosubi,prob.qosubj,prob.qoval] = find(tril(sparse(2*Q)));

if any(K.q)
    nof_new = sum(K.q);
    prob.a = [prob.a [spalloc(K.f,nof_new,0);spalloc(K.l,nof_new,0);speye(nof_new)]];
    %prob.a(1+K.f+K.l:end,1:length(c)) = prob.a(1+K.f+K.l:end,1:length(c));
    prob.blc(1+K.f+K.l:end) = prob.buc(1+K.f+K.l:end);
    prob.buc(1+K.f+K.l:end) = prob.buc(1+K.f+K.l:end);
    prob.c = [prob.c;zeros(nof_new,1)];
    top = size(F_struc,2)-1;
    for i = 1:length(K.q)
        prob.cones{i}.type = 'MSK_CT_QUAD';
        prob.cones{i}.sub  = top+1:top+K.q(i);
        prob.blx(top+1:top+K.q(i)) = -inf;
        prob.bux(top+1:top+K.q(i)) = inf;
        top = top + K.q(i);
    end
end

if ~isempty(integer_variables)
    prob.ints.sub = integer_variables;
end

prob.param = options.mosek;

function prob = create_mosek_geometric(options,F_struc,c,Q,K,ub,lb,mt,linear_variables,extended_variables);

x = [];
D_struc = [];
res = [];
solvertime = 0;
[prob,problem] = yalmip2geometric(options,F_struc,c,Q,K,ub,lb,mt,linear_variables,extended_variables);
if problem == 0

    % Mosek does not support equalities
    if ~isempty(prob.G)
        prob.A = [prob.A;prob.G;-prob.G];
        prob.b = [prob.b;prob.h;1./prob.h];
        prob.map = [prob.map;max(prob.map) + (1:2*length(prob.h))'];
    end

else
    prob = [];
end


function [limits state] = hlp_adaptMinMaxLimits(varargin)
% adapt min and max limits using an exponential window moving average. The
% moving average is calculated in place based on new data values and
% previous min/max limits.

g = arg_define(varargin, ...
        arg_norep({'values'},[],[],'data values. can be scalar, vector or matrix'), ...
        arg_nogui({'state'},[],[],'current state of the adaptation'), ...
        arg_sub({'adaptOpts'},{},@hlp_scaleLimits,'Adaptation options'), ...
        arg({'reset'},false,[],'Reset adaptation state') ...
        );

state = g.state;

if g.reset || isempty(state)
    % initialize state
    state.lastMin      = min(g.values(:));
    state.lastMax      = max(g.values(:));
    state.numRunsSoFar = 0;
end

if isfield(g.adaptOpts,'arg_direct')
    g.adaptOpts = rmfield(g.adaptOpts,'arg_direct');
end

% adapt limits using exponential window moving average
[state.lastMin state.lastMax] = hlp_scaleLimits(g.values,state.lastMin, ...
                                state.lastMax,state.numRunsSoFar,g.adaptOpts);
state.numRunsSoFar = state.numRunsSoFar + 1;

limits = [state.lastMin, state.lastMax];


function [AUC_FV,AUC_ges,AUC_GT,AUC_trans]=finalexp(method)
%This script run different methods on different sets of features to fill the final table
% method may be 'NN'(network),'tree','randforest','bayes','log','boost', 'linearsvm','kernelsvm'
%csv_path = '../Annotation/saved_anno.mat';
%load(csv_path);

disp(['Classifier is ', method])
% read CV
fea_path = '../dataset_trial/FVs';
fea_types = {'mbhx','mbhy'};

% Load all FV features
if ~exist('feaMap.mat')
    feaMap = containers.Map;
    for fea_i = 1:length(fea_types)
        fea_ext = [fea_types{fea_i},'.fv.txt'];
        fea_list = dir([fea_path,'/*',fea_ext]);
        for vid_i = 1:length(fea_list)
            tmpfea = importdata(fullfile(fea_path,fea_list(vid_i).name));
            feaMap(fea_list(vid_i).name) = tmpfea;
        end
    end
    save('feaMap.mat','feaMap');
else
    load('feaMap.mat');
end

prob_lf = cell(1, 10);
prob_FV = cell(1, 10);  %Fisher Vector
prob_ges = cell(1,10);  %pred gesture
prob_GT = cell(1, 10);  %GT gesture
prob_MFCC = cell(1,10); %MFCC feature
prob_trans = cell(1,10);    %Transcript feature
lab_vec = cell(1, 10);  %label vector
AUC_gt = zeros(1,10);

%fine grid search on gesture features on different weights (0 0.5 1)
for cv = 0:9
    disp(['CROSS VALIDATION:', num2str(cv)])
    if ~exist(sprintf(['grid_search/final%d_',method,'.mat'],cv+1),'file')
        disp('IDTFV');
        tmpprob_FV = test_dtfv_CV(cv, feaMap, method);  %IDT+FV
        disp('Pred');
        [tmplab,tmpprob, w] = test_gestureSearch(cv, method); %Pred Gesture
        disp('GT')
        tmpprob_GT = test_GTgestureSearch(cv, method);  %GT Gesture, currently use 5 GT
        disp('trans');
        tmpprob_trans = test_Trans(cv, method);
        save(sprintf(['grid_search/final%d_',method,'.mat'],cv+1), 'tmpprob_FV','tmplab','tmpprob','tmpprob_GT','tmpprob_trans');
        fprintf('Save search results.\n');
    else
        disp(['Load from ',sprintf(['grid_search/final%d_',method,'.mat'],cv+1)]);
        load(sprintf(['grid_search/final%d_',method,'.mat'],cv+1));
    end
%     [tmplab,tmpprob, w] = test_gestureSearch(cv, method); %Pred Gesture
    lab_vec{cv+1} = tmplab;
    prob_ges{cv+1} = tmpprob;
    prob_FV{cv+1} = tmpprob_FV;
    prob_GT{cv+1} = tmpprob_GT;
    prob_trans{cv+1} = tmpprob_trans;
    if ~exist(sprintf(['grid_search/MFCC%d_',method,'.mat'],cv+1),'file')
        disp('MFCC');
        tmpprob_MFCC = test_MFCC(cv, method);
        save(sprintf(['grid_search/MFCC%d_',method,'.mat'],cv+1), 'tmpprob_MFCC');
        fprintf('Save MFCC.\n');
    else
        disp(['Load from ',sprintf(['grid_search/MFCC%d_',method,'.mat'],cv+1)]);
        load(sprintf(['grid_search/MFCC%d_',method,'.mat'],cv+1));
    end
    prob_MFCC{cv+1} = tmpprob_MFCC;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%55
% Compute individual feature AUC
for cv = 0:9
    validID = ~isnan(prob_ges{cv+1}{length(prob_ges{1})});
    % IDTFV only
    [~,~,~,AUC_FV(cv+1)] = perfcurve(lab_vec{cv+1}(validID),prob_FV{cv+1}(validID),0);
    % Gesture only
    for comb_i = 1: length(prob_ges{1})
        [~,~,~,AUC_ges(cv+1, comb_i)] = perfcurve(lab_vec{cv+1}(validID),prob_ges{cv+1}{comb_i}(validID),0);
        [~,~,~,AUC_GT(cv+1, comb_i)] = perfcurve(lab_vec{cv+1}(validID),prob_GT{cv+1}{comb_i}(validID),0);
    end
    % Trans only
    [~,~,~,AUC_trans(cv+1)] = perfcurve(lab_vec{cv+1}(validID),prob_trans{cv+1}(validID),0);
    % MFCC only
    [~,~,~,AUC_MFCC(cv+1)] = perfcurve(lab_vec{cv+1}(validID),prob_MFCC{cv+1}(validID),0);

end

fprintf('IDTFV only: %f.\n', mean(AUC_FV));
fprintf('Pred Gesture only: %f.\n', max(mean(AUC_ges,1)));
fprintf('GT Gesture only: %f.\n', max(mean(AUC_GT,1)));
fprintf('Trans only: %f.\n', mean(AUC_trans));
fprintf('MFCC only: %f.\n', mean(AUC_MFCC));

tmpAUC = mean(AUC_ges,1); comb_maxi = find(tmpAUC==max(tmpAUC)); comb_maxi = comb_maxi(1); %for gesture and GT
tmpAUC = mean(AUC_GT,1); comb_maxi_GT = find(tmpAUC==max(tmpAUC)); comb_maxi_GT = comb_maxi_GT(1);

% Do a grid search to find best weights for ges_id
combs = unique(combnk([0 0 0 0 0 .5 .5 .5 .5 .5 1 1 1 1 1], 5), 'rows');
comb_i = 1;
for i = 1:size(combs,1)
    perW = unique(perms(combs(i,:)), 'rows');
    for j = 1:size(perW, 1)
        %tmpw = repmat(perW(j,:), num_C, 1);
        w{comb_i} = perW(j,:);
        comb_i = comb_i +1;
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Find best ratio for idt and Gesture
disp('---------------------------------------------------------------------------------')
disp('IDT+ Gesture...............')
for comb_i = 1: length(prob_ges{1})
    for r  = 1:11
        ratio = -0.1+ 0.1*r;
        AUC = zeros(1, 10);
        AUC_GT = zeros(1, 10);
        for cv = 0:9
            % pred late fusion
            prob_lf= ratio*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_i})) +(1-ratio)* prob_ges{cv+1}{comb_i}(~isnan(prob_ges{cv+1}{comb_i}));
            % GT late fusion
            if ~isinf(prob_GT{cv+1}{comb_i}(~isnan(prob_ges{cv+1}{comb_i})))
            %prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_i}))
            %prob_GT{cv+1}{comb_i}(~isnan(prob_ges{cv+1}{comb_i}))
                prob_lf_GT = ratio*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_i})) +(1-ratio)* prob_GT{cv+1}{comb_i}(~isnan(prob_ges{cv+1}{comb_i}));
            else
                prob_lf_GT = ratio*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_i}));
            end
            [~,~,~,AUC(cv+1)] = perfcurve(lab_vec{cv+1}(~isnan(prob_ges{cv+1}{comb_i})),prob_lf,0);
            [~,~,~,AUC_GT(cv+1)] = perfcurve(lab_vec{cv+1}(~isnan(prob_ges{cv+1}{comb_i})),prob_lf_GT,0);
        end
        AUC_r(comb_i, r) = mean(AUC);
        AUC_r_GT(comb_i,r) = mean(AUC_GT);
    end
end
% find best ratio and gesture weights value, only select one if more than one are applicable
[comb_s, r_s] = find(AUC_r == max(AUC_r(:)));
[comb_s_GT, r_s_GT] = find(AUC_r_GT == max(AUC_r_GT(:)));
combs = unique(combnk([0 0 0 0 0 .5 .5 .5 .5 .5 1 1 1 1 1], 5), 'rows');
comb_i = 1;
for i = 1:size(combs,1)
    perW = unique(perms(combs(i,:)), 'rows');
    for j = 1:size(perW, 1)
        %tmpw = repmat(perW(j,:), num_C, 1);
        w{comb_i} = perW(j,:);
        comb_i = comb_i +1;
    end
end
comb_s = comb_s(1);
r_s = r_s(1);
comb_s_GT = comb_s_GT(1);
r_s_GT = r_s_GT(1);
fprintf('IDTFV+Pred: %f.\n', max(AUC_r(:)));

ratio1 = -0.1+0.1*r_s; % ratio for idt and gesture
ratio1_GT = -0.1+0.1*r_s_GT; % ratio for idt and GT gesture

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Also consider MFCC feature
disp('---------------------------------------------------------------------------------')
disp('With MFCC Feature......................')
for r = 1:11
    ratio2 = -0.1+0.1*r;
    AUC = zeros(1, 10);
    AUC_GT = zeros(1,10);
    for cv  = 0:9
        % pred+idt probs and GT+idt probs
        prob_lf0 = ratio1*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_s})) +(1-ratio1)* prob_ges{cv+1}{comb_s}(~isnan(prob_ges{cv+1}{comb_s}));
        prob_lf0_GT = ratio1_GT*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT})) +(1-ratio1_GT)* prob_GT{cv+1}{comb_s_GT}(~isnan(prob_ges{cv+1}{comb_s_GT}));
        % compute fusion
        prob_lf= ratio2*prob_lf0 + (1-ratio2)*prob_MFCC{cv+1}(~isnan(prob_ges{cv+1}{comb_s}));
        [~,~,~,AUC(cv+1)] = perfcurve(lab_vec{cv+1}(~isnan(prob_ges{cv+1}{comb_s})),prob_lf,0);
        prob_lf_GT= ratio2*prob_lf0_GT + (1-ratio2)*prob_MFCC{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT}));
        [~,~,~,AUC_GT(cv+1)] = perfcurve(lab_vec{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT})),prob_lf_GT,0);
    end
    AUC_lf(r) = mean(AUC(~isnan(AUC)));
    AUC_lf_GT(r) = mean(AUC_GT(~isnan(AUC_GT)));
end

fprintf('IDTFV+Pred+MFCC: %f.\n', max(AUC_lf(:)));
fprintf('IDTFV+GT+MFCC: %f.\n', max(AUC_lf_GT(:)));

r_s = find(AUC_lf == max(AUC_lf));
r_s_GT = find(AUC_lf_GT == max(AUC_lf_GT));
r_s_GT = r_s_GT(1);
r_s = r_s(1);

ratio_M = -0.1+0.1*r_s; % ratio for idt+ges and MFCC
ratio_M_GT = -0.1+0.1*r_s_GT; % ratio for idt+GT and MFCC

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Also consider Trans feature
disp('---------------------------------------------------------------------------------')
disp('With Trans Feature......................')
for r = 1:11
    ratio2 = -0.1+0.1*r;
    AUC = zeros(1, 10);
    AUC_GT = zeros(1,10);
    for cv  = 0:9
        % pred+idt probs and GT+idt probs
        prob_lf0 = ratio1*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_s})) +(1-ratio1)* prob_ges{cv+1}{comb_s}(~isnan(prob_ges{cv+1}{comb_s}));
        prob_lf0_GT = ratio1_GT*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT})) +(1-ratio1_GT)* prob_GT{cv+1}{comb_s_GT}(~isnan(prob_ges{cv+1}{comb_s_GT}));
        % compute fusion
        prob_lf= ratio2*prob_lf0 + (1-ratio2)*prob_trans{cv+1}(~isnan(prob_ges{cv+1}{comb_s}));
        [~,~,~,AUC(cv+1)] = perfcurve(lab_vec{cv+1}(~isnan(prob_ges{cv+1}{comb_s})),prob_lf,0);
        prob_lf_GT= ratio2*prob_lf0_GT + (1-ratio2)*prob_trans{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT}));
        [~,~,~,AUC_GT(cv+1)] = perfcurve(lab_vec{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT})),prob_lf_GT,0);
    end
    AUC_lf(r) = mean(AUC(~isnan(AUC)));
    AUC_lf_GT(r) = mean(AUC_GT(~isnan(AUC_GT)));
end

fprintf('IDTFV+Pred+trans: %f.\n', max(AUC_lf(:)));
fprintf('IDTFV+GT+trans: %f.\n', max(AUC_lf_GT(:)));

r_s = find(AUC_lf == max(AUC_lf));
r_s_GT = find(AUC_lf_GT == max(AUC_lf_GT));
r_s_GT = r_s_GT(1);
r_s = r_s(1);

ratio_T = -0.1+0.1*r_s; % ratio for idt+ges and MFCC
ratio_T_GT = -0.1+0.1*r_s_GT; % ratio for idt+GT and MFCC

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% All features
disp('---------------------------------------------------------------------------------')
disp('With All Features...................')
for r = 1:11
    ratio2 = -0.1+0.1*r;
    AUC = zeros(1, 10);
    AUC_GT = zeros(1,10);
    for cv  = 0:9
        % pred gesture with
        prob_lf0 = ratio1*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_s})) +(1-ratio1)* prob_ges{cv+1}{comb_s}(~isnan(prob_ges{cv+1}{comb_s}));
        % GT gesture with trans
        prob_lf0_GT = ratio1_GT*prob_FV{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT})) +(1-ratio1_GT)* prob_GT{cv+1}{comb_s_GT}(~isnan(prob_ges{cv+1}{comb_s_GT}));
        % compute fusion with MFCC
        prob_M0 = ratio_M*prob_lf0 + (1-ratio_M)*prob_MFCC{cv+1}(~isnan(prob_ges{cv+1}{comb_s}));
        prob_M0_GT = ratio_M_GT*prob_lf0_GT + (1-ratio_M_GT)*prob_MFCC{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT}));
        % compute fusion with Trans
        prob_T= ratio2*prob_M0 + (1-ratio2)*prob_trans{cv+1}(~isnan(prob_ges{cv+1}{comb_s}));
        [~,~,~,AUC(cv+1)] = perfcurve(lab_vec{cv+1}(~isnan(prob_ges{cv+1}{comb_s})),prob_T,0);
        prob_T_GT= ratio2*prob_M0_GT + (1-ratio2)*prob_trans{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT}));
        [~,~,~,AUC_GT(cv+1)] = perfcurve(lab_vec{cv+1}(~isnan(prob_ges{cv+1}{comb_s_GT})),prob_T_GT,0);
    end
    AUC_final(r) = mean(AUC(~isnan(AUC)));
    AUC_final_GT(r) = mean(AUC_GT(~isnan(AUC_GT)));
end

fprintf('IDTFV+Pred+MFCC+Trans: %f.\n', max(AUC_final(:)));
fprintf('IDTFV+GT+MFCC+Trans: %f.\n', max(AUC_final_GT(:)));

r_f = find(AUC_final == max(AUC_final));
r_f_GT = find(AUC_final_GT == max(AUC_final_GT));
r_f_GT = r_f_GT(1);
r_f = r_f(1);

ratio_All = -0.1+0.1*r_f; % ratio for idt+ges and MFCC
ratio_All_GT = -0.1+0.1*r_f_GT; % ratio for idt+GT and MFCC


%PROCM Fixed-cell mapping to execute arbitray Matlab function on objects
%      Low-level routine
%
%    [OUT1,OUT2, ..] = A*PROCM(COMMAND,PAR1,PAR2,....)
%    [OUT1,OUT2, ..] = {A,B}*PROCM(COMMAND,PAR1,PAR2,....)
%
% INPUT
%    A               Dataset, datafile, cell array or double
%    B               Dataset, datafile, cell array or double
%    COMMAND         String with function name or PRTools nmapping
%    PAR1,...        Optional parameters for COMMAND
%
% OUTPUT
%    OUT1, ...       Cell arrays with results from COMMAND
%
% DESCRIPTION
% This routine executes a given COMMAND over a set of objects. These can
% be supplied by a dataset, a datafile, a cell array or a double array.
% Rows are interpreted as objects. For each object N stored in A the
% routine COMMAND is processed by
%
%    [OUT1{N}, ...] = COMMAND(OBJECT_N,PAR1,PAR2,....)
%
% For diadic operations the two inputs should be combined in a cell: {A,B}.
% They are processed by
%
%    [OUT1{N}, ...] = COMMAND(OBJECT_A_N,OBJECT_B_N,PAR1,PAR2,....)
%
% This is a low-level routine that feeds the unpacked objects in datafiles
% and dataset (doubles) to COMMAND. Use FILTM for a higher level of
% processing. Use MAPM to handle entire matrices, datasets or datafiles
% instead of processing object by object.
%
% SEE ALSO (PRTools Guide)
% DATASETS, DATAFILES, IM2OBJ, FEAT2OBJ, DATA2IM, FILTM, FILTM, MAPM

% Copyright: R.P.W. Duin, r.p.w.duin@37steps.com

function varargout = procm(varargin)

  if nargin == 0
    error('No command found')
  end
  varargin = shiftargin(varargin,'char');
  if isempty(varargin{1})
    w = prmapping(mfilename,'fixed_cell',varargin(2:end));
    varargout{1} = setname(w,'DataProc');
    return
  end

  % now we have: procm(data,command,pars)
  % data might be dataset, datafile, cell array, double, structure array

  nout = max(1,nargout);
  varargout = cell(1,nout); % output list
  argout = cell(1,nout);    % temp cell array for output per object
  pars = cell(1,nargin-2);     % input pars
  [a,command,pars{:}] = deal(varargin{:}); % use nice names
%   if numel(pars) > 1 % allow argument list as cell array or not.
%    pars = {pars}
%   end
  if iscell(a) && all(size(a)==[1,2])      % diadic operation
    [a,b] = deal(a{:});
    diadic = true;
  else
    diadic = false;
  end
  m = size(a,1);
  for j=1:nout              % output space
    varargout{j} = cell(m,1);
  end
  t = sprintf(['Processing %i objects by ' command ': '],m);
  prwaitbar(m,t)
  for i=1:m                   % loop over objects
    prwaitbar(m,i,[t num2str(i)]);
    if diadic                 % call command
      [argout{:}] = feval(command,g(a,i),g(b,i),pars{:});
    else
      x = g(a,i);
      [argout{:}] = feval(command,g(a,i),pars{:});
    end
    for j=1:nout           % store results
      varargout{j}{i} = argout{j};
    end
  end
  prwaitbar(0);

return

function x = g(a,i)
  if iscell(a)              % get cell data
    x =a{i};
  elseif isa(a,'prdataset') % datasets and datafiles
    x = +a(i,:);            % get their data
  else                      % all other datatypes
    x = a(i,:);
  end
return


function varargout = singleSignTest(varargin)
%SINGLESIGNTEST   Heuristic check to see if a DISKFUN changes sign.
%   SINGLESIGNTEST(F) returns 1 if the values of F on a tensor grid are of
%   the same sign.
%
%   [OUT, WZERO] = SINGLESIGNTEST( F ), returns WZERO = 1 if a zero has
%   been found.
%
%   The algorithm works by sampling F on a tensor-grid and checking if
%   those values are of the same sign. This command is mainly for internal
%   use in DISKFUN commands.
%
% See also DISKFUN/ABS, DISKFUN/SQRT, and DISKFUN/LOG.

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

[varargout{1:nargout}] = singleSignTest@separableApprox(varargin{:});

end


function autoShowSyn1(varargin)
% This function is used to provde synthetic data for a certain date (mm/dd/yyyy).
% two digits for QA band
%
% Specific parameters
% ------------------------
%   'InDir'     Directory of CCDC change detection results.
%                        Default is the path to current folder.
%   'OutDir'    Directory of the model output.  Default is the
%                        same as InputDirectory.
%   'Year'               Year.
%   'Month'              Month.
%   'Day'                Day.
%   'DOY'                Day of year.

% Examples:
% ------------------------
% autoShowSyn1('Year',2010,'Month',7,'Day',1)
% will give the synthetic data at July 1,2010.
%
% autoShowSyn1('Year',2010,'DOY',200)
% will give the synthetic data at 200th day,2010.
%

 %% get parameters from inputs
% where the all CCDC change detection results are
dir_cur = pwd;
% where the output files are
dir_out = '';
p = inputParser;
p.FunctionName = 'paras';

addParameter(p,'InDir',dir_cur);
addParameter(p,'OutDir',dir_out);
addParameter(p,'Year',0);
addParameter(p,'Month',0);
addParameter(p,'Day',0);
addParameter(p,'DOY',0);

parse(p,varargin{:});
dir_cur = p.Results.InDir;
dir_out = p.Results.OutDir;

yy=p.Results.Year;
mm=p.Results.Month;
dd=p.Results.Day;
doy=p.Results.DOY;
if isempty(dir_out)
    dir_out = dir_cur;
end

if yy>0
    if mm>0&&dd>0 % using yyyy/mm/dd
        % converted to julian date
        j_date=datenum(yy,mm,dd);
        j0_date=datenum(yy,1,0);
        doy = j_date-j0_date;
        % date for show i.e. 19990815
        %s_date=yy*10000+mm*100+dd;
        s_date = yy*1000 + doy;
    elseif doy>0 % using yyyy DOY
        j_date = datenum(yy,1,0) + doy;
        s_date = yy*1000 + doy;
    end
end
% v_input = ccdc_Input(dir_cur);

% 1. inputs: the time for predicted synthetic data
% yy=2000;
% mm=12;
% dd = 1;
% OR
% yy=2000;
% doy=120;

% nbands = v_input.nbands - 1;% number of bands in the image
% ncoefs = v_input.num_c;% number of coefficients
%
% % dimension and projection of the image
% % cd(v_input.l_dir);
% nrows = v_input.ijdim(1);
% ncols = v_input.ijdim(2);
% jiDim = [ncols,nrows];
% jiUL = v_input.jiul;
% res = v_input.resolu;
% zc = v_input.zc;

% get num of total folders start with "L"
imf=dir(fullfile(dir_cur,'L*')); % folder names
% filter for Landsat folders
imf = regexpi({imf.name}, 'L(T5|T4|E7|C8|ND)(\w*)', 'match');
imf = [imf{:}];
imf = vertcat(imf{:});
% sort according to yeardoy
yeardoy = str2num(imf(:, 10:16));
[~, sort_order] = sort(yeardoy);
imf = imf(sort_order, :);
% name of the first stacked image
filename = dir(fullfile(dir_cur,imf(1,:),'L*MTLstack'));
% read in dimension and zone number of the data
[jiDim,jiul,resolu,zc] = envihdrread(fullfile(dir_cur,imf(1,:),filename.name));

n_syn = ['LS',imf(1,4:9),num2str(s_date)];

nbands = 8; %original band amounts
nbands = nbands - 1; % show change for all the bands except fmask

ncoefs = 8; %max num of coefficients
nrows = jiDim(2);
ncols = jiDim(1);

% produce synthetic data (1, 2, 3, 4, 5, 7, and QA)
SR = -9999*ones(nrows,ncols,nbands,'int16'); % 1. change here for excluding thermal

% make Predict folder for storing predict images
%n_pre = v_input.name_pre;%'PredictAll';
n_pre = 'PredictAll';

if isempty(dir(fullfile(dir_cur,n_pre)))
    mkdir(fullfile(dir_cur,n_pre));
end

% folder saved everything
%n_rst = v_input.name_rst;
n_rst = 'TSFitMap';
%cd(n_rst);% TSFitMap

imf=dir(fullfile(dir_cur,n_rst,'record_change*')); % folder names
num_line = size(imf,1);

%%
for line = 1:num_line
    %fprintf('Processing %.2f percent\r',100*(line/num_line));
    load(fullfile(dir_cur,n_rst,imf(line).name));

    % postions & coefficients
    pos = [rec_cg.pos];
    % continue if there is no model available
    l_pos = length(pos);
    if l_pos == 0
        continue;
    end
    % get coefficients matrix
    coefs = [rec_cg.coefs];
    % reshape coefs
    coefs = reshape(coefs,nbands*ncoefs,l_pos);
    % get category matrix
    category = [rec_cg.category];
    % take the first digit (number of coefficients)
    category = category - 10*floor(category/10);

    % model start, end, & break time for prediction
    model_start = [rec_cg.t_start];
    model_end = [rec_cg.t_end];
    model_break = [rec_cg.t_break];
    % model on the right
    ids_right = model_start > j_date;
    % model on the left
    ids_left = (model_end < j_date & model_break == 0)|(model_break <= j_date & model_break > 0);
    % id within model interval
    ids_middle = model_start <= j_date & ((model_end >= j_date & model_break == 0) | (model_break > j_date & model_break > 0));

    % position for model in the middle
    pos_middle = pos(ids_middle);
    % coefficients for model in the middle
    coefs_middle = coefs(:,ids_middle);
    % category for model in the middle
    category_middle = category(ids_middle);

    % positions for the nearest model on the right
    pos_right = pos(ids_right);
    [pos_near_right,ids_near_right] = unique(pos_right,'first');
    % coefficients for the nearest model on the right
    coefs_right = coefs(:,ids_right);
    coefs_near_right = coefs_right(:,ids_near_right);
    % category for the nearest model on the right
    category_right = category(ids_right);
    category_near_right = category_right(ids_near_right);

    % postions for the nearest model on the left
    pos_left = pos(ids_left);
    [pos_near_left,ids_near_left] = unique(pos_left,'last');
    % coefficients for the nearest model on the left
    coefs_left = coefs(:,ids_left);
    coefs_near_left = coefs_left(:,ids_near_left);
    % category for the nearest model on the left
    category_left = category(ids_left);
    category_near_left = category_left(ids_near_left);

    % pass if there is no nearest model on the left
    l_pos=length(pos_near_left);
    if l_pos > 0
        % providing predictions
        for i=1:l_pos
            [I,J]=ind2sub(jiDim,pos_near_left(i));
            for j_b=1:nbands-1 % excluding thermal band
                SR(J,I,j_b)=autoTSPred(j_date,coefs_near_left(((j_b-1)*ncoefs+1):j_b*ncoefs,i));
            end
            % QA band
            SR(J,I,end) = 20 + category_near_left(i); % model forward predicted values
        end
    end

    % pass if there is no nearest model on the right
    l_pos=length(pos_near_right);
    if l_pos > 0
        % providing predictions
        for i=1:l_pos
            [I,J]=ind2sub(jiDim,pos_near_right(i));
            for j_b=1:nbands-1 % excluding thermal band
                SR(J,I,j_b)=autoTSPred(j_date,coefs_near_right(((j_b-1)*ncoefs+1):j_b*ncoefs,i));
            end
            % QA band
            SR(J,I,end) = 10 + category_near_right(i); % model backward predicted values
        end
    end

    % pass if there is no nearest model in the middle
    l_pos=length(pos_middle);
    if l_pos > 0
        % providing estimations
        for i=1:l_pos
            [I,J]=ind2sub(jiDim,pos_middle(i));
            for j_b=1:nbands-1 % excluding thermal band
                SR(J,I,j_b)=autoTSPred(j_date,coefs_middle(((j_b-1)*ncoefs+1):j_b*ncoefs,i));
            end
            % QA band
            SR(J,I,end) = 0 + category_middle(i); % model estimated values
        end
    end
end

n_bands = {'Band 1','Band 2','Band 3','Band 4','Band 5','Band 7','QA'};
% n_bands = 1:7;
% write ENVI files
ARD_enviwrite_bands_n(fullfile(dir_out,n_pre,n_syn),SR,'int16','bip',n_bands,dir_cur,dir_out);
end


function out = iszero(f)
%ISZERO   True for zero SINGFUN objects.
%   ISZERO(F) returns logical TRUE if the smooth part of F is zero and FALSE
%   otherwise.

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

% Check if the smooth part is zero:
out = iszero(f.smoothPart);

end


function  sL = subBoundaryLength(grains,varargin)
% subgrain boundary length per grain
%
% Input
%  grains - @grain2d
%
% Output
%  l - number of boundary segments
%
% Syntax
%   l = grains.subBoundaryLength
%

grainIds = grains.innerBoundary.grainId;

sL = grains.innerBoundary.segLength;

% if varargin is a logical use for selection of relevant innerBoundary
if nargin>1 && islogical(varargin{1})
    grainIds = grainIds(varargin{1},:);
    sL = sL(varargin{1});
end

ind = (diff(grainIds,1,2)~=0);
grainIds(ind,:) = [];
sL(ind,:) = [];

sL = accumarray(grainIds(:,1),sL,[max(grains.id) 1]);

% convert from id to ind
sL = sL(grains.id);


function [ rtn ] = TESTZERODAY( denum, testCase )
%TEST test the known zero-day values from JPL's ephemerides
  output = 1;
  rtn = 0;

  if nargin < 1
    denum = 405;
  end
  if isnumeric(denum)
    denum = sprintf('%d',denum);
  end
  if nargin < 2
    testCase = -1;
  end
  [ st, error ] = Ephem.readHeader( denum );
  if error == 0 && isfield(st,'JDEPOC') % contains zero data
    year = floor(st.JDEPOC/365.2425 - 4712.019); % possibly off by +1 year at New Years Day
    s = Ephem(denum);
    s.output = output;
    s.KM = 0;
    pos_err = 5.0e-8;
    vel_err = 7.0e-6;
    for i=1:2
      if i == 1
        fprintf(output,'Testing ascii ephemeris DE%s zero day\n',denum);
        fn = Ephem.asc_name(denum,year);
        [s,error] = s.openDEasc(denum, fn);
      elseif i == 2
        fprintf(output,'Testing binary ephemeris DE%s zero day\n',denum);
        fn = Ephem.eph_name(denum,year);
        [s,error] = s.openDEeph(denum, fn);
      end
      if error
        %if nargin > 1
        %  testCase.verifyEqual(error,0,'bad openDE');
        %end
        break;
      end
      target = Ephem.Mercury;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'X1')
        check(st,'1',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Venus;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'X2')
        check(st,'2',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Earth;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'XB')
        check(st,'B',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Mars;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'X4')
        check(st,'4',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Jupiter;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'X5')
        check(st,'5',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Saturn;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'X6')
        check(st,'6',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Uranus;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'X7')
        check(st,'7',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Neptune;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'X8')
        check(st,'8',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Pluto;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'X9')
        check(st,'9',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      target = Ephem.Moon;
      [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
      if ~error && isfield(st,'XM')
        check(st,'M',target_pos,target_vel,pos_err,vel_err,testCase);
      end
      if isfield(st,'XS') && st.XS ~= 0 && st.YS ~= 0 && st.ZS ~= 0 % has Sun data
        target = Ephem.Sun;
        [ target_pos, target_vel,~, error ] = s.state( st.JDEPOC, target );
        check(st,'S',target_pos,target_vel,pos_err,vel_err,testCase);
      end
    end
  end
end
function rtn = check(st,n,pos,vel,pos_err,vel_err,testCase)
  rtn = true;
  output = 1;
  real_pos = [st.(sprintf('X%s',n)),st.(sprintf('Y%s',n)),st.(sprintf('Z%s',n))];
  real_vel = [st.(sprintf('XD%s',n)),st.(sprintf('YD%s',n)),st.(sprintf('ZD%s',n))];
  diff = (pos(1) - real_pos(1))/real_pos(1);
  if abs(diff) >= pos_err
    str = sprintf('X%c %g ~= %g (%g)\n',n,pos(1),real_pos(1),diff);
    if nargin > 6 && testCase ~= -1
      testCase.verifyEqual(pos(1),real_pos(1),'RelTol',pos_err,str);
    else
      fprintf(output,str);
    end
    rtn = false;
  end
  diff = (pos(2) - real_pos(2))/real_pos(2);
  if abs(diff) >= pos_err
    str = sprintf('Y%c %g ~= %g (%g)\n',n,pos(2),real_pos(2),diff);
    if nargin > 6 && testCase ~= -1
      testCase.verifyLessThan(abs(diff),pos_err,str);
    else
      fprintf(output,str);
    end
    rtn = false;
  end
  diff = (pos(3) - real_pos(3))/real_pos(3);
  if abs(diff) >= pos_err
    str = sprintf('Z%c %g ~= %g (%g)\n',n,pos(3),real_pos(3),diff);
    if nargin > 6 && testCase ~= -1
      testCase.verifyLessThan(abs(diff),pos_err,str);
    else
      fprintf(output,str);
    end
    rtn = false;
  end
  diff = (vel(1) - real_vel(1))/real_vel(1);
  if abs(diff) >= vel_err
    str = sprintf('XD%c %g ~= %g (%g)\n',n,vel(1),real_vel(1),diff);
    if nargin > 6 && testCase ~= -1
      testCase.verifyLessThan(abs(diff),vel_err,str);
    else
      fprintf(output,str);
    end
    rtn = false;
  end
  diff = (vel(2) - real_vel(2))/real_vel(2);
  if abs(diff) >= vel_err
    str = sprintf('YD%c %g ~= %g (%g)\n',n,vel(2),real_vel(2),diff);
    if nargin > 6 && testCase ~= -1
      testCase.verifyLessThan(abs(diff),vel_err,str);
    else
      fprintf(output,str);
    end
    rtn = false;
  end
  diff = (vel(3) - real_vel(3))/real_vel(3);
  if abs(diff) >= vel_err
    str = sprintf('ZD%c %g ~= %g (%g)\n',n,vel(3),real_vel(3),diff);
    if nargin > 6 && testCase ~= -1
      testCase.verifyLessThan(abs(diff),vel_err,str);
    else
      fprintf(output,str);
    end
    rtn = false;
  end
end


function [output, validFrameMask] = F_hadamard(input_layers)
input = input_layers{1}.a;
input2 = input_layers{2}.a;

output = input .* input2;

[D,M,N] = size(input);
if N==1
    validFrameMask = [];
else
    validFrameMask = getValidFrameMask(input_layers{1});
end

end


%%********************************************************
%% qops:  Fu = qops(pblk,w,f,options,u);
%%
%% options = 1, Fu(i) = <wi,fi>
%%         = 2, Fu(i) = 2*wi(1)*fi(1)-<wi,fi>
%%         = 3, Fui   = w(i)*fi
%%         = 4, Fui   = w(i)*fi, Fui(1) = -Fui(1).
%% options = 5, Fu = w [ f'*u ; ub + fb*alp ], where
%%              alp = (f'*u + u0)/(1+f0);
%% options = 6, compute Finv*u.
%%
%% Note F = w [f0  fb'; fb  I+ fb*fb'/(1+f0) ], where
%%      f0*f0 - fb*fb' = 1.
%%      Finv = (1/w) [f0  -fb'; -fb  I+ fb*fb'/(1+f0) ].
%%
%% SDPT3: version 3.1
%% Copyright (c) 1997 by
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
%% Last Modified: 16 Sep 2004
%%********************************************************

function  Fu = qops(pblk,w,f,options,u)

if (options >= 1 && options <= 4)
    Fu = mexqops(pblk{2},w,f,options);
elseif (options == 5)
    s = 1 + [0 cumsum(pblk{2})];
    idx1 = s(1:length(pblk{2}));
    inprod = mexqops(pblk{2},f,u,1);
    tmp = (u(idx1)+inprod)./(1+f(idx1));
    Fu  = u + mexqops(pblk{2},tmp,f,3);
    Fu(idx1) = inprod;
    Fu = mexqops(pblk{2},w,Fu,3);
elseif (options == 6)
    s = 1 + [0 cumsum(pblk{2})];
    idx1 = s(1:length(pblk{2}));
    gamprod = mexqops(pblk{2},f,u,2);
    tmp = (u(idx1)+gamprod)./(1+f(idx1));
    Fu  = u - mexqops(pblk{2},tmp,f,3);
    Fu(idx1) = gamprod;
    Fu = mexqops(pblk{2},1./w,Fu,3);
end
%%********************************************************


%% housekeeping
clear
close all
clc

%% rise the model
m=rise('lwz_model','solve_linear',true);

%% get the parameters

[p,priors]=create_parameters(true);

m=set(m,'parameters',p);

%% bring in the data

data=create_data();

%% estimate the model

ms=estimate(m,'data',data,...
    'estim_priors',priors,...
    'kf_presample',3,...
    'kf_init_variance',10);

% 'optimizer','bee_gate','optimset',struct('MaxTime',30*60)


function [modelMin,AddedExchange] = findMinCardModel(model,Ex_Rxns)
% Function to find the minimal cardinality model.
%
% USAGE:
%    [modelMin, AddedExchange] = findMinCardModel(model, Ex_Rxns)
%
% INPUTS:
%     model:         Metabolic model
%     Ex_Rxns:       Vector of exchange reactions for FVA
%
% OUTPUTS:
%    modelMin:       Updated model with new reaction bounds
%    AddedExchange:  Vector of exchanged reactions
%
% .. Authors:
%       - Ines Thiele 2014
%       - Maike K. Aurich 27/05/15 change tolerance

tol = -1e-6;  % Default tolerance (limit for calling flux 0)

AddedExchange = '';
% convert to irrev model
[modelIrrev,matchRev,rev2irrev,irrev2rev] = convertToIrreversible(model);
%translate Ex_Rxns from rev model to irrev model
Ex_RxnsIrrev=[];
for w=1:length(Ex_Rxns)
    tmp = modelIrrev.rxns(strmatch(Ex_Rxns(w),modelIrrev.rxns));
    Ex_RxnsIrrev = [Ex_RxnsIrrev; tmp];
end

minNorm = zeros(length(modelIrrev.rxns),1);
minNorm(ismember(modelIrrev.rxns,Ex_RxnsIrrev))= 1;

modelIrrev.osense=1; %minimize linear objective

[solutionCard2]=solveCobraLPCPLEXcard(modelIrrev,0,0,[],[],minNorm,'zero');

% needs backward translation from irrev to rev
% update constraints in original model according to solution
RxnID = find(ismember(modelIrrev.rxns,Ex_RxnsIrrev));
unUsedRxns = find(solutionCard2.full<=abs(tol));
usedRxns = find(solutionCard2.full>abs(tol));
UnusedRxnID = intersect(unUsedRxns,RxnID);
UsedRxnID = intersect(usedRxns,RxnID);
modelMin = model;
for i = 1 :length(UnusedRxnID)
    if strcmp(modelIrrev.rxns{UnusedRxnID(i)}(end-1:end),'_r')
        OriModelName = modelIrrev.rxns{UnusedRxnID(i)}(1:end-2);
        modelMin = changeRxnBounds(modelMin,OriModelName,0,'b');
    elseif strcmp(modelIrrev.rxns{UnusedRxnID(i)}(end-1:end),'_b') % no uptake
        OriModelName = modelIrrev.rxns{UnusedRxnID(i)}(1:end-2);
        modelMin = changeRxnBounds(modelMin,OriModelName,0,'l');
    elseif strcmp(modelIrrev.rxns{UnusedRxnID(i)}(end-1:end),'_f') % no secretion
        OriModelName = modelIrrev.rxns{UnusedRxnID(i)}(1:end-2);
        modelMin = changeRxnBounds(modelMin,OriModelName,0,'u');
    else
        OriModelName = modelIrrev.rxns{UnusedRxnID(i)};
        modelMin = changeRxnBounds(modelMin,OriModelName,0,'b');
    end
end
cntR=1;
for i = 1 :length(UsedRxnID)
    if strcmp(modelIrrev.rxns{UsedRxnID(i)}(end-1:end),'_r')
        AddedExchange{cntR,1} = strcat(modelIrrev.rxns{UsedRxnID(i)}(1:end-2));
        cntR = cntR+1;
    elseif strcmp(modelIrrev.rxns{UsedRxnID(i)}(end-1:end),'_b') %  uptake
        AddedExchange{cntR,1}= strcat(modelIrrev.rxns{UsedRxnID(i)}(1:end-2));

        cntR = cntR+1;
    elseif strcmp(modelIrrev.rxns{UsedRxnID(i)}(end-1:end),'_f') %  uptake
        AddedExchange{cntR,1}= strcat(modelIrrev.rxns{UsedRxnID(i)}(1:end-2));

        cntR = cntR+1;

    else
        AddedExchange{cntR,1} = strcat(modelIrrev.rxns{UsedRxnID(i)});
        cntR = cntR+1;
    end
end


function [f,df] = sqplab_fun(x)

global SQPLABDATA

xevaled = zeros(1,length(SQPLABDATA.interfacedata.c));
xevaled(SQPLABDATA.linearindicies) = x;

% Experimental support for arbitrary functions
if SQPLABDATA.evalinobjective
    if SQPLABDATA.monominobjective
        if ~isempty(SQPLABDATA.bilinears)
            xevaled(SQPLABDATA.bilinears(:,1)) = xevaled(SQPLABDATA.bilinears(:,2)).*xevaled(SQPLABDATA.bilinears(:,3));
        else
            xevaled(SQPLABDATA.nonlinearindicies) = prod(repmat(xevaled,length(SQPLABDATA.nonlinearindicies),1).^SQPLABDATA.monomtable(SQPLABDATA.nonlinearindicies,:),2);
        end
    end
    for i = 1:length(SQPLABDATA.interfacedata.evalMap)
        arguments = SQPLABDATA.evalMap{i}.prearg;
        arguments{2} = xevaled(SQPLABDATA.interfacedata.evalMap{i}.variableIndex);
        xevaled(SQPLABDATA.interfacedata.evalVariables(i)) = feval(arguments{:});
    end
end

if SQPLABDATA.monominobjective
    if ~isempty(SQPLABDATA.bilinears)
        xevaled(SQPLABDATA.bilinears(:,1)) = xevaled(SQPLABDATA.bilinears(:,2)).*xevaled(SQPLABDATA.bilinears(:,3));
    else
        xevaled(SQPLABDATA.nonlinearindicies) = prod(repmat(xevaled,length(SQPLABDATA.nonlinearindicies),1).^SQPLABDATA.monomtable(SQPLABDATA.nonlinearindicies,:),2);
    end
end

xevaled = xevaled(:);
if SQPLABDATA.SimpleLinearObjective
    f = SQPLABDATA.interfacedata.c'*xevaled;
else
    f = (SQPLABDATA.interfacedata.c'+xevaled'*SQPLABDATA.interfacedata.Q)*xevaled;
end

if SQPLABDATA.SimpleLinearObjective
    df = SQPLABDATA.interfacedata.c(SQPLABDATA.linearindicies);
elseif SQPLABDATA.SimpleQuadraticObjective
    df = SQPLABDATA.interfacedata.c(SQPLABDATA.linearindicies) + 2*SQPLABDATA.interfacedata.Q(SQPLABDATA.linearindicies,SQPLABDATA.linearindicies)*x;
elseif SQPLABDATA.SimpleNonlinearObjective
    df = [];
    for i = 1:length(SQPLABDATA.linearindicies)
        xevaled = zeros(1,length(SQPLABDATA.interfacedata.c));
        xevaled(SQPLABDATA.linearindicies) = x;
        mt = SQPLABDATA.monomtable;
        oldpower = mt(:,SQPLABDATA.linearindicies(i));
        mt(:,SQPLABDATA.linearindicies(i)) = mt(:,SQPLABDATA.linearindicies(i))-1;
        xevaled = prod(repmat(xevaled,size(mt,1),1).^mt,2);
        xevaled = xevaled(:)'.*oldpower';xevaled(isnan(xevaled))=0;
        df = [df;SQPLABDATA.interfacedata.c'*xevaled'];
    end
    df = df + 2*SQPLABDATA.interfacedata.Q(SQPLABDATA.linearindicies,SQPLABDATA.linearindicies)*x;
else
    df = [];
end


function displayNeurons(obj, ind, C2, folder_nm)
%% view all components and delete components manually. it overlaps the
%   neuon contours with correlation image and shows the corresponding
%   spatial/temporal components
%% input:
%   ind: vector, indices of components to be displayed, no bigger than the maximum
%       number of neurons
%   C2:  K*T matrix, another temporal component to be displayed together
%       with the esitmated C. usually it is C without deconvolution.
%   folder_nm: string, the folder to output images neuron by neuron.

%% Author: Pengcheng Zhou, Carnegie Mellon University, 2016

if ~exist('ind', 'var') || isempty(ind)
    % display all neurons if ind is not specified.
    ind = 1:size(obj.A, 2);
end
if ~exist('C2', 'var'); C2=[]; end

if exist('folder_nm', 'var')&&(~isempty(folder_nm))
    % create a folder to save resulted images
    save_img = true;
    cur_cd = cd();
    if ~exist(folder_nm, 'dir'); mkdir(folder_nm);
    else
        fprintf('The folder has been created and old results will be overwritten. \n');
    end
    cd(folder_nm);
else
    save_img = false;
end
%% delete neurons with too few pixels
obj.delete(sum(obj.A>0, 1)<max(obj.options.min_pixel, 1));

ind_del = false(size(ind));     % indicator of deleting neurons
ctr = obj.estCenter();       % estimate neurons center
gSiz = obj.options.gSiz;        % maximum size of a neuron
Cn = obj.Cn;                    % correlation image
if isempty(Cn)
    fprintf('Please assign obj.Cn with correlation image!\n');
    return;
end
if isempty(obj.Coor) || (size(obj.A, 2)~=length(obj.Coor))   % contours of the neuron has not been calculated
    figure;
    obj.Coor = obj.get_contours();
end
Coor = obj.Coor;        % contours of all extracted neurons

% time
T = size(obj.C, 2);
t = 1:T;
if ~isnan(obj.Fs)
    t = t/obj.Fs;
    str_xlabel = 'Time (Sec.)';
else
    str_xlabel = 'Frame';
end

% start displaying neurons
figure('position', [100, 100, 1024, 512]);
m = 1;
while and(m>=1, m<=length(ind))
    %% contours + correlation image
    subplot(221); cla;
    obj.image(Cn, [0,1]); hold on; colormap winter;
    axis equal off tight;
    for k=1:m
        % plot contour
        tmp_con = Coor{ind(k)};
        cont_del = (sum(tmp_con<=1, 1)>0);
        tmp_con(:, cont_del) = [];
        if isempty(tmp_con)
            plot(ctr(m, 2), ctr(m, 2));
        else
            if and(k<m, ~ind_del(k))
                plot(tmp_con(1, 1:end), tmp_con(2, 1:end), 'color','k', 'linewidth', 2);
            elseif k==m
                plot(tmp_con(1, 1:end), tmp_con(2, 1:end), 'r', 'linewidth', 3);
            end
        end

        title(sprintf('Neuron %d', ind(m)));
    end

    %% zoomed-in view
    subplot(222);
    imagesc(reshape(obj.A(:, ind(m)), obj.options.d1, obj.options.d2));
    colormap(gca, jet);
    axis equal; axis off;
    x0 = ctr(ind(m), 2);
    y0 = ctr(ind(m), 1);
    xlim(x0+[-gSiz, gSiz]*2);
    ylim(y0+[-gSiz, gSiz]*2);

    %% temporal components
    subplot(2,2,3:4);cla;
    if ~isempty(C2)
        plot(t, C2(ind(m), :)*max(obj.A(:, ind(m))), 'linewidth', 2); hold on;
        plot(t, obj.C(ind(m), :)*max(obj.A(:, ind(m))), 'r');
    else

        plot(t, obj.C(ind(m), :)*max(obj.A(:, ind(m))));
    end
    xlabel(str_xlabel);

    %% save images
    if save_img
        saveas(gcf, sprintf('neuron_%d.png', ind(m)));
        m = m+1;
    else
        fprintf('Neuron %d, keep(k, default)/delete(d)/split(s)/delete all(da)/backward(b)/end(e):    ', ind(m));
        tmp_option = input('', 's');
        if tmp_option=='d'
            ind_del(m) = true;
            m = m+1;
        elseif strcmpi(tmp_option, 'b')
            m = m-1;
        elseif strcmpi(tmp_option, 'da')
            ind_del(m:end) = true;
            break;
        elseif strcmpi(tmp_option, 'k')
            ind_del(m) = false;
            m= m+1;
        elseif strcmpi(tmp_option, 's')
            try
                subplot(222);
                temp = imfreehand();
                tmp_ind = temp.createMask();
                tmpA = obj.A(:, ind(m));
                obj.A(:, end+1) = tmpA.*tmp_ind(:);
                obj.C(end+1, :) = obj.C(ind(m), :);
                obj.A(:, ind(m)) = tmpA.*(1-tmp_ind(:));
                obj.S(end+1, :) = obj.S(ind(m), :);
                obj.C_raw(end+1, :) = obj.C_raw(ind(m), :);
                obj.P.kernel_pars(end+1, :) = obj.P.kernel_pars(ind(m), :);
            catch
                sprintf('the neuron was not split\n');
            end
        elseif strcmpi(tmp_option, 't')
            try
                subplot(222);
                temp = imfreehand();
                tmp_ind = temp.createMask();
                obj.A(:, ind(m)) = obj.A(:, ind(m)).*tmp_ind(:);
            catch
                sprintf('the neuron was not trimmed\n');
            end
        elseif strcmpi(tmp_option, 'e')
            break;
        else
            m = m+1;
        end
    end
end
if save_img
    cd(cur_cd);
else
    obj.delete(ind(ind_del));
    obj.Coor = obj.get_contours(0.9);
end
figure; obj.viewContours(obj.Cn, 0.8, 0); close;


function test_ft_write_mri

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY ft_read_mri ft_write_mri

mri = ft_read_mri(dccnpath('/home/common/matlab/fieldtrip/data/ftp/test/ctf/Subject01.mri'));
mri = ft_convert_units(mri, 'mm');

%%

dataformat = {
  'analyze'
  'analyze_hdr'
  'analyze_img'
  'analyze_old'
  'freesurfer_mgz'
  'mgh'
  'mgz'
  'nifti'
  'nifti2'
  'nifti_gz'
  'nifti_img'
  'nifti_spm'
  'vmp'
  'vmr'
  };

%%

p = tempname;

for i=1:numel(dataformat)
  filename = fullfile(p, ['Subject01_' dataformat{i}]);
  % pass it as separate fields
  ft_write_mri(filename, mri.anatomy, 'dataformat', dataformat{i}, 'transform', mri.transform, 'unit', mri.unit, 'coordsys', mri.coordsys);
end

% remove the temporary directory with all files inside it
rmdir(p, 's');

%%

p = tempname;

for i=1:numel(dataformat)
  filename = fullfile(p, ['Subject01_' dataformat{i}]);
  % pass it as a structure
  ft_write_mri(filename, mri, 'dataformat', dataformat{i});
end

% remove the temporary directory with all files inside it
rmdir(p, 's');

%%

p = tempname;

% scale between -1 and 1, we will skip the unsigned formats
dat = double(mri.anatomy);
dat = dat./max(abs(dat(:)));

mri.anatomy = double(dat);                         filename = fullfile(p, 'Subject01_double'); ft_write_mri(filename, mri, 'dataformat', 'analyze_old');
mri.anatomy = single(dat);                         filename = fullfile(p, 'Subject01_single'); ft_write_mri(filename, mri, 'dataformat', 'analyze_old');
mri.anatomy = int32(dat.*double(intmax('int32'))); filename = fullfile(p, 'Subject01_int32');  ft_write_mri(filename, mri, 'dataformat', 'analyze_old');
mri.anatomy = int16(dat.*double(intmax('int16'))); filename = fullfile(p, 'Subject01_int16');  ft_write_mri(filename, mri, 'dataformat', 'analyze_old');

mri.anatomy = double(dat);                         filename = fullfile(p, 'Subject01_double'); ft_write_mri(filename, mri, 'dataformat', 'nifti');
mri.anatomy = single(dat);                         filename = fullfile(p, 'Subject01_single'); ft_write_mri(filename, mri, 'dataformat', 'nifti');
mri.anatomy = int32(dat.*double(intmax('int32'))); filename = fullfile(p, 'Subject01_int32');  ft_write_mri(filename, mri, 'dataformat', 'nifti');
mri.anatomy = int16(dat.*double(intmax('int16'))); filename = fullfile(p, 'Subject01_int16');  ft_write_mri(filename, mri, 'dataformat', 'nifti');
mri.anatomy = uint8(dat.*double(intmax('int8')));  filename = fullfile(p, 'Subject01_int8');   ft_write_mri(filename, mri, 'dataformat', 'nifti');

% remove the temporary directory with all files inside it
rmdir(p, 's');


function test_suite = test_independent_samples_partitioner
% tests for cosmo_independent_samples_partitioner
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #
    try % assignment of 'localfunctions' is necessary in Matlab >= 2016
        test_functions=localfunctions();
    catch % no problem; early Matlab versions can use initTestSuite fine
    end
    initTestSuite;

function test_independent_samples_partitioner_tiny()
    min_class_count=2;
    max_class_count=2+min_class_count;
    rng_class_count=[min_class_count,max_class_count];

    for nclasses=[2 3]
        for test_count=0:(nclasses+1)
            seed=ceil(rand()*1e6);
            opt=struct();
            opt.test_count=test_count;
            p1=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,opt,seed);

            opt=struct();
            opt.test_count=-test_count; % use test_ratio
            p2=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,opt,seed);

            assertEqual(p1,p2);
        end
    end

function test_independent_samples_partitioner_big()
    nclasses=ceil(rand()*4+10);
    for test_count=0:(nclasses+1)
        min_class_count=ceil(rand()*10+2);
        max_class_count=min_class_count+ceil(rand()*10+2);
        rng_class_count=[min_class_count,max_class_count];

        opt=struct();
        opt.test_count=test_count;
        opt.fold_count=ceil(rand()*100+10);

        p1=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,...
                                opt);

        opt=struct();
        opt.test_count=-test_count; % use test_ratio
        opt.fold_count=ceil(rand()*100+10);
        p2=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,...
                                opt);
    end

function test_independent_samples_partitioner_big_with_seed()
    opt=struct();
    opt.fold_count=100;
    opt.test_count=1;

    nclasses=ceil(rand()*4+10);
    min_class_count=ceil(rand()*10+2);
    max_class_count=min_class_count+ceil(rand()*10+2);
    rng_class_count=[min_class_count,max_class_count];

    ds_seed=(ceil(rand()*1e6));

    % without seed they use the default seed, must be equal
    p1=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,...
                                opt,ds_seed);
    p2=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,...
                                opt,ds_seed);
    assertEqual(p1,p2);
    opt.seed=1;
    p3=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,...
                                opt,ds_seed);
    assertEqual(p1,p3);
    opt.seed=2;
    p4=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,...
                                opt,ds_seed);
    assertFalse(isequal(p1,p4));

    % with no seed they must be identical
    opt.seed=0;
    p1=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,...
                                opt,ds_seed);
    p2=helper_test_independent_samples_partitioner(nclasses,...
                                rng_class_count,...
                                opt,ds_seed);

    assertFalse(isequal(p1,p2));

function p=helper_test_independent_samples_partitioner(nclasses,...
                            rng_class_count,opt,gen_seed)
    if nargin<4
        gen_seed=0;
    end

    ds=helper_generate_dataset(nclasses,...
                            rng_class_count,...
                            gen_seed);

    % compute how many samples per class in test set
    class_counts=histc(ds.sa.targets,1:nclasses);
    min_class_count=min(class_counts);
    max_class_count=max(class_counts);

    test_count=opt.test_count;
    if test_count<0
        % use test_ratio
        test_count=-test_count;
        opt=rmfield(opt,'test_count');
        opt.test_ratio=test_count/min_class_count;

    end

    train_count=min_class_count-test_count;

    has_illegal_count=train_count<=0 || test_count<=0;
    if has_illegal_count
        if ~isfield(opt,'fold_count')
            opt.fold_count=1;
        end
    else
        if isfield(opt,'fold_count')
            % given by calling funciton
            fold_count=opt.fold_count;
        else
            % use all folds available
            assert(nclasses<=3,'fold_count required with nclasses>3');
            assert(max_class_count<=5,'too many classes');
            % When not set we generate all possible folds; thereare at most
            % nchoosek(5,3)^nreps <= 20^3 = 8000 possible folds
            max_fold_count=8000; %

            % see how many possible folds based on each class
            combi_test=@(i)nchoosek(class_counts(i),test_count);
            test_fold_counts=arrayfun(combi_test,1:nclasses);
            combi_train=@(i)nchoosek(class_counts(i)-test_count,train_count);
            train_fold_counts=arrayfun(combi_train,1:nclasses);

            % take product
            fold_count=prod(test_fold_counts)*prod(train_fold_counts);
            assert(fold_count<=max_fold_count,'memory safety limit exceeded');
            opt.fold_count=fold_count;
        end
    end

    func=@()cosmo_independent_samples_partitioner(ds,opt);

    if has_illegal_count
        % not enough samples, expect an exception
        assertExceptionThrown(func,'')
        p=[];
        return
    end

    p=func();

    assertEqual(numel(p.train_indices),fold_count);
    assertEqual(numel(p.test_indices),fold_count);

    nsamples=size(ds.samples,1);

    train_count=min(class_counts)-test_count;

    for f=1:fold_count
        tr=p.train_indices{f};
        te=p.test_indices{f};
        assertTrue(isempty(intersect(tr,te)));

        assert_all_int_less_than(tr,nsamples);
        assert_all_int_less_than(te,nsamples);

        % equal number of targets in all classes, for train and test
        assert_all_hist_equal(ds.sa.targets(te),nclasses,test_count);
        assert_all_hist_equal(ds.sa.targets(tr),nclasses,train_count);
    end

    assert_all_folds_unique(p.train_indices,p.test_indices)

function ds=helper_generate_dataset(nclasses,rng_class_count,seed)
    % generate dataset where each target occurs at least min_class_count
    % times
    min_count=rng_class_count(1);
    max_count=rng_class_count(2);

    seed_arg={'seed',seed};

    delta=(max_count-min_count);
    assert(delta>0);

    % make lots of trials
    nregular=nclasses*min_count;
    nextra=ceil(delta*nclasses*cosmo_rand(seed_arg{:}));

    nsamples=nregular+nextra;

    ds=struct();
    ds.samples=rand(nsamples,2);
    ds.sa.targets=zeros(nsamples,1);
    rp=cosmo_randperm(nsamples,seed_arg{:});
    ds.sa.targets(1:nsamples)=mod(rp,nclasses)+1;
    ds.sa.chunks=(1:nsamples)';

    h=histc(ds.sa.targets,1:nclasses);
    assert(min(h)>=min_count)
    assert(max(h)<=max_count)

function assert_all_folds_unique(xs,ys)
    assert(all(min(cellfun(@min,xs))>=0));
    assert(all(min(cellfun(@min,ys))>=0));

    xs_max=max(cellfun(@max,xs));
    ys_max=max(cellfun(@max,ys));

    % value greater than max in all
    ys_mark=1+max(xs_max,ys_max);

    nfolds=numel(xs);
    merged=cell(nfolds,1);
    for f_i=1:nfolds

        xy=sort([xs{f_i}(:); (ys_mark+ys{f_i}(:))]);
        merged{f_i}=xy(:)';
    end

    % must all be same length
    c=cellfun(@numel,merged);
    assertEqual(c(1)+zeros(size(c)),c,'inputs do not have same length');

    % put in matrix
    merged_mat=cat(1,merged{:});
    s=sortrows(merged_mat);

    % look for duplicate rows
    eq_msk=bsxfun(@eq,s(1:(end-1),:),s(2:end,:));
    row_same=find(all(eq_msk,2),1);

    assertEqual(row_same,zeros(0,1),'row duplicate');

function assert_all_hist_equal(targets,nclasses,nreps)
    h_targets=histc(targets(:)',1:nclasses);
    assertEqual(h_targets,nreps+zeros(1,nclasses));

function assert_all_int_less_than(x,mx)
    assert(isnumeric(x));
    assertEqual(sort(x),x);
    assert(all(x>=1));
    assert(all(x<=mx));
    assert(all(round(x)==x));

function test_independent_samples_partitioner_mismatch_exceptions
    aet=@(varargin)assertExceptionThrown(@()...
                   cosmo_independent_samples_partitioner(varargin{:}),'');

    aet_targets=@(counts,varargin)aet(...
                 helper_generate_dataset_with_target_counts(counts{:}),...
                                                            varargin{:});

    opt=struct();
    opt.test_count=1;
    opt.fold_count=1;

    % missing target
    aet_targets({[3 3 3],[4 4]},opt);

    % not enought targets in one class
    aet_targets({[3 3 3],[2 2 1]},opt);

    opt.test_count=3;
    aet_targets({[4 3 4],[4 4 4]},opt);

    % try with ratio
    opt=rmfield(opt,'test_count');

    % missing target
    opt.test_ratio=.25;
    aet_targets({[10 10 10],[10 10]},opt);

    % too few targets
    aet_targets({[2 2 2],[4 4 4]},opt);

    % with too many folds
    aet_targets({[4 4 4],[4 4 4]},opt,'max_fold_count',0);

function test_independent_samples_partitioner_arg_exceptions
    aet=@(varargin)assertExceptionThrown(@()...
                   cosmo_independent_samples_partitioner(varargin{:}),'');
    ds=cosmo_synthetic_dataset();
    ds.sa.chunks=(1:size(ds.samples,1))';

    % missing arguments
    aet(ds);
    aet(ds,'fold_count');
    aet(ds,'fold_count',2);

    % mutually exclusive arguments
    aet(ds,'fold_count',2,'test_count',1,'test_ratio',.5);

    % not a dataset
    aet(struct,'fold_count',2,'test_count',1);

    % non-unique
    ds_bad=ds;
    ds_bad.sa.chunks(2)=ds.sa.chunks(1);
    aet(ds_bad,'fold_count',2,'test_count',1);

function ds=helper_generate_dataset_with_target_counts(varargin)
    nfeatures=2;
    nchunks=numel(varargin);
    ds_cell=cell(nchunks,1);
    for i=1:nchunks
        counts=varargin{i};
        nclasses=numel(counts);
        ds_parts=cell(nclasses,1);
        for j=1:nclasses
            nt=counts(j);
            ds=struct();

            ds.samples=randn(nt,nfeatures);
            ds.sa.targets=zeros(nt,1)+j;
            ds.sa.chunks=zeros(nt,1)+i;
            ds_parts{j}=ds;
        end

        ds_cell{i}=cosmo_stack(ds_parts);
    end

    ds=cosmo_stack(ds_cell);


function [bResult] = gui_IsStringPositiveFloat(sInput, sMessage)

bResult = true;
Tmp = str2double(sInput);
if (isnan(Tmp) | (Tmp <= 0))
  errordlg([sMessage ' must be a positive float value']);
  bResult = false;
end


% x = blk2vec(X,nL)
%
% Converts a block diagonal matrix into a vector.
%
% **********  INTERNAL FUNCTION OF FROMPACK  **********

function x = blk2vec(X,nL)

%
% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% This program 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 2 of the License, or
% (at your option) any later version.
%
% This program 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 program; if not, write to the Free Software
% Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA %

nblk = length(nL);
sumnk = 0;
x = [];
for k = 1:nblk
    nk = nL(k);
    x = [x; vec(X(sumnk+1:sumnk + nk,sumnk+1:sumnk + nk))] ;
    sumnk = sumnk + nk;
end


function u = rgbtogrey(v)

% rgbtogrey -- Create greyscale image from RGB image
%
% Usage:
%       u = rgbtogrey(v)
%
% Input:
%       v           Input RGB image
%
% Output:
%       u           Output greyscale image
%
%
% Author: Brendt Wohlberg <brendt@lanl.gov>  Modified: 2014-05-29
%
% This file is part of the SPORCO library. Details of the copyright
% and user license can be found in the 'License' file distributed with
% the library.

if size(v,3) == 1,
  u = v;
elseif size(v,3) == 3,
  C = [0.30 0.59 0.11];
  u = C(1)*v(:,:,1) +  C(2)*v(:,:,2) + C(3)*v(:,:,3);
else
  warning('rgbtogrey: input image must have 1 or 3 bands');
  u = [];
end

return


function varargout = sech(varargin)

switch class(varargin{1})

    case 'sdpvar'
        varargout{1} = InstantiateElementWise(mfilename,varargin{:});

    case 'char'

        operator = CreateBasicOperator('bell-shape','callback');
        operator.derivative = @(x)(-tanh(x).*sech(x));
        operator.stationary = [0 1];
        operator.inflection = [-inf 1 -0.881493604 -1 0.881493604 1];
        operator.range = [0 1];

        varargout{1} = [];
        varargout{2} = operator;
        varargout{3} = varargin{3};

    otherwise
        error(['SDPVAR/' upper(mfilename) ' called with weird argument']);
end


function [rtk,stat0]=relpos(rtk,obsr,obsb,nav)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%% relative positioning %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%input:  rtk - rtk control struct
%        obsr - rover observations
%        obsb - base observations
%        nav - navigation message
%output: rtk - rtk control struct
%        stat0 - state (0:error 1:ok)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%relative positioning include PPD, PPK and PPS
%PPD:post-processing differenced, based on double-differenced PR
%PPK:post-processing kinematic, based on double-differenced CP and PR
%PPS:post-processing static, based on double-differenced CP and PR
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
global glc
opt=rtk.opt; nf=rtk.NF; dt=timediff(obsr(1).time,obsb(1).time);
nobsr=size(obsr,1); nobsb=size(obsb,1);

if rtk.opt.mode<=glc.PMODE_DGNSS
    stat=glc.SOLQ_DGNSS;
else
    stat=glc.SOLQ_FLOAT;
end

for i=1:glc.MAXSAT
    [sys,~]=satsys(i);
    rtk.sat(i).sys=sys;
    for j=1:glc.NFREQ
        rtk.sat(i).vsat(j)=0;
    end
    for j=1:glc.NFREQ
        rtk.sat(i).snr(j)=0;
    end
end

svr=satposs(obsr,nav,opt.sateph);
svb=satposs(obsb,nav,opt.sateph);

% zero-differenced residuals for base
[zdb,stat_tmp]=zdres(2,obsb,svb,nav,rtk.basepos,opt,rtk);
if stat_tmp==0,stat0=0;return;end

ind=selcomsat(obsr,obsb,opt,zdb);
if ind.ns==0,stat0=0;return;end

% debug tracing
% fprintf('\n\n\n');
% fprintf('time=%d\n',obsr(1).time.time);
% fprintf('before time update\n');
% printx(rtk.x,rtk);
% printP(rtk.P,rtk);

% time update
rtk=udstate(rtk,obsr,obsb,nav,ind);

% debug tracing
% fprintf('after time update\n');
% printx(rtk.x,rtk);
% printP(rtk.P,rtk);

xp=rtk.x; Pp=zeros(rtk.nx,rtk.nx);
for i=1:opt.niter

    % zero-differenced residuals for rover
    [zdr,stat_tmp]=zdres(1,obsr,svr,nav,xp(1:3),opt,rtk);
    if stat_tmp==0,stat=glc.SOLQ_NONE;break;end

    % double-differenced residuals,measurement matrix and noise matrix
    [rtk,v,H,R,nv,~]=ddres(rtk,nav,dt,xp,Pp,zdr,zdb,ind);
    if nv<=0,stat=glc.SOLQ_NONE;break;end

    % debug tracing
%     printv(v);
%     printH(H);
%     printR(R);

    % measurement update
    Pp=rtk.P;
    [xp,Pp,stat_tmp]=Kfilter_h(v,H,R,xp,Pp);
    if stat_tmp==0
        [week,sow]=time2gpst(obs(1).time);
        fprintf('Warning:GPS week = %d sow = %.3f,filter error!\n',week,sow);
        stat=glc.SOLQ_NONE;
        break;
    end

    % debug tracing
%     fprintf('after measurement update\n');
%     printx(xp,rtk);
%     printP(Pp,rtk);

end

if stat~=glc.SOLQ_NONE
    % zero-differenced residuals for rover
    [zdr,stat_tmp]=zdres(1,obsr,svr,nav,xp(1:3),opt,rtk);
    if stat_tmp~=0
        % post-fit residuals for float solution
        [rtk,v,~,R,nv,vflag]=ddres(rtk,nav,dt,xp,Pp,zdr,zdb,ind);
        % validation of float solution
        if valpos_rel(rtk,v,R,vflag,nv,4)
            rtk.x=xp; rtk.P=Pp;
            rtk.sol.ns=0;
            for i=1:ind.ns
                for f=1:nf
                    sati=ind.sat(i);
                    if ~rtk.sat(sati).vsat(f),continue;end
                    rtk.sat(sati).lock(f)=rtk.sat(sati).lock(f)+1;
                    rtk.sat(sati).outc(f)=0;
                    if f==1,rtk.sol.ns=rtk.sol.ns+1;end
                end
            end
            if rtk.sol.ns<4,stat=glc.SOLQ_NONE;end
        else
            stat=glc.SOLQ_NONE;
        end
    end
end

% ambiguity resolution
if stat~=glc.SOLQ_NONE
    [rtk,~,xa,nb]=resamb(rtk);
    if nb>1
        % zero-differenced residuals for rover
        [zdr,stat_tmp]=zdres(1,obsr,svr,nav,xa(1:3),opt,rtk);
        if stat_tmp~=0
            % post-fit reisiduals for fixed solution
            [rtk,v,~,R,nv,vflag]=ddres(rtk,nav,dt,xa,Pp,zdr,zdb,ind);
            % validation of fixed solution
            if valpos_rel(rtk,v,R,vflag,nv,4)
                rtk.nfix=rtk.nfix+1;
                if rtk.nfix>=opt.minfix&&rtk.opt.modear==glc.ARMODE_FIXHOLD
                    % hold integer ambiguity
                    rtk=holdamb(rtk,xa);
                end
                stat=glc.SOLQ_FIX;
            end
        end
    end
end

% save solution status
if stat==glc.SOLQ_FIX
    rtk.sol.pos=rtk.xa(1:3)';
    rtk.sol.posP(1)=rtk.Pa(1,1); rtk.sol.posP(2)=rtk.Pa(2,2);
    rtk.sol.posP(3)=rtk.Pa(3,3); rtk.sol.posP(4)=rtk.Pa(1,2);
    rtk.sol.posP(5)=rtk.Pa(2,3); rtk.sol.posP(6)=rtk.Pa(1,3);
    if rtk.opt.dynamics==1
        rtk.sol.vel=rtk.xa(4:6)';
        rtk.sol.velP(1)=rtk.Pa(4,4); rtk.sol.velP(2)=rtk.Pa(5,5);
        rtk.sol.velP(3)=rtk.Pa(6,6); rtk.sol.velP(4)=rtk.Pa(4,5);
        rtk.sol.velP(5)=rtk.Pa(5,6); rtk.sol.velP(6)=rtk.Pa(4,6);
    end
else
    rtk.sol.pos=rtk.x(1:3)';
    rtk.sol.posP(1)=rtk.P(1,1); rtk.sol.posP(2)=rtk.P(2,2);
    rtk.sol.posP(3)=rtk.P(3,3); rtk.sol.posP(4)=rtk.P(1,2);
    rtk.sol.posP(5)=rtk.P(2,3); rtk.sol.posP(6)=rtk.P(1,3);
    if rtk.opt.dynamics==1
        rtk.sol.vel=rtk.xa(4:6)';
        rtk.sol.velP(1)=rtk.P(4,4); rtk.sol.velP(2)=rtk.P(5,5);
        rtk.sol.velP(3)=rtk.P(6,6); rtk.sol.velP(4)=rtk.P(4,5);
        rtk.sol.velP(5)=rtk.P(5,6); rtk.sol.velP(6)=rtk.P(4,6);
    end
    rtk.nfix=0;
end

for i=1:nobsr
    for j=1:nf
        if obsr(i).L(j)==0,continue;end
        rtk.sat(obsr(i).sat).pt(1,j)=obsr(i).time;
        rtk.sat(obsr(i).sat).ph(1,j)=obsr(i).L(j);
    end
end
for i=1:nobsb
    for j=1:nf
        if obsb(i).L(j)==0,continue;end
        rtk.sat(obsb(i).sat).pt(2,j)=obsb(i).time;
        rtk.sat(obsb(i).sat).ph(2,j)=obsb(i).L(j);
    end
end

for i=1:ind.ns
    for j=1:nf
        rtk.sat(ind.sat(i)).snr(j)=obsr(ind.ir(i)).S(j);
    end
end

for i=1:glc.MAXSAT
    for j=1:nf
        if rtk.sat(i).fix(j)==2&&stat~=glc.SOLQ_FIX
            rtk.sat(i).fix(j)=1;
        end
        if bitand(rtk.sat(i).slip(j),1)
            rtk.sat(i).slipc(j)=rtk.sat(i).slipc(j)+1;
        end
    end
end

if stat~=glc.SOLQ_NONE,rtk.sol.stat=stat;end

stat0=(stat~=glc.SOLQ_NONE);

return