function [M_final,shifts_g,template,options,col_shift] = normcorre_batch_even(Y,options,template)

% online motion correction through DFT subpixel registration
% Based on the dftregistration.m function from Manuel Guizar and Jim Fienup

% INPUTS
% Y:                Input data, can be already loaded in memory as a 3D
%                   tensor, a memory mapped file, or a pointer to a tiff stack
% options:          options structure for motion correction (optional, rigid registration is performed if not provided)
% template:         provide template (optional)

% OUTPUTS
% M_final:          motion corrected data
% shifts_up:        upsampled shifts
% shifts:           originally calculated shifts
% template:         calculated template

%% first determine filetype

if isa(Y,'char')
    [~,~,ext] = fileparts(Y);
    ext = ext(2:end);
    if strcmpi(ext,'tif') || strcmpi(ext,'tiff')
        tiffInfo = imfinfo(Y);
        filetype = 'tif';
        T = length(tiffInfo);
        sizY = [tiffInfo(1).Height,tiffInfo(1).Width,T];
    elseif strcmpi(ext,'mat')
        filetype = 'mem';
        Y = matfile(Y,'Writable',true);
        details = whos(Y);
        var_sizes = [details.bytes];
        [~,var_ind] = max(var_sizes);
        var_name = details(var_ind).name;
        sizY = size(Y,var_name);
        T = sizY(end);
    elseif strcmpi(ext,'hdf5') || strcmpi(ext,'h5')
        filetype = 'hdf5';
        fileinfo = hdf5info(Y);
        data_name = fileinfo.GroupHierarchy.Datasets.Name;
        sizY = fileinfo.GroupHierarchy.Datasets.Dims;
        T = sizY(end);
    elseif strcmpi(ext,'raw')
        filetype = 'raw';
        fid = fopen(Y);
        FOV = [options.d1,options.d2];
        bitsize = options.bitsize;
        imsize = FOV(1)*FOV(2)*bitsize;                                                   % Bit size of single frame
        current_seek = ftell(fid);
        fseek(fid, 0, 1);
        file_length = ftell(fid);
        fseek(fid, current_seek, -1);
        T = file_length/imsize;
        sizY = [FOV,T];
        fclose(fid);
    elseif strcmpi(ext,'avi')
        filetype = 'avi';
        sizY = size(read_file(Y));
        FOV = sizY(1:2);
        T = sizY(end);
    end
elseif isobject(Y)
    filetype = 'mem';
    var_name = 'Y';
    sizY = size(Y,var_name);
    T = sizY(end);
else % array loaded in memory
    filetype = 'mat';
    sizY = size(Y);
    T = sizY(end);
end

nd = length(sizY)-1;                          % determine whether imaging is 2d or 3d
sizY = sizY(1:nd);
otherdims = repmat({':'},1,nd);
%% set default parameters if not present

if ~exist('options','var') || isempty(options)
    options = NoRMCorreSetParms('d1',sizY(1),'d2',sizY(2));
    if nd > 2; options.d3 = sizY(3); end
end

memmap = options.memmap;
grid_size = options.grid_size;
mot_uf = options.mot_uf;
min_patch_size = options.min_patch_size;
min_diff = options.min_diff;
overlap_pre = options.overlap_pre;
overlap_post = options.overlap_post;
upd_template = options.upd_template;
bin_width = options.bin_width;
buffer_width = options.buffer_width;
max_dev_g = options.max_dev;
init_batch = options.init_batch;
us_fac = options.us_fac;
method = options.method;
filename = options.mem_filename;
iter = options.iter;
add_value = options.add_value;
max_shift = options.max_shift;
if strcmpi(options.boundary,'nan')
    fill_value = NaN;
else
    fill_value = add_value;
end
print_msg = options.print_msg;

while mod(T,bin_width) == 1
    if T == 1
        error('Movie appears to have only one frame. Use the function normcorre instead')
    end
    bin_width = bin_width + 1;
end

%% first check for offset due to bi-directional scanning

if options.correct_bidir && isempty(options.col_shift)
    col_shift = correct_bidirectional_offset(Y,options.nFrames,options.bidir_us);
elseif ~isempty(options.col_shift)
    col_shift = options.col_shift;
else
    col_shift = 0;
end
options.col_shift = col_shift;
if col_shift
    if print_msg; fprintf('Offset %1.1d pixels due to bidirectional scanning detected. \n',col_shift); end
    if strcmpi(options.shifts_method,'fft')
        options.shifts_method = 'cubic';
        if print_msg; fprintf('Cubic shifts will be applied. \n'); end
    end
end
%% read initial batch and compute template

init_batch = min(T,init_batch);
interval = ceil(T/2-init_batch/2+1):floor(T/2+init_batch/2);
switch filetype
    case 'tif'
        Y_temp = read_file(Y,interval(1),init_batch,[],tiffInfo);
    case 'hdf5'
        Y_temp = read_file(Y,interval(1),init_batch);
    case 'avi'
        Y_temp = read_file(Y,interval(1),init_batch);
    case 'mem'
        Y_temp = Y.(var_name)(otherdims{:},interval);
    case 'mat'
        Y_temp = Y(otherdims{:},interval);
    case 'raw'
        Y_temp = read_raw_file(Y,interval(1),init_batch,FOV,bitsize);
end
data_type = class(Y_temp);
Y_temp = single(Y_temp);
use_proj = true;
if nargin < 3 || isempty(template)
    if print_msg; fprintf('Registering the first %i frames just to obtain a good template....',init_batch); end
    template_in = median(Y_temp,nd+1)+add_value;
    fftTemp = fftn(template_in);
    for t = 1:size(Y_temp,nd+1)
        if nd == 2
            [~,Greg] = dftregistration_min_max(fftTemp,fftn(Y_temp(:,:,t)),us_fac,-max_shift,max_shift,options.phase_flag);
        end
        if nd == 3
            [~,Greg] = dftregistration_min_max_3d(fftTemp,fftn(Y_temp(:,:,:,t)),us_fac,-max_shift,max_shift,options.phase_flag);
        end
        M_temp = real(ifftn(Greg));
        template_in = template_in*(t-1)/t + M_temp/t;
    end
    template_in = template_in + add_value;
    if print_msg; fprintf('..done. \n'); end
else
    template_in = single(template + add_value);
end

[d1,d2,d3,~] = size(Y_temp);
if nd == 2; d3 = 1; end
%% setup grids for patches
dim = [d1,d2,d3];
patches = construct_grid_even(grid_size,overlap_pre,dim,min_diff);
shifts_g = struct('shifts',cell(T,1),'shifts_up',cell(T,1),'diff',cell(T,1));
template_patches = split_frame(template_in,patches);
patch_size = size(template_patches);
n_patches = [length(unique(patches(:,1))),length(unique(patches(:,3))),length(unique(patches(:,5)))];
%%
%maxNumCompThreads(1);
temp_mat = template_in;

fftTemp =fft(fft(fft(template_patches,[],1),[],2),[],3);
fftTempMat = fftn(temp_mat);

if ~strcmpi(options.output_type,'mat')
    options.mem_batch_size = max(min(round(options.mem_batch_size/bin_width)*bin_width,T),1);
    mem_buffer = squeeze(zeros([dim,options.mem_batch_size],'single'));
end

switch lower(options.output_type)
    case 'mat'
        M_final = zeros([sizY,T],data_type);
    case 'memmap'
        M_final = matfile(filename,'Writable',true);
        if nd == 2; M_final.Y(d1,d2,T) = zeros(1,data_type); end
        if nd == 3; M_final.Y(d1,d2,d3,T) = zeros(1,data_type); end
        M_final.Yr(d1*d2*d3,T) = zeros(1,data_type);
    case {'hdf5','h5'}
         if exist(options.h5_filename,'file')
            [pathstr,fname,ext] = fileparts(options.h5_filename);
            new_filename = fullfile(pathstr,[fname,'_',datestr(now,30),ext]);
            warning_msg = ['File ',options.h5_filename,'already exists. Saving motion corrected file as',new_filename];
            warning('%s',warning_msg);
            options.h5_filename = new_filename;
        end
        M_final = options.h5_filename;
        if nd == 2
            h5create(options.h5_filename,['/',options.h5_groupname],[d1,d2,Inf],'Chunksize',[d1,d2,options.mem_batch_size],'Datatype',data_type);
        elseif nd == 3
            h5create(options.h5_filename,['/',options.h5_groupname],[d1,d2,d3,Inf],'Chunksize',[d1,d2,d3,options.mem_batch_size],'Datatype',data_type);
        end
    case {'tif','tiff'}
        M_final = ['motion corrected file has been saved as ', options.tiff_filename];
        opts_tiff.append = true;
        opts_tiff.big = true;
        if nd == 3
            error('Saving volumetric tiff stacks is currently not supported. Use a different filetype');
        end
    otherwise
        error('This filetype is currently not supported')
end

cnt_buf = 0;
if print_msg; fprintf('Template initialization complete.  Now registering all the frames with new template. \n'); end
%%

prevstr = [];
for it = 1:iter
    for t = 1:bin_width:T
        switch filetype
            case 'tif'
                Ytm = single(read_file(Y, t, min(t+bin_width-1,T)-t+1, [], tiffInfo));
            case 'avi'
                Ytm = single(read_file(Y, t, min(t+bin_width-1,T)-t+1));
            case 'hdf5'
                Ytm = single(h5read(Y,data_name,[ones(1,nd),t],[sizY(1:nd),min(t+bin_width-1,T)-t+1]));
            case 'mem'
                Ytm = single(Y.(var_name)(otherdims{:},t:min(t+bin_width-1,T)));
            case 'mat'
                Ytm = single(Y(otherdims{:},t:min(t+bin_width-1,T)));
            case 'raw'
                Ytm = single(read_raw_file(Y,t,min(t+bin_width-1,T)-t+1,FOV,bitsize));
        end

        Mf = zeros(size(Ytm),data_type);
        lY = size(Ytm,nd+1);
        shifts = struct('shifts',cell(lY,1),'shifts_up',cell(lY,1),'diff',cell(lY,1));
        for i = lY:-1:1
            Yt = Ytm(otherdims{:},i);
            future_results(i) = parfeval(@register_frame, 2, Yt,fftTempMat,fftTemp,patches,options);
        end
        for i = 1:lY
            [idx, shifts_temp, Mf_temp] = fetchNext(future_results);
            shifts(idx).shifts = shifts_temp;
            shifts(idx).shifts_up = shifts_temp;
            Mf(otherdims{:},idx) = Mf_temp;
        end

        shifts_g(t:min(t+bin_width-1,T)) = shifts;

        if ~strcmpi(options.output_type,'mat')
            rem_mem = rem(t+lY-1,options.mem_batch_size);
            if rem_mem == 0; rem_mem = options.mem_batch_size; end
            mem_buffer(otherdims{:},rem_mem-lY+1:rem_mem) = cast(Mf,data_type);
        end
        if it == iter
            switch lower(options.output_type)
                case 'mat'
                    M_final(otherdims{:},t:min(t+bin_width-1,T)) = cast(Mf,data_type);
                case 'memmap'
                    if rem_mem == options.mem_batch_size || t+lY-1 == T
                        M_final.Y(otherdims{:},t+lY-rem_mem:t+lY-1) = mem_buffer(:,:,1:rem_mem);
                        M_final.Yr(:,t+lY-rem_mem:t+lY-1) = reshape(mem_buffer(1:d1*d2*d3*rem_mem),d1*d2*d3,rem_mem);
                    end
                case {'hdf5','h5'}
                    if rem_mem == options.mem_batch_size || t+lY-1 == T
                        if nd == 2; h5write(options.h5_filename,['/',options.h5_groupname],mem_buffer(:,:,1:rem_mem),[ones(1,nd),t+lY-rem_mem],[sizY(1:nd),rem_mem]); end
                        if nd == 3; h5write(options.h5_filename,['/',options.h5_groupname],mem_buffer(:,:,:,1:rem_mem),[ones(1,nd),t+lY-rem_mem],[sizY(1:nd),rem_mem]); end
                    end
                case {'tif','tiff'}
                    if rem_mem == options.mem_batch_size || t+lY-1 == T
                        saveastiff(cast(mem_buffer(:,:,1:rem_mem),data_type),options.tiff_filename,opts_tiff);
                    end
            end
        end
        if print_msg
            str = sprintf('%d out of %d frames registered, iteration %d out of %d..', t+lY-1, T, it, iter);
            refreshdisp(str, prevstr, t);
            prevstr=str;
        end
        % update template
        if upd_template
            cnt_buf = cnt_buf + 1;
            if strcmpi(method{2},'mean')
                new_temp = nanmean(Mf,nd+1);
            elseif strcmpi(method{2},'median')
                new_temp = nanmedian(x,nd+1);
            end
            if any(isnan(new_temp(:)))
                new_temp(isnan(new_temp)) =  template(isnan(new_temp));
            end
            if strcmpi(method{1},'mean')
                cnt = t/bin_width + 1;
                temp_mat = temp_mat*(cnt-1)/cnt + new_temp/cnt;
            elseif strcmpi(method{1},'median')
                ind_buffer = mod(cnt_buf,buffer_width) + buffer_width*(~mod(cnt_buf,buffer_width));
                buffer_med(otherdims{:},ind_buffer) = new_temp;
                temp_mat = nanmedian(buffer_med,nd+1);
            end
            template_patches = split_frame(temp_mat,patches);
            fftTemp = fft(fft(fft(template_patches,[],1),[],2),[],3);
            fftTempMat = fftn(temp_mat);
        end
    end

    if it == iter
        template = temp_mat - add_value;
    end
    if memmap
        M_final.shifts = shifts_g;
        M_final.template = template;
    end
end
if print_msg; fprintf('\n'); end
maxNumCompThreads('automatic');


% statcondfiledtrip()  - same as statcond except that it uses the fieldtrip
%                        statistical functions. This is useful to perform
%                        a wider variety of corrections for multiple
%                        comparisons for instance.
% Usage:
%          >> [stats, df, pvals, surrog] = statcond( data, 'key','val'... );
% Inputs:
%   data       = same as for statcond()
%
% Optional inputs:
%   'paired'   = ['on'|'off'] pair the data array {default: 'on' unless
%                the last dimension of data array is of different lengths}.
%   'mode'     = ['perm'|'param'] mode for computing the p-values:
%                 'param' = parametric testing (standard ANOVA or t-test);
%                 'perm' = non-parametric testing using surrogate data
%                  made by permuting the input data {default: 'perm'}
%   'naccu'    = this input is passed on as 'numrandomization' to Fieldtrip
%   'chanlocs' = EEGLAB channel location structure to perfom statistics
%                and cluster correction for multiple comparisons accross
%                channels (native fieldtrip entries may also be used).
%
% Fieldtrip options:
%   Any option to the freqanalysis, the statistics_montecarlo, the
%   statistics_analysis, statistics_stat, statistics_glm may be used
%   using 'key', val argument pairs.
%
% Outputs:
%   stats      = F- or T-value array of the same size as input data without
%                the last dimension. A T value is returned only when the data
%                includes exactly two conditions.
%   df         = degrees of freedom, a (2,1) vector, when F-values are returned
%   pvals      = array of p-values. Same size as input data without the last
%                data dimension. All returned p-values are two-tailed.
%   surrog     = surrogate data array (same size as input data with the last
%                dimension filled with a number ('naccu') of surrogate data sets.
%
% Author: Arnaud Delorme, SCCN/INC/UCSD, La Jolla, 2005-
%         With thanks to Robert Oostenveld for fruitful discussions
%         and advice on this function.
%
% See also: freqanalysis(), statistics_montecarlol()

% Copyright (C) Arnaud Delorme
%
% 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function [ ori_vals, df, pvals, surrogval ] = statcondfieldtrip( data, varargin );

    if nargin < 1
        help statcondfieldtrip;
        return;
    end;

    [g cfgparams] = finputcheck( varargin, { 'naccu'    'integer'   [1 Inf]             200;
                                             'mode'     'string'    { 'param' 'perm' 'bootstrap' }  'param';
                                             'chanlocs' 'struct'    { }   struct([]);
                                             'method'   'string'    { 'montecarlo' 'analytic' 'stat' 'glm' } 'analytic';
                                             'paired'   'string'    { 'on' 'off' }      'on' }, 'statcond', 'ignore');
    if isstr(g), error(g); end;

    if size(data,2) == 1, data  = transpose(data); end; % cell array transpose

    tmpsize   = size(data{1});

    % cfg configuration for Fieldtrip
    % -------------------------------
    cfg = struct(cfgparams{:});
    cfg.method      = g.method;
    if ~strcmpi(g.mode, 'param'), cfg.method = 'montecarlo'; end;
    if ~isempty(g.chanlocs)
        EEG = eeg_emptyset;
        EEG.chanlocs = g.chanlocs;
        EEG.nbchan   = length(g.chanlocs);
        EEG.data     = zeros(EEG.nbchan,100,1);
        EEG = eeg_checkset(EEG);
        tmpcfg = eeglab2fieldtrip(EEG, 'preprocessing', 'none');
        lay = prepare_layout(tmpcfg, tmpcfg);
        tmpcfg.layout        = lay;
        tmpcfg.neighbourdist = 30; %mean(abs([ EEG.chanlocs.X ]));
        cfg.neighbours    = neighbourselection(tmpcfg, []);
    else
        cfg.neighbours  = {};
    end;
    cfg.feedback    = 'no';
    cfg.ivar        = 1;
    cfg.alpha       = 0.05;
    cfg.numrandomization = g.naccu;

    % test if data can be paired
    % --------------------------
    if length(unique(cellfun('size', data, ndims(data{1}) ))) > 1
        g.paired = 'off';
    end;
    fprintf('%d x %d, ', size(data,1), size(data,2));
    if strcmpi(g.paired, 'on')
         fprintf('paired data, ');
    else fprintf('unpaired data, ');
    end;
    if size(data,1) == 1 & size(data,2) == 2
         fprintf('computing T values\n');
    else fprintf('computing F values\n');
    end;

    % output text
    % -----------
    if ~strcmpi(g.mode, 'param')
        fprintf('Accumulating (of %d):', g.naccu);
    end;

    if size(data,1) == 1, % only one row

        if size(data,2) == 2 & strcmpi(g.paired, 'on')

            % paired t-test (very fast)
            % -------------
            cfg.statistic   = 'depsamplesT';
            [newdata design1 design2 design3] = makefieldtripdata(data, 0, g.chanlocs);
            cfg.design      = [ design1; design3 ];
            cfg.uvar        = 2;

            cfg
            stat            = freqstatistics(cfg, newdata{:});
            ori_vals        = stat.stat;
            df              = [];
            pvals           = stat.prob;
            return;

        elseif size(data,2) == 2 & strcmpi(g.paired, 'off')

            % paired t-test (very fast)
            % -------------
            cfg.statistic   = 'indepsamplesT';
            [newdata design1] = makefieldtripdata(data, 0, g.chanlocs);
            cfg.design      = design1;
            stat            = freqstatistics(cfg, newdata{:});
            ori_vals        = stat.stat;
            df              = [];
            pvals           = stat.prob;
            return;

        elseif strcmpi(g.paired, 'on')

            % one-way ANOVA (paired) this is equivalent to unpaired t-test
            % -------------
            cfg.statistic   = 'depsamplesF';
            [newdata design1 design2 design3] = makefieldtripdata(data, 0, g.chanlocs);
            cfg.design      = [ design1; design3 ];
            cfg.uvar        = 2;
            stat            = freqstatistics(cfg, newdata{:});
            ori_vals        = stat.stat;
            df              = [];
            pvals           = stat.prob;
            return;

        else
            % one-way ANOVA (unpaired)
            % -------------
            cfg.statistic   = 'indepsamplesF';
            [newdata design1] = makefieldtripdata(data, 0, g.chanlocs);
            cfg.design      = [ design1 ];
            stat            = freqstatistics(cfg, newdata{:});
            ori_vals        = stat.stat;
            df              = [];
            pvals           = stat.prob;
            return;

        end;
    else
        if strcmpi(g.paired, 'on')

            % two-way ANOVA (paired)
            % -------------
            cfg.statistic   = 'anovan';
            [newdata design1 design2 design3] = makefieldtripdata(data, 0, g.chanlocs);
            cfg.design      = [ design1; design2; design3 ];
            cfg.effect      = 'X1*X2';
            cfg.ivar        = [1 2];
            cfg.uvar        = 3;
            stat            = freqstatistics(cfg, newdata{:});
            ori_vals        = stat.stat;
            df              = [];
            pvals           = stat.prob;
            return;

        else

            % two-way ANOVA (unpaired)
            % -------------
            cfg.statistic   = 'anovan';
            cfg.clustercritval = 4.5416; % 95 percentile of n =10000; a = { rand(n,10) rand(n,10); rand(n,10) rand(n,10) }; [F df p ] = statcondfieldtrip(a, 'paired', 'off');
            [newdata design1 design2] = makefieldtripdata(data, 0, g.chanlocs);
            if ~isempty(g.chanlocs)
                for index = 1:length(newdata)
                    newdata{index}.powspctrm = squeeze(newdata{index}.powspctrm);
                    newdata{index}.label     = { g.chanlocs.labels };
                    newdata{index}.freq      = 1;
                end;
            end;
            cfg
            newdata{1}
            cfg.design      = [ design1; design2 ];
            cfg.effect      = 'X1*X2';
            cfg.ivar        = [1 2];
            stat            = freqstatistics(cfg, newdata{:});
            ori_vals        = stat.stat;
            df              = [];
            pvals           = stat.prob;
            return;

        end;
    end;

function val = myndims(a)
    if ndims(a) > 2
        val = ndims(a);
    else
        if size(a,1) == 1,
            val = 2;
        elseif size(a,2) == 1,
            val = 1;
        else
            val = 2;
        end;
    end;

function [newdata, design1, design2, design3] = makefieldtripdata(data, chanflag, chanlocs);

    newdata = {};
    for i = 1:length(data(:))

        switch myndims(data{1})
          case 1,
            newdata{i}.powspctrm = data{i};

          case 2,
            if chanflag
                 newdata{i}.powspctrm = transpose(data{i});
            else newdata{i}.powspctrm = reshape(transpose(data{i}), size(data{i},2), 1, size(data{i},1));
            end;

          case 3,
            if chanflag
                 newdata{i}.powspctrm = permute(data{i}, [3 1 2]);
            else newdata{i}.powspctrm = permute(data{i}, [3 4 1 2]);
            end;

          case 4,
            if chanflag
                 newdata{i}.powspctrm = permute(data{i}, [4 1 2 3]);
            else newdata{i}.powspctrm = permute(data{i}, [3 5 1 2]);
            end;

        end;

        newdata{i}.dimord    = 'rpt_chan_freq_time';
        newdata{i}.label     = cell(1,size(newdata{i}.powspctrm,2));
        newdata{i}.label(:)  = { 'cz' };
        newdata{i}.freq      = [1:size(newdata{i}.powspctrm,3)];
        newdata{i}.time      = [1:size(newdata{i}.powspctrm,4)];

        % below in case channels are specified
        % not that statistics are done on time x frequencies or channels
        % so time x frequency x channels do not work yet here
        if ~isempty(chanlocs)
            newdata{i}.powspctrm = squeeze(newdata{i}.powspctrm);
            newdata{i}.label     = { chanlocs.labels };
            newdata{i}.freq      = 1;
            newdata{i}.time      = 1;
        end;

    end;

    design1 = [];
    design2 = [];
    design3 = [];
    for i = 1:size(data,2)
        for j = 1:size(data,1)
            ij = j+(i-1)*size(data,1);
            design1 = [ design1 ones(1, size(newdata{i}.powspctrm,1))*i ];
            design2 = [ design2 ones(1, size(newdata{i}.powspctrm,1))*j ];
            design3 = [ design3 [1:size(newdata{i}.powspctrm,1)] ];
        end;
    end;


function om = add_legacy_cost(om, name, idx, varargin)
%ADD_LEGACY_COST  Adds a set of user costs to the model.
%
%   OM.ADD_LEGACY_COST(NAME, CP);
%   OM.ADD_LEGACY_COST(NAME, CP, VARSETS);
%   OM.ADD_LEGACY_COST(NAME, IDX_LIST, CP);
%   OM.ADD_LEGACY_COST(NAME, IDX_LIST, CP, VARSETS);
%
%   Adds a named block of user-defined costs to the model. Each set is
%   defined by the CP struct described below. All user-defined sets of
%   costs are combined together into a single set of cost parameters in
%   a single CP struct by BULD_COST_PARAMS. This full aggregate set of
%   cost parameters can be retreived from the model by GET_COST_PARAMS.
%
%   Examples:
%       cp1 = struct('N', N1, 'Cw', Cw1);
%       cp2 = struct('N', N2, 'Cw', Cw2, 'H', H, 'dd', dd, ...
%                     'rh', rh, 'kk', kk, 'mm', mm);
%       om.add_legacy_cost('usr1', cp1, {'Pg', 'Qg', 'z'});
%       om.add_legacy_cost('usr2', cp2, {'Vm', 'Pg', 'Qg', 'z'});
%
%       om.init_indexed_name('c', {2, 3});
%       for i = 1:2
%         for j = 1:3
%           om.add_legacy_cost('c', {i, j}, cp(i,j), ...);
%         end
%       end
%
%   Let x refer to the vector formed by combining the specified VARSETS,
%   and f_u(x, CP) be the cost at x corresponding to the cost parameters
%   contained in CP, where CP is a struct with the following fields:
%       N      - nw x nx sparse matrix (optional, identity matrix by default)
%       Cw     - nw x 1 vector
%       H      - nw x nw sparse matrix (optional, all zeros by default)
%       dd, mm - nw x 1 vectors (optional, all ones by default)
%       rh, kk - nw x 1 vectors (optional, all zeros by default)
%
%   These parameters are used as follows to compute f_u(x, CP)
%
%       R  = N*x - rh
%
%               /  kk(i),  R(i) < -kk(i)
%       K(i) = <   0,     -kk(i) <= R(i) <= kk(i)
%               \ -kk(i),  R(i) > kk(i)
%
%       RR = R + K
%
%       U(i) =  /  0, -kk(i) <= R(i) <= kk(i)
%               \  1, otherwise
%
%       DDL(i) = /  1, dd(i) = 1
%                \  0, otherwise
%
%       DDQ(i) = /  1, dd(i) = 2
%                \  0, otherwise
%
%       Dl = diag(mm) * diag(U) * diag(DDL)
%       Dq = diag(mm) * diag(U) * diag(DDQ)
%
%       w = (Dl + Dq * diag(RR)) * RR
%
%       f_u(x, CP) = 1/2 * w'*H*w + Cw'*w
%
%   See also OPT_MODEL, PARAMS_LEGACY_COST, EVAL_LEGACY_COST.

%   MATPOWER
%   Copyright (c) 2008-2020, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

if iscell(idx)
    cp = varargin{1};
    args = varargin(2:end);
else                            %% simple named set
    cp = idx;
    args = varargin;
    idx = {};
end

if isempty(args)
    varsets = {};
else
    varsets = args{1};
end

%% convert varsets from cell to struct array if necessary
varsets = om.varsets_cell2struct(varsets);
nv = om.varsets_len(varsets);   %% number of variables

if isfield(cp, 'N')
    [nw, nx] = size(cp.N);
else
    nw = length(cp.Cw);
    nx = nw;
    cp.N = speye(nw, nx);
end

%% check sizes
if nx ~= nv
    if nw == 0
        cp.N = sparse(nw, nx);
    else
        error('@opt_model/add_legacy_cost: number of columns in N (%d x %d) does not match\nnumber of variables (%d)\n', nw, nx, nv);
    end
end
if size(cp.Cw, 1) ~= nw
    error('@opt_model/add_legacy_cost: number of rows of Cw (%d x %d) and N (%d x %d) must match\n', size(cp.Cw), nw, nx);
end
if isfield(cp, 'H') && (size(cp.H, 1) ~= nw || size(cp.H, 2) ~= nw)
    error('@opt_model/add_legacy_cost: both dimensions of H (%d x %d) must match the number of rows in N (%d x %d)\n', size(cp.H), nw, nx);
end
if isfield(cp, 'dd') && size(cp.dd, 1) ~= nw
    error('@opt_model/add_legacy_cost: number of rows of dd (%d x %d) and N (%d x %d) must match\n', size(cp.dd), nw, nx);
end
if isfield(cp, 'rh') && size(cp.rh, 1) ~= nw
    error('@opt_model/add_legacy_cost: number of rows of rh (%d x %d) and N (%d x %d) must match\n', size(cp.rh), nw, nx);
end
if isfield(cp, 'kk') && size(cp.kk, 1) ~= nw
    error('@opt_model/add_legacy_cost: number of rows of kk (%d x %d) and N (%d x %d) must match\n', size(cp.kk), nw, nx);
end
if isfield(cp, 'mm') && size(cp.mm, 1) ~= nw
    error('@opt_model/add_legacy_cost: number of rows of mm (%d x %d) and N (%d x %d) must match\n', size(cp.mm), nw, nx);
end

%% add the legacy cost set
om.add_named_set('cost', name, idx, nw, cp, varsets);


function Y = subs(S,old,new)
    % Symbolic substitution.  Also used to evaluate expressions numerically.
    %   SUBS(S,OLD,NEW) replaces OLD with NEW in the symbolic expression S.
    %   OLD is a symbolic variable, a string representing a variable name, or
    %   a symbolic expression. NEW is a symbolic or numeric variable
    %   or expression.  That is, SUBS(S,OLD,NEW) evaluates S at OLD = NEW.
    %
    %   SUBS(S,VALUES), where VALUES is a STRUCT, replaces the symbolic
    %   variables in S which are field names in VALUES by the corresponding
    %   entries of the struct.
    %
    %
    %   If OLD and NEW are vectors or cell arrays of the same size, each element
    %   of OLD is replaced by the corresponding element of NEW.  If S and OLD
    %   are scalars and NEW is a vector or cell array, the scalars are expanded
    %   to produce an array result.  If NEW is a cell array of numeric matrices,
    %   the substitutions are performed elementwise.
    %
    %   Examples:
    %     Single input:
    %       Suppose
    %          y = exp(-a*t)*C1
    %       After that, set a = 980 and C1 = 3 in the workspace.
    %       Then the statement
    %          subs(y)
    %       produces
    %          ans = 3*exp(-980*t)
    %
    %     Single Substitution:
    %       subs(a+b,a,4) returns 4+b.
    %       subs(a*b^2, a*b, 5) returns 5*b.
    %
    %     Multiple Substitutions:
    %       subs(cos(a)+sin(b),{a,b},[sym('alpha'),2]) or
    %       subs(cos(a)+sin(b),{a,b},{sym('alpha'),2}) returns
    %       cos(alpha)+sin(2)
    %
    %     Scalar Expansion Case:
    %       subs(exp(a*t),'a',-magic(2)) returns
    %
    %       [   exp(-t), exp(-3*t)]
    %       [ exp(-4*t), exp(-2*t)]
    %
    %     Multiple Scalar Expansion:
    %       subs(x*y,{x,y},{[0 1;-1 0],[1 -1;-2 1]}) returns
    %         0  -1
    %         2   0
    %
    %   See also SYM/SUBEXPR, SYM/VPA, SYM/DOUBLE.

    % Convert inputs to SymExpression
    S = SymExpression(S);

    narginchk(2,3);

    if nargin == 2
        assert(isstruct(old),'SymExpression:invalidInputArgs',...
            'The second argument must be a struct if there are two input arguments.');
        srule = SymExpression(old);

        sstr = ['ReplaceAll[' S.s ',' srule.s ']'];

        % create a new object with the evaluated string
        Y = SymExpression(sstr);
    elseif nargin == 3

        if iscell(old) && iscell(new)
            old_s = cellfun(@(x)SymExpression(x),old,'UniformOutput',false);
            new_s = cellfun(@(x)SymExpression(x),new,'UniformOutput',false);

            rarray = cellfun(@(x,y)[x.s '->' y.s], old_s, new_s ,'UniformOutput',false);
            srule = SymExpression(['<| ', ...
                implode(rarray,', '), ...
                ' |>']);
        elseif ischar(old)
            old_s = SymExpression(old);
            new_s = SymExpression(new);
            srule = SymExpression(['<| ', ...
                old_s.s, '->', new_s.s, ...
                ' |>']);
        elseif isa(old,'SymExpression')
            siz_o = size(old);
            siz_n = size(new);

            assert(prod(siz_o) == prod(siz_n),...
                'The sizes of the second and third argument must be the same.');
            old_s = flatten(SymExpression(old));
            new_s = flatten(SymExpression(new));
            rarray = arrayfun(@(x,y)['First@' x.s '->First@' y.s], old_s, new_s ,'UniformOutput',false);
            srule = SymExpression(['<| ', ...
                implode(rarray,', '), ...
                ' |>']);
        end

        sstr = ['ReplaceAll[' S.s ',' srule.s ']'];

        % create a new object with the evaluated string
        Y = SymExpression(sstr);
    end


function EEG = est_aamp(varargin)

% Obtain the instantaneous analytic amplitude within a given band of a collection of
% processes in EEG.CAT.srcdata. This uses the hilbert transform and EEGLAB's eegfilt().
%
% See Also: eegfilt(), hilbert(), hlp_aamp()
%
% References:
%
% [1] Mullen T (2010) The Source Information Flow Toolbox (SIFT):
%   Theoretical Handbook and User Manual.
%   Available at: http://www.sccn.ucsd.edu/wiki/SIFT/
%
%
% Author: Tim Mullen 2012, SCCN/INC, UCSD.
% Email:  tim@sccn.ucsd.edu

% This function is part of the Source Information Flow Toolbox (SIFT)
%
% 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 3 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

g = arg_define([0 1], varargin, ...
        arg_norep({'EEG'},mandatory),...
        arg({'ampband','AmplitudePassBand'},[80 150],[],'The [lo hi] pass-band to use for amplitude (Hz)','shape','row'), ...
        arg_subtoggle({'normalize','NormalizeData'},{'method', {'ensemble'}},@pre_normData,'Data normalization. Normalize analytic amplitude trials across time, ensemble, or both','cat','Normalization'), ...
        arg({'plot','PlotData'},false,[],'Plot amplitude envelope'), ...
        arg({'verb','Verbosity'},true,[],'Verbose output') ...
    );

% yeild EEG structure to workspace
data = hlp_splitstruct(g,{'EEG'});
arg_toworkspace(data);
clear data;

%% hilbert transform the data
AA = hlp_aamp(EEG, 'AmplitudePassBand', g.ampband, 'verb', g.verb);

% normalize analytic amplitude, if desired
if g.normalize.arg_selection
    AA = pre_normData('data',AA,g.normalize,'verb',g.verb);
end

% concatenate analytic amplitudes to end of dataset
EEG.CAT.srcdata = cat(1, EEG.CAT.srcdata, AA);

% update EEG datastructure to reflect new AA 'channels'
EEG.CAT.curComponentNames = EEG.CAT.curComponentNames(EEG.CAT.curComps);
EEG.data       = cat(1, EEG.data, AA);
EEG.CAT.curComps = [EEG.CAT.curComps EEG.CAT.curComps+EEG.CAT.nbchan];
EEG.nbchan     = 2*EEG.CAT.nbchan;
EEG.CAT.nbchan = 2*EEG.CAT.nbchan;

N = length(EEG.CAT.curComponentNames);
for k=1:N
    EEG.CAT.curComponentNames{k+N} = [EEG.CAT.curComponentNames{k} '_amp'];
end
% EEG.CAT.curComponentNames = cellstr(num2str(EEG.CAT.curComps'))';
N = length(EEG.chanlocs);
for k=1:N
    EEG.chanlocs(k+N) = EEG.chanlocs(k);
    EEG.chanlocs(k+N).labels = [EEG.chanlocs(k).labels ' amp'];
end

EEG.CAT.datamode = 'AnalyticAmplitude';
EEG.CAT.ampband = g.ampband;

if g.plot
    eegplot(EEG.CAT.srcdata,'srate',EEG.srate,'title',sprintf('AmplitudeModulation [%0.5g %0.5g] Hz',g.ampband(1),g.ampband(2)));
    ax = findobj(gcf,'tag','eegaxis');
    set(ax,'YTickLabel',flipud([EEG.CAT.curComponentNames,' ']'));
end


function model = rmSearchFit_oneGaussianNonlinear(model, data, params, wProcess, t)
% rmSearchFit_oneGaussianNonlinear - wrapper for 'fine' one Gaussian fit
%
% model = rmSearchFit_oneGaussianNonlinear(model, data, params, wProcess, t);
%
% 2008/01 SOD: split of from rmSearchFit.
% 2010/02 SOD: cleanup.
% 2015/02 JW: branched from rmSearchFit_oneGaussian, now includes
%             non-linear model (see Kay et al, 2013, on Compressive
%             Spatial Summation)

% fminsearch options
searchOptions = params.analysis.fmins.options;
expandRange   = params.analysis.fmins.expandRange;

% convert to double just in case
params.analysis.X = double(params.analysis.X);
params.analysis.Y = double(params.analysis.Y);

params.analysis.allstimimages_unconvolved = double(params.analysis.allstimimages_unconvolved);
data = double(data);

% get starting upper and lower range and reset TolFun
% (raw rss computation (similar to norm) and TolFun adjustments)
model.s = model.s_major;
[range, TolFun] = rmSearchFit_range(params,model,data);

% GLU 2021-10-14: not sute if best option, but I am going to restrict here
%                 the exponent
%                 If we are here we know that we are fitting the nonlinear css
if params.analysis.fixcssexp ~= 0
   range.start(4,:) = params.analysis.fixcssexp * ones(size(range.start(4,:)));
   range.lower(4,:) = params.analysis.fixcssexp * ones(size(range.start(4,:)));;
   range.upper(4,:) = params.analysis.fixcssexp * ones(size(range.start(4,:)));;
end

% amount of negative fits
nNegFit  = 0;
vethresh = params.analysis.fmins.vethresh;
trends   = t.trends;
t_id     = t.dcid+1;

%-----------------------------------
% Go for each voxel
%-----------------------------------
progress = 0;tic;
for ii = 1:numel(wProcess),
    % progress monitor (10 dots)
    if floor(ii./numel(wProcess)*10)>progress,
        % print out estimated time left
        if progress==0,
            esttime = toc.*10;
            if floor(esttime./3600)>0,
                fprintf(1,'[%s]:Estimated processing time: %d voxels: %d hours.\n',...
                    mfilename,numel(wProcess),ceil(esttime./3600));
            else
                fprintf(1,'[%s]:Estimated processing time: %d voxels: %d minutes.\n',...
                    mfilename,numel(wProcess),ceil(esttime./60));
            end;
            fprintf(1,'[%s]:Nonlinear optimization (x,y,sigma, exponent):',mfilename);
        end;
        fprintf(1,'.');drawnow;
        progress = progress + 1;
    end;

    % volume index
    vi = wProcess(ii);
    vData = data(:,ii);

    % reset tolFun: Precision of evaluation function.
    % We define RMS improvement relative to the initial raw 'no-fit' data
    % RMS. So, 1 means stop if there is less than 1% improvement on the fit:
    % searchOptions = optimset(searchOptions,'tolFun',optimget(params.analysis.fmins.options,'tolFun')./100.*rawrss);
    % optimset and optimget are a little slow so:
    searchOptions.TolFun = TolFun(ii);

    % actual fitting routine
    if searchOptions.MaxIter>0
        outParams = ...
            fmincon(@(x) rmModelSearchFit_oneGaussianNonlinear(x,vData,...
                                                            params.analysis.X,...
                                                            params.analysis.Y,...
                                                            params.analysis.allstimimages_unconvolved,...
                                                            params.analysis.Hrf,...
                                                            params.analysis.scans,...
                                                            trends),...
                     range.start(:,vi),...  % X0. Vector of 5 [x,y,sigma,exp,?]
                     [],[], ...             % A, B
                     [],[], ...             % Aeq, Beq
                     range.lower(:,vi), ... % LB
                     range.upper(:,vi),...  % UB
                     @(x) distanceCon(x,range.start(:,vi),range.step(:,vi).*expandRange),... % NONLCON
                     searchOptions); % OPTIONS
    else
        outParams = range.start(:,vi);
    end

    %[ outParams range.lower(:,vi) range.start(:,vi) range.upper(:,vi)]

    % make RF, prediction and get rss,b
    Xv = params.analysis.X-outParams(1);
    Yv = params.analysis.Y-outParams(2);
    n  = outParams(4);
    rf = exp( (Yv.*Yv + Xv.*Xv) ./ (-2.*(outParams(3).^2)) );
    pred = (params.analysis.allstimimages_unconvolved * rf).^ n;
    for scan = 1:numel(params.stim)
        inds = params.analysis.scans == scan;
        pred(inds) = filter(params.analysis.Hrf{scan}, 1, pred(inds));
    end

    X  = [pred trends];
    b    = pinv(X)*vData;
    rss  = norm(vData-X*b).^2;

    % store results only if the first beta is positive, somehow fmincon
    % outputs negative fits. If the fit is negative keep old (grid) fit. We
    % do adjust the rss, so it won't be accidentally counted as a 'good'
    % fit.
    if b(1)>0,
        model.x0(vi)         = outParams(1);
        model.y0(vi)         = outParams(2);
        model.s(vi)          = outParams(3);
        model.s_major(vi)    = outParams(3);
        model.s_minor(vi)    = outParams(3);
        model.s_theta(vi)    = 0;
        model.exponent(vi)   = outParams(4);
        model.rss(vi)        = rss;
        model.b([1 t_id],vi) = b;
    else
        % change the percent variance explained to be just under the
        % current vethresh. So it counts as a 'coarse'-fit but can still be
        % included in later 'fine'-fits
        model.rss(vi)  = (1-max((vethresh-0.01),0)).*model.rawrss(vi);
        nNegFit = nNegFit + 1;
    end
end

% end time monitor
et  = toc;
if floor(et/3600)>0,
    fprintf(1,'Done [%d hours].\n',ceil(et/3600));
else
    fprintf(1,'Done [%d minutes].\n',ceil(et/60));
end;
fprintf(1,'[%s]:Removed negative fits: %d (%.1f%%).\n',...
    mfilename,nNegFit,nNegFit./numel(wProcess).*100);
return;

%-----------------------------------
% make sure that the pRF can only be moved "step" away from original
% position "startParams" - for the one Gaussian model
function [C, Ceq]=distanceCon(x,startParams,step)
Ceq = [];
dist = x([1 2])-startParams([1 2]);
C = norm(dist) - step;
return;
%-----------------------------------


function planC = translateStruct(structNum,xyzT,structName,planC)
%
% function planC = translateStruct(structNum,xyzT,structName,planC)
%
% This function creates a new structure by translating structNum by amounts
% xT, yT and zT in x,y,z directions respectively. Note that xyzT = [xT yT zT].
% structName must be a string to name the new structure.
%
% Example:
%   planC = translateStruct(12,[-1 0 0],'moveStruct12');
%
% APA, 9/12/06
%
% LM DK compatible with CERR 3.0
%
% See also GETUNIFORMSTR MASKTOCERRSTRUCTURE
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

if ~exist('planC')

    global planC

end

indexS = planC{end};

%obtain scanNum associated to the structNum for CERR3

%scanNum = getAssociatedScan(planC{indexS.structures}(structNum).assocScanUID);

%scanNum is always 1 for CERR2

scanNum =  getStructureAssociatedScan(structNum, planC);

%obtain r,c,s coordinates of scan x,y,z vals

scanS = planC{indexS.scan}(scanNum);

[xUnifScanValsV, yUnifScanValsV, zUnifScanValsV] = getUniformScanXYZVals(scanS);

[rScanValsV, cScanValsV, sScanValsV] = xyztom(xUnifScanValsV, yUnifScanValsV, zUnifScanValsV,scanNum, planC, 1);

%obtain r,c,s coordinates of structure based on its associated scan

rcsStructValsV = getUniformStr(structNum);

scanUnifSiz = getUniformScanSize(scanS);

rcsStructValsV = find(rcsStructValsV);

[rStructValsV, cStructValsV, sStructValsV] = ind2sub(scanUnifSiz,rcsStructValsV);

%obtain x,y,z coordinates of voxels included within the structure

xStructValsV = xUnifScanValsV(cStructValsV);

yStructValsV = yUnifScanValsV(rStructValsV);

zStructValsV = zUnifScanValsV(sStructValsV);

%translate the x,y,z pints included within the structure by specified amount

xStructValsV = xStructValsV + xyzT(1);

yStructValsV = yStructValsV + xyzT(2);

zStructValsV = zStructValsV + xyzT(3);

%convert the translated x,y,z vals of structure to r,c,s of scanNum

[rStructValsV, cStructValsV, sStructValsV] = xyztom(xStructValsV, yStructValsV, zStructValsV,scanNum, planC, 1);

rStructValsV = round(rStructValsV);

rStructValsV = clip(rStructValsV,min(rScanValsV),max(rScanValsV),'limits');

cStructValsV = round(cStructValsV);

cStructValsV = clip(cStructValsV,min(cScanValsV),max(cScanValsV),'limits');

sStructValsV = round(sStructValsV);

sStructValsV = clip(sStructValsV,min(sScanValsV),max(sScanValsV),'limits');

%generate uniformized mask for this new structure

maskM = zeros(scanUnifSiz);

indicesWithinSkinV = sub2ind(scanUnifSiz,rStructValsV,cStructValsV,sStructValsV);

maskM(indicesWithinSkinV) = 1;

%generate contours on slices out of uniform mask and add to planC

planC = maskToCERRStructure(maskM, 1, scanNum, structName, planC);


function k = whiteKernDiagCompute(kern, x)

% WHITEKERNDIAGCOMPUTE Compute diagonal of WHITE kernel.
% FORMAT
% DESC computes the diagonal of the kernel matrix for the white noise kernel given a design matrix of inputs.
% ARG kern : the kernel structure for which the matrix is computed.
% ARG x : input data matrix in the form of a design matrix.
% RETURN k : a vector containing the diagonal of the kernel matrix
% computed at the given points.
%
% SEEALSO : whiteKernParamInit, kernDiagCompute, kernCreate, whiteKernCompute
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005, 2006

% KERN

k = repmat(kern.variance, size(x, 1), 1);


function [ode,alg] = dae(daefh, ...
  x_struct, z_struct, u_struct, p_struct, x_order, ...
  x, z, u, p, userdata)
% evaluate the system equations for the assigned variables

x = ocl.Variable.create(x_struct,x);
z = ocl.Variable.create(z_struct,z);
u = ocl.Variable.create(u_struct,u);
p = ocl.Variable.create(p_struct,p);

daehandler = ocl.DaeHandler(userdata);
daefh(daehandler,x,z,u,p);

nx = length(x_struct);
nz = length(z_struct);

ode = daehandler.getOde(nx, x_order);
alg = daehandler.getAlg(nz);


function [trans_head2mri] = fiff_read_coord_trans(transfile)
%
%  usage: [trans_head2mri] = fiff_read_coord_trans(transfile)
%
%  input:
%       transfile = name of transformation fif file (usually stored in
%       the subject's Freesurfer directory in /mri/T1-neuromag/sets).
%
%  output:
%       trans_head2mri = transformation structure from head to MRI coordinate systems.
%
%                    Note: the inverse transformation, from MRI to head coordinate systems
%                              can be obtained by just taking the inverse:
%                                   trans_mri2head.from=5; trans_mri2head.to=4;
%                                   trans_mri2head.trans=inv(trans_head2mri.trans);
%
%  author:  Rey Ramirez  email: rrramir@uw.edu

FIFF = fiff_define_constants;
[fid,~,dir] = fiff_open(transfile);
a = find([dir.kind] == FIFF.FIFF_COORD_TRANS);
pos = dir(a(1)).pos;
tag = fiff_read_tag(fid,pos);
trans_head2mri = tag.data;


% reads multi-channel recording file to a matrix
% function .lfp] = function readmulti(fname,numchannel,chselect)
% last argument is optional (if omitted, it will read all the
% channels

function .lfp] = readmulti_ss(fname,numchannel,chselect)

if nargin == 2
  datafile = fopen(fname,'r');
 .lfp = fread(datafile,[numchannel,inf],'int16');
  fclose(datafile);
 .lfp =.lfp';
  return
end

if nargin == 3

  % the real buffer will be buffersize * numch * 2 bytes
  % (short = 2bytes)

  buffersize = 4096;

  % get file size, and calculate the number of samples per channel
  fileinfo = dir(fname);
  N_EL = ceil(fileinfo(1).bytes / 2 / numchannel);

  datafile = fopen(fname,'r');

  mmm = sprintf('%d elements',N_EL);
%  disp(mmm);

 .lfp=zeros(length(chselect),N_EL);
  N_EL=0;
  numelm=0;
  while ~feof(datafile),
    [data,count] = fread(datafile,[numchannel,buffersize],'int16');
    numelm = count/numchannel;
    if numelm>0 % Kenji modified 061009.Otherwise if numelm == 0 an error occur.
       .lfp(:,N_EL+1:N_EL+numelm) = data(chselect,:);
        N_EL = N_EL+numelm;
    end % Kenji modified 061009.Otherwise if numelm == 0 an error occur.

end
fclose(datafile);

end

eeg =.lfp';


function out = isinf(f)
%ISINF   Test if a TRIGTECH is unbounded.
%   ISINF(F) returns TRUE if F has any infinite values and FALSE otherwise.
%
% See also ISFINITE, ISNAN.

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

% Check if any values are infinite:
out = any(isinf(f.values(:)));

end


function modifieddq = satdq(dqlimit,q)
modifieddq = q;
count = length(q);
for i=1:count
    if modifieddq(i)<-dqlimit(i)
        modifieddq(i) = -dqlimit(i);
    end
    if modifieddq(i)> dqlimit(i)
        modifieddq(i) = dqlimit(i);
    end
end
end

github-repos/MATLAB/xuhuairuogu-V-REP-Simulation-Projects/V-REP-Simulation-Projects-841b944af4ea3a8fb250578d36434515f577f411/admittance control(adapted from an example in the book--A Systematic Approach to Learning Robot Programming with ROS)/iiwa14_kinematics/satdq.m


function id = phWindowIndices(ph,phWindow)
%
% id = phWindowIndices(ph,phWindow)
%
% Returns indices of vector ph within phWindow
%
% if phWindow(1)<phWindow(2) returns phWindow(1) <= ph <= phWindow(2)
% if phWindow(1)>phWindow(2) returns ph >= phWindow(1) or ph <= phWindow(2)
%
% djh, 7/98

if diff(phWindow)>0
  id = find(ph>=phWindow(1) & ph<=phWindow(2));
else
  id = find(ph>=phWindow(1) | ph<=phWindow(2));
end


% The mutation function:
function nnum = SMutateBit(num)

% Selecting a position:
pos = ceil(rand*32);

% Flipping that bit:
change = bitset(0,pos);
nnum = bitxor(num,change);


function [exploration,sws,rem] = BrainStates(s,t,f,q,emg,varargin)

%BrainStates - Determine brain state using LFP, EMG and movement.
%
%  USAGE
%
%    [exploration,sws,rem] = BrainStates(s,t,f,q,emg,<options>)
%
%    s              spectrogram
%    t              time bins for spectrogram
%    f              frequency bins for spectrogram
%    q              'quiescence' vector, obtained using QuietPeriods (see NOTE)
%    emg            electromyogram (pass [] if missing)
%    <options>      optional list of property-value pairs (see table below)
%
%    =========================================================================
%     Properties    Values
%    -------------------------------------------------------------------------
%     'nClusters'   number of clusters for K-means clustering (default = 2)
%     'method'      see below (default = 'hippocampus')
%     'nComponents' number of principal components (for 'pca' method only)
%                   (default = automatically computed to account for 85% of
%                   the variance)
%     'show'        plot K-means clustering in feature space ('kmeans'),
%                   clusters on spectrogram ('clusters') or both ('all')
%                   (default = 'none')
%    =========================================================================
%
%  METHODS
%
%    Option 'method' can take several possible values:
%
%     'pca'         PCA on the spectrogram
%     'hippocampus' theta / delta ratio
%     'amygdala'    gamma / low ratio
%     'cortex'      heuristic ratios described in Gervasoni et al. (2004)
%
%  OUTPUT
%
%    exploration    at each time t, whether the rat was exploring
%    sws            at each time t, whether the rat was in slow wave sleep
%    rem            at each time t, whether the rat was in rapid eye movement sleep
%
%  NOTE
%
%    Quiescence q is a time series of boolean values specifying for each
%    timestamp whether the animal was quiet (as determined by QuietPeriods).
%
%  SEE
%
%    See also QuietPeriods, SpectrogramBands.

% Copyright (C) 2008-2014 by Michaël Zugaro, Gabrielle Girardeau
%
% 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 3 of the License, or
% (at your option) any later version.

% Defaults
nClusters = 2;
window = 5*1250;
show = 'none';
nComponents = 0;
method = 'hippocampus';

% Check number of parameters
if nargin < 5,
	error('Incorrect number of parameters (type ''help BrainStates'' for details).');
end

if mod(length(varargin),2) ~= 0,
  error('Incorrect number of parameters (type ''help BrainStates'' for details).');
end

% Parse options
for i = 1:2:length(varargin),
	if ~ischar(varargin{i}),
		error(['Parameter ' num2str(i) ' is not a property (type ''help BrainStates'' for details).']);
	end
	switch(lower(varargin{i})),
		case 'nclusters',
			nClusters = varargin{i+1};
			if ~isiscalar(nClusters,'>0'),
				error('Incorrect value for property ''nClusters'' (type ''help BrainStates'' for details).');
			end
		case 'method',
			method = lower(varargin{i+1});
			% 'direct' and 'ratios' are for backward compatibility (deprecated)
			if ~isstring_FMAT(method,'pca','hippocampus','cortex','amygdala','direct','ratios'),
				error('Incorrect value for property ''method'' (type ''help BrainStates'' for details).');
			end
		case 'ncomponents',
			nComponents = varargin{i+1};
			if ~isiscalar(nComponents,'>0'),
				error('Incorrect value for property ''nComponents'' (type ''help BrainStates'' for details).');
			end
		case 'show',
			show = lower(varargin{i+1});
			if ~isstring_FMAT(show,'kmeans','clusters','all','none'),
				error('Incorrect value for property ''show'' (type ''help BrainStates'' for details).');
			end
		otherwise,
			error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help BrainStates'' for details).']);
	end
end

% Compute and interpolate EMG and quiescence at spectrogram timestamps
emg0 = [];
if ~isempty(emg),
	emg0 = Interpolate(emg,t,'trim','off');
	emg0 = Smooth(abs(emg0(:,2)),5);
end
q0 = [];
if all(q(:,2)==0|q(:,2)==1),
	q0 = Interpolate(double(q),t,'trim','off');
	q0 = round(q0(:,2));
else
	q0 = Interpolate(q,t,'trim','off');
	q0 = q0(:,2);
end

% No movement info => undetermined
usable = ~isnan(q0);

% Exploration corresponds to movement periods
exploration = zeros(size(t));
exploration(usable) = ~q0(usable);

% Sleep/rest corresponds to quiescence
sleep = zeros(size(t));
sleep(usable) = q0(usable);
sleep = logical(sleep);

% Get ratios
bands = SpectrogramBands(s,f);

% Determine features for automatic data clustering
switch(method),
	case 'pca',
		% Compute PCA on spectrogram and reduce dimensionality
		S = s(:,sleep)';
		S(:,f>30) = 0;
		[eigenvectors,projected,lambda] = princomp(S,'econ');
		if nComponents == 0,
			nComponents = find(cumsum(lambda)/sum(lambda)>0.85);
			nComponents = nComponents(1);
		end
		eigenvectors = eigenvectors(:,1:nComponents);
		lambda = lambda(1:nComponents);
		projected = projected(:,1:nComponents);
		features = projected;
	case {'hippocampus','direct'},
		% Use theta/delta ratio
		features = bands.ratios.hippocampus(sleep);
	case {'cortex','ratios'},
		% Use heuristic ratios of Gervasoni et al. (2004)
		features = bands.ratios.cortex(sleep);
	case 'amygdala',
		% Use gamma / low ratio
		features = bands.ratios.amygdala(sleep);
end

% Add EMG to feature list
if ~isempty(emg0),
	features = [features emg0(sleep)];
end

% Normalize columns (we need this because K-means clustering uses Euclidean
% distances)
features = zscore(features);

% Cluster (K-means)
cluster = kmeans(features,nClusters);

% Identify clusters
sws = logical(zeros(size(t)));
rem = logical(zeros(size(t)));
% 1) Measure mean ratio for each state
switch(method),
    case 'amygdala',
        ratio = bands.ratios.amygdala(sleep);
    otherwise,
        ratio = bands.ratios.hippocampus(sleep);
end
for i = 1:nClusters,
	meanRatio(i) = mean(ratio(cluster==i));
end
% 2) REM is the quiet state with highest mean ratio
[~,i] = sort(meanRatio(:),1,'descend');
h = i(1);
rem(sleep) = cluster==h;
highest = meanRatio(h);
% 3) SWS is the quiet state with lowest mean ratio
[~,i] = sort(meanRatio(:),1,'ascend');
l = i(1);
sws(sleep) = cluster==l;
lowest = meanRatio(l);
% 4) REM must have a ratio at least twice as high as SWS
if highest < 2*lowest,
	sws(sleep) = 1;
	rem(sleep) = 0;
end

% Show K-means clustering in feature space
if strcmp(show,'kmeans') | strcmp(show,'all'),
	figure;
	% Determine number N of subplots (depends on number of principal components kept; clip at 15)
	n = size(features,2);
	N = min([n*(n-1)/2 21]);
	if N == 0, N = 1; end
	m0 = round(sqrt(N));
	n0 = ceil(N/m0);
	colors = jet(nComponents);
	if strcmp(method,'pca'),
		% Plot principal components
		subplot(m0+1,1,1);hold on;
		l = 'h = legend(';
		for i = 1:nComponents,
			plot(f,eigenvectors(:,i),'color',colors(i,:));
			l = [l '''' int2str(i) ''','];
		end
		l = [l(1:end-1) ',''location'',''northoutside'',''orientation'',''horizontal'');'];
		eval(l);
		set(h,'color',[1 1 1]*.7);
		shift = 1;
	else
		shift = 0;
	end
	% List pairs of principal component IDs to display in successive 2D projections
	colors = jet(nClusters);
	if N > 1,
		feature1 = [];
		feature2 = [];
		i = 1;
		while length(feature1) < N,
			feature1 = [feature1 repmat(i,1,n-i)];
			feature2 = [feature2 i+1:n];
			i = i+1;
		end
		% Plot 2D projections of data in PC space, colored by cluster ID
		for i = 1:N,
			subplot(m0+shift,n0,i+shift*n0);hold on;
			for j = 1:size(features,1),
				plot(features(j,feature1(i)),features(j,feature2(i)),'.','color',colors(cluster(j),:));
			end
			xlabel([int2str(feature1(i)) ' vs ' int2str(feature2(i))]);
		end
	else
		subplot(shift+1,1,shift+1);hold on;
		r = rand(size(features));
		for j = 1:size(features,1),
			plot(r(j),features(j),'.','color',colors(cluster(j),:));
		end
	end
end

%%%%%PLOT%%%%%%

% Redefine ratios for plotting
switch(method)
  case 'amygdala'
    ratio=bands.ratios.amygdala;
  case {'hippocampus','pca'}
    ratio=bands.ratios.hippocampus;
  case 'cortex'
    ratio=bands.ratios.cortex;
end

% Show clusters on spectrogram
if strcmp(show,'clusters') | strcmp(show,'all'),
	figure;
	% 1) Plot spectrogram and ratio
	subplot(2,1,1);hold on;
	PlotColorMap(log(s),1,'cutoffs',[0 12],'x',t,'y',f);
	plot(t,ratio*10,'k');
	l = ['h = legend(''' method ' ratio'',''q'''];
	ylim([0 30]);
	yLim = ylim;
	dy = yLim(2) - yLim(1);
	y0 = yLim(1);
	% ... quiescence...
	plot(t,5*ZeroToOne(q0)+y0+0.5*dy,'b');
	% ... and EMG
	if ~isempty(emg0),
		plot(t,ZeroToOne(emg0)*5+y0+0.65*dy,'r');
		l = [l ',''emg'''];
	end
	l = [l ');'];
	eval(l);
	set(h,'color',[1 1 1]);
	xlim([t(1) t(end)]);
	% 2) Plot spectrogram and clusters
	subplot(2,1,2);hold on;
	PlotColorMap(log(s),1,'cutoffs',[0 12],'x',t,'y',f);
	ylim([0 30]);
	l = 'h = legend(';
	yLim = ylim;
	dy = yLim(2) - yLim(1);
	y0 = yLim(1);
	% Plot clustering output
	c = nan(size(t));
	c(sleep) = cluster-1;
	plot(t,5*ZeroToOne(c)+y0+0.35*dy,'k');
	l = [l '''cluster'',''location'',''north'',''orientation'',''horizontal'');'];
	eval(l);
	% Show SWS/REM
	if ~isempty(sws),
		z = nan(size(t));
		z(sws) = t(sws);
		plot(z,15*~isnan(z),'b','linewidth',5);
	end
	if ~isempty(rem),
		z = nan(size(t));
		z(rem) = t(rem);
		plot(z,15*~isnan(z),'r','linewidth',5);
	end
	xlim([t(1) t(end)]);
	set(h,'color',[1 1 1]);
end


function [G, ind] = subGrid(G,q,epsilon,varargin)
% sub-SO3Grid as epsilon neigborhood of a node
%
% Syntax
%   G = subGrid(G,midpoint,radius)
%
% Input
%  G        - @SO3Grid
%  midpoint - @quaternion
%  radius   - double
%
% Output
%  G - SO3Grid
%
% See also
%  SO3Grid/find S2Grid/subGrid

if nargin >= 3
  ind = find(G,q,epsilon,varargin{:});
  ind = any(ind,2);
elseif islogical(q)
  ind = q;
else
  ind = false(length(G),1);
  ind(q) = true;
end

G.a = G.a(ind);
G.b = G.b(ind);
G.c = G.c(ind);
G.d = G.d(ind);
G.i = G.i(ind);

G.gamma = subGrid(G.gamma,ind);
G.alphabeta  = subGrid(G.alphabeta,GridLength(G.gamma)>0);
G.gamma(GridLength(G.gamma)==0) = [];


I = imreadRGB(fullfile('birds.jpg'));
imsz = [size(I,1), size(I,2)];

tic;
[P, S] = getProposals(I, net, param);
res = propOpt(P, S, param);

% scale bboxes to full size
res = bsxfun(@times, res, imsz([2 1 2 1])');

% optional window refining process
resRefine = refineWin(I, res, net, param);
toc

subplot(1,2,1)
imshow(I)
for i = 1:size(res,2)
    rect = res(:,i);
    rect(3:4) = rect(3:4)-rect(1:2) +1;
    rectangle('Position',rect,'linewidth',2,'edgecolor',[1 0 0]);
end
title('W/O Window Refining');

subplot(1,2,2)

imshow(I)
for i = 1:size(resRefine,2)
    rect = resRefine(:,i);
    rect(3:4) = rect(3:4)-rect(1:2) +1;
    rectangle('Position',rect,'linewidth',2,'edgecolor',[1 0 0]);
end
title(sprintf('With Window Refining\n for Small Objects'))


function predictAllRF_Aerts(pathRF)

startpath = pwd;

cd(pathRF), load('training'), load('testing')
nameOutcomes = fieldnames(training.outcomes); nOutcomes = numel(nameOutcomes);
fSetNames = {'PETsign','CTsign','CTorigsign'}; nFset = numel(fSetNames); % The two sets tested for the radiomic signature

for o = 1:nOutcomes
    if strcmp(nameOutcomes{o},'DeathSign')
        outcome = testing.outcomes.Death;
        time = testing.timeToEvents.Death;
    else
        outcome = testing.outcomes.(nameOutcomes{o});
        time = testing.timeToEvents.(nameOutcomes{o});
    end
    censoring = 1 - outcome;
    for f = 1:nFset
        results = struct;
        RF = load(['RF_',[fSetNames{f},'Clinic'],'_',nameOutcomes{o}]); RF = struct2cell(RF); RF = RF{1};
        indClinic = training.clinical.bestAdd.(nameOutcomes{o}).(fSetNames{f});
        text = testing.textures.(nameOutcomes{o}).(fSetNames{f}); nText = size(text,2);
        tableTest = [text,testing.clinical.table(:,indClinic)];
        [prob] = predictRF(tableTest,RF);
        results.probResponse = prob;
        [AUC,sensitivity,specificity,accuracy] = calcPerformMetrics(prob,outcome,0.5);
        CI = calcCI(prob,time,censoring);
        results.AUC = AUC; results.Sensitivity = sensitivity; results.Specificity = specificity; results.Accuracy = accuracy;
        results.CI = CI;
        save(['testResultsRF_',[fSetNames{f},'Clinic'],'_',nameOutcomes{o}],'results'), clear results
    end
end

cd(startpath)
end


function b = back1(engine, bfuture, f, t)

if t ~= 1
  error('mixed up time stamps')
end
bnet = bnet_from_engine(engine);
ss = bnet.nnodes_per_slice;

int = engine.interface;
D = engine.in_clq; % from J2
C = engine.int_clq1; % from J1
phiD = marginalize_pot(bfuture.clpot{D}, int, engine.maximize);
phiC = marginalize_pot(f.clpot{C}, int, engine.maximize);
ratio = divide_by_pot(phiD, phiC);
f.clpot{C} = multiply_by_pot(f.clpot{C}, ratio);

[b.clpot, seppot] = distribute_evidence(engine.jtree_engine1, f.clpot, f.seppot);
for c=1:length(b.clpot)
  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
end
b.t = t;


%% subfunction: set slice timing related info
function [h, hdr] = sliceTiming(h, hdr)
s = h{1};
TR = tryGetField(s, 'RepetitionTime'); % in ms
if isempty(TR), TR = tryGetField(s, 'TemporalResolution'); end
if isempty(TR), return; end
hdr.pixdim(5) = TR / 1000;
hdr.xyzt_units = 8; % seconds
if hdr.dim(5)<3 || tryGetField(s, 'isDTI', 0) || ...
        strncmp(tryGetField(s, 'MRAcquisitionType'), '3D', 2)
    return; % skip 3D, DTI, fieldmap, short EPI etc
end

nSL = hdr.dim(4);
delay = asc_header(s, 'lDelayTimeInTR', 0)/1000; % in ms now
if delay ~= 0, h{1}.DelayTimeInTR = delay; end
TA = TR - delay;

% Siemens mosaic
t = csa_header(s, 'MosaicRefAcqTimes'); % in ms
if ~isempty(t) && isfield(s, 'LastFile') && max(t)-min(t)>TA % MB wrong vol 1
    try t = mb_slicetiming(s, TA); end %#ok<*TRYNC>
end

if isempty(t) && strncmpi(s.Manufacturer, 'UIH', 3)
    t = zeros(nSL, 1);
    if isfield(s, 'MRVFrameSequence') % mosaic
        for j = 1:nSL
            item = sprintf('Item_%g', j);
            str = s.MRVFrameSequence.(item).AcquisitionDateTime;
            t(j) = datenum(str, 'yyyymmddHHMMSS.fff');
        end
    else
        dict = dicm_dict('', 'AcquisitionDateTime');
        for j = 1:nSL
            s1 = dicm_hdr(h{j}.Filename, dict);
            t(j) = datenum(s1.AcquisitionDateTime, 'yyyymmddHHMMSS.fff');
        end
    end
    t = (t - min(t)) * 24 * 3600 * 1000; % day to ms
end

if isempty(t) && any(isfield(s, {'TriggerTime' 'RTIA_timer'})) % GE
    ind = numel(h) + (1-nSL:0); % seen problem for 1st vol, so use last vol
    t = cellfun(@(c)tryGetField(c, 'TriggerTime', 0), h(ind));
    if all(diff(t)==0), t = cellfun(@(c)tryGetField(c, 'RTIA_timer', 0), h(ind)); end
    if all(diff(t)==0), t = [];
    else
        t = t - min(t);
        ma = max(t) / TA;
        if ma>1, t = t / 10; % was ms*10, old dicom
        elseif ma<1e-3, t = t * 1000; % was sec, new dicom?
        end
    end
end

if isempty(t) && isfield(s, 'ProtocolDataBlock') && ...
        isfield(s.ProtocolDataBlock, 'SLICEORDER') % GE with invalid RTIA_timer
    SliceOrder = s.ProtocolDataBlock.SLICEORDER;
    t = (0:nSL-1)' * TA/nSL;
    if strcmp(SliceOrder, '1') % 0/1: sequential/interleaved based on limited data
        t([1:2:nSL 2:2:nSL]) = t;
    elseif ~strcmp(SliceOrder, '0')
        errorLog(['Unknown SLICEORDER (' SliceOrder ') for ' s.Filename]);
        return;
    end
end

% Siemens multiframe: read TimeAfterStart from last file
if isempty(t) && tryGetField(s, 'NumberOfFrames', 1)>1 &&  ...
        ~isempty(csa_header(s, 'TimeAfterStart'))
    % Use TimeAfterStart, not FrameAcquisitionDatetime. See
    % https://github.com/rordenlab/dcm2niix/issues/240#issuecomment-433036901
    % s2 = struct('FrameAcquisitionDatetime', {cell(nSL,1)});
    % s2 = dicm_hdr(h{end}, s2, 1:nSL); % avoid 1st volume
    % t = datenum(s2.FrameAcquisitionDatetime, 'yyyymmddHHMMSS.fff');
    % t = (t - min(t)) * 24 * 3600 * 1000; % day to ms
    s2 = struct('TimeAfterStart', nan(1, nSL));
    s2 = dicm_hdr(h{end}, s2, 1:nSL); % avoid 1st volume
    t = s2.TimeAfterStart; % in secs
    t = (t - min(t)) * 1000;
end

% Get slice timing for non-mosaic Siemens file. Could remove Manufacturer
% check, but GE/Philips AcquisitionTime seems useless
if isempty(t) && ~tryGetField(s, 'isMos', 0) && strncmpi(s.Manufacturer, 'SIEMENS', 7)
    dict = dicm_dict('', {'AcquisitionDateTime' 'AcquisitionDate' 'AcquisitionTime'});
    t = zeros(nSL, 1);
    for j = 1:nSL
        s1 = dicm_hdr(h{j}.Filename, dict);
        try str = s1.AcquisitionDateTime;
        catch
            try str = [s1.AcquisitionDate s1.AcquisitionTime];
            catch, t = []; break;
            end
        end
        t(j) = datenum(str, 'yyyymmddHHMMSS.fff');
    end
    t = (t - min(t)) * 24 * 3600 * 1000; % day to ms
end

if isempty(t) % non-mosaic Siemens: create 't' based on ucMode
    ucMode = asc_header(s, 'sSliceArray.ucMode'); % 1/2/4: Asc/Desc/Inter
    if isempty(ucMode), return; end
    t = (0:nSL-1)' * TA/nSL;
    if ucMode==2
        t = t(nSL:-1:1);
    elseif ucMode==4
        if mod(nSL,2), t([1:2:nSL 2:2:nSL]) = t;
        else, t([2:2:nSL 1:2:nSL]) = t;
        end
    end
    if asc_header(s, 'sSliceArray.ucImageNumb'), t = t(nSL:-1:1); end % rev-num
end

if numel(t)<2, return; end
t = t - min(t); % it may be relative to 1st slice

t1 = sort(t);
if t1(1)==t1(2) || (t1(end)>TA), sc = 0; % no useful info, or bad timing MB
elseif t1(1) == t1(2), sc = 0; t1 = unique(t1); % was 7 for MB but error in FS
elseif isequal(t, t1), sc = 1; % ascending
elseif isequal(t, flip(t1)), sc = 2; % descending
elseif t(1)<t(3) % ascending interleaved
    if t(1)<t(2), sc = 3; % odd slices first
    else, sc = 5; % Siemens even number of slices
    end
elseif t(1)>t(3) % descending interleaved
    if t(1)>t(2), sc = 4;
    else, sc = 6; % Siemens even number of slices
    end
else, sc = 0; % unlikely to reach
end

h{1}.SliceTiming = 0.5 - t/TR; % as for FSL custom timing
hdr.slice_code = sc;
hdr.slice_end = nSL-1; % 0-based, slice_start default to 0
hdr.slice_duration = min(diff(t1))/1000;


classdef prtClassMap < prtClass
 %prtClassMap  Maximum a Posteriori classifier
 %
 %    CLASSIFIER = prtClassMap returns a Maximum a Posteriori classifier
 %
 %    CLASSIFIER = prtClassMap(PROPERTY1, VALUE1, ...) constructs a
 %    prtClassMAP object CLASSIFIER with properties as specified by
 %    PROPERTY/VALUE pairs.
 %
 %    A prtClassMap object inherits all properties from the abstract class
 %    prtClass. In addition is has the following property:
 %
 %    rvs    - A prtRv object. This property describes the random variable
 %             model used for Maximum a Posteriori classification.
 %
 %    A prtClassMap object inherits inherits the TRAIN, RUN, CROSSVALIDATE
 %    and KFOLDS methods from prtClass.
 %
 %    Example:
 %
 %    Test` = prtDataGenUnimodal;       % Create some test and
 %    TrainingDataSet = prtDataGenUnimodal;   % training data
 %    classifier = prtClassMap;               % Create a classifier
 %    classifier = classifier.train(TrainingDataSet);    % Train
 %    classified = run(classifier, TestDataSet);         % Test
 %
 %    subplot(2,1,1); classifier.plot;  % Plot results
 %    subplot(2,1,2); prtScoreRoc(classified,TestDataSet);
 %    set(get(gca,'Children'), 'LineWidth',3)
 %
 %    See also prtClass, prtClassLogisticDiscriminant, prtClassBagging,
 %    prtClassMap, prtClassFld, prtClassBinaryToMaryOneVsAll, prtClassDlrt,
 %    prtClassPlsda, prtClassFld, prtClassRvm, prtClassGlrt,  prtClassSvm,
 %    prtClassTreeBaggingCap, prtClassKmsd, prtClassKnn

    properties (SetAccess=private)
        % Required by prtAction
        name = 'Maximum a Posteriori'   % Maximum a Posteriori
        nameAbbreviation = 'MAP'        % MAP
        isNativeMary = true;            % True
    end

    properties
        rvs = prtRvMvn; % Random variable object containing mean and variance
    end
    properties (Hidden)
        runLogLikelihoods = false
    end

    methods
        % Constructor
        function self = prtClassMap(varargin)

            self.classTrain = 'prtDataInterfaceCategoricalTargets';
            self.classRun = 'prtDataSetBase';
            self.classRunRetained = false;

            self = prtUtilAssignStringValuePairs(self,varargin{:});
        end
        % Set function
        function self = set.rvs(self,val)
            if ~(isa(val, 'prtRv') || isa(val, 'prtBrv'))
                error('prtClassMAP:rvs','Rvs parameter must be of class prtRv');
            else
                self.rvs = val;
            end
        end
    end

    methods (Access = protected, Hidden = true)

        function self = trainAction(self,ds)

            % Repmat the rv objects to get one for each class
            % The pattern of supplied RVs repeats, if 2 rvs are suplied for
            % a three class problem, the third class gets the same as class
            % 1, if there were a fourth class if would be the same as class
            % 2.
            self.rvs = repmat(self.rvs(:), (ds.nClasses - length(self.rvs)+1),1);
            self.rvs = self.rvs(1:ds.nClasses);

            % Get the ML estimates of the RV parameters for each class
            for iY = 1:ds.nClasses
                self.rvs(iY) = train(self.rvs(iY), ds.retainClassesByInd(iY));
            end
        end

        function ds = runAction(self,ds)

            % We call run for each RV
            % Typically this is the loglikelihood, but it might not be.
            logLikelihoods = zeros(ds.nObservations, length(self.rvs));
            for iY = 1:length(self.rvs)
                logLikelihoods(:,iY) = getObservations(run(self.rvs(iY), ds));
            end

            if ~self.runLogLikelihoods
                % If we don't want loglikelihoods transform them to
                % probabilities
                logLikelihoods = exp(bsxfun(@minus, logLikelihoods, prtUtilSumExp(logLikelihoods.').'));
            end

            if ~isa(ds,'prtDataSetClass')
                ds = ds.toPrtDataSetClassNoData();
            end
            ds.X = logLikelihoods;
        end

        function xOut = runActionFast(self,xIn,ds) %#ok<INUSD>

            logLikelihoods = zeros(size(xIn,1),length(self.rvs));
            for iY = 1:length(self.rvs)
                logLikelihoods(:,iY) = runFast(self.rvs(iY), xIn);
            end

            if ~self.runLogLikelihoods
                % If we don't want loglikelihoods transform them to
                % probabilities
                xOut = exp(bsxfun(@minus, logLikelihoods, prtUtilSumExp(logLikelihoods.').'));
            else
                xOut = logLikelihoods;
            end
        end
    end

end


%%%%% Author Muhammad Adil Farooqi %%%%
%%%%% E-mail: engr.adilfarooqi@gmail.com %%%%%
%%%%% OCR_ANN GUI %%%%%

%%
function varargout = OCR_ANN(varargin)
% OCR_ANN M-file for OCR_ANN.fig
%
%
%
% % Last Modified by GUIDE v2.5 28-May-2011 04:54:03

% Begin initialization code -
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @OCR_ANN_OpeningFcn, ...
                   'gui_OutputFcn',  @OCR_ANN_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

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

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

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

% Update handles structure
guidata(hObject, handles);

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

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

% Get default command line output from handles structure
varargout{1} = handles.output;

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

%%%% step# 01 Image Acquisition %%%%%%

clc;
[filename, pathname] = uigetfile({'*.jpg';'*.bmp';'*.gif';'*.*'}, 'Pick an Image File');
TestIm = imread([pathname,filename]);

axes(handles.axes1);
imshow(TestIm);

save('TestIm','TestIm');
clear all;

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

%%% step# 02 Preprocessing %%%%
load TestIm

%Convert to gray scale
if size(TestIm,3)==3 %RGB image
    TestIm = rgb2gray(TestIm);
end
%Convert to binary image
threshold = graythresh(TestIm);
TestIm =~im2bw(TestIm,threshold);

%Remove Salt and paper noise
TestIm = medfilt2(TestIm);

axes(handles.axes2);
imshow(TestIm)

save('TestIm','TestIm');
clc; clear all;

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

%%%% step# 03 Segmentation %%%%%
load TestIm

%Label and Count Connected components
[L Ne] = bwlabel(TestIm);
glyphs = []  %%%Initilize glyphs matrix

   for n=1:Ne
    [r c] =find(L==n);

    glyph = TestIm(min(r):max(r),min(c):max(c));

    glyph = imresize(glyph,[35 35]);

    % Again convert to binaray image
    glyph = double(glyph);
    thresh = graythresh(glyph);
    glyph = im2bw(glyph,thresh);

    glyphs = [glyphs glyph]

    axes(handles.axes3);
    imshow(glyph)

   end
   [m n] = size(glyphs)
   set(handles.text6,'string',n/35)
   save('glyphs','glyphs');
   clear all;
%%
% --- Executes on button press in axes4_pushbutton.
function axes4_pushbutton_Callback(hObject, eventdata, handles)
% hObject    handle to axes4_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

%%%% step# 04 Classification %%%%

load glyphs;
load net;
[r c] = size(glyphs);

    glyphsclass = [];performance = [];%%initilize matrix
    for n = 0:35:(c-35)
        glyph = glyphs(1:35,1+n:(n+35));
        glyph = mat2vect(glyph);
        [glyphclass,PF,AF,E,Perf] = sim(net,glyph);

        performance = [performance Perf]
        axes(handles.axes4)
       plot(performance,'-.b*','LineWidth',2,'MarkerSize',10)
        glyphsclass = [glyphsclass glyphclass]

    end

save('glyphsclass','glyphsclass');
clear all;

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

%%% step# 04 Output %%%%%

load glyphsclass

[r c] = size(glyphsclass);
alphabets = [];space = ' ';haroof = [] %%%initilize matrix

for n=1:c

    glyphclass = glyphsclass(1:r,n) %%% individiual alphabet

    [i j] = max(glyphclass); %%% alphabet???

if j==5 | j==6 | j== 7 | j== 8 | j==9 | j==10 | j==11 | j==12 | j==13 | j==14 | j==15 | j==16 |...
        j==17 | j==18 | j==19 |j==20 | j==21 | j==22 | j==23 | j==24 | j==25

if j==5
    alphabet = '0627'
    harf='alif      '
end
if j==6
    alphabet = '0628'
    harf = 'bay       ';
end

if j==7
    alphabet = '062D'
    harf = 'bari he   ';
end

if j==8
    alphabet = '062F'
    harf = 'dal       ';
end

if j==9
    alphabet = '0631'
    harf = 're        ';
end

if j==10
    alphabet = '0633'
    harf = 'sin       ';
end

if j==11
    alphabet = '0635'
    harf = 'suad      ';
end

if j==12
    alphabet = '0637';
    harf = 'toe       ';
end

if j==13
    alphabet = '0639';
    harf = 'ain       ';
end

if j==14
    alphabet = '0641';
    harf = 'fe        ';
end
if j==15
    alphabet = '0642';
    harf = 'qaf       ';
end
if j==16
    alphabet = '06A9';
    harf = 'kaf       ';
end

if j==17
    alphabet = '0644';
    harf = 'lam       ';
end
if j==18
    alphabet ='0645';
    harf = 'mim       ';
end
if j==19
    alphabet = '0646';
    harf = 'nun       ';
end

if j==20
    alphabet = '0648';
    harf = 'vao       ';
end
if j==21
    alphabet = '06C1';
    harf = 'choti he  ';
end
if j==22
    alphabet = '06BE';
    harf = 'DoCashmiHe';
end
if j==23
    alphabet = '0621';
    harf = 'hamzah    ';
end
if j==24
    alphabet = '06CC';
    harf = 'choti ye  ';
end
if j==25
    alphabet = '06D2';
    harf = 'bari ye   ';
end

alphabets = [alphabets space alphabet]
haroof = [haroof space harf]
end

%%%If glyph is Diacritics then...
[x y] = size(alphabets);
[m n] = size(haroof);

    if j==1 & alphabet=='0628' %%%%bay
        alphabets(1,(y-3):y) ='0628'%%%each alphabet is of length 4
        haroof(1,(n-9):n) = 'bay       '%%%each harf is of length 10
    end
    if j==2 & alphabet=='0628'
        alphabets(1,(y-3):y) = '062A'%%te
        haroof(1,(n-9):n) = 'te        '
    end
    if j==1 & alphabet== '062A'%%te
        alphabets(1,(y-3):y) = '062B'%%se
        haroof(1,(n-9):n) = 'se        '
    end
    if j==3 & alphabet =='0628'%%bay
        alphabets(1,(y-3):y) = '0679'%%te
        haroof(1,(n-9):n) = 'te        '

    end
    if j==1 & alphabet == '062D' %%%%bar? he
        alphabets(1,(y-3):y) = '062C'%%j?m
        haroof(1,(n-9):n) = 'jim       '
    end
    if j==2 & alphabet =='062D'
        alphabets(1,(y-3):y) = '0686'%%chay
        haroof(1,(n-9):n) = 'chay      '
    end
    if j==1 & alphabet =='062F'  %%%d?l
        alphabets(1,(y-3):y) = '0630'%%z?l
        haroof(1,(n-9):n) = 'zal       '
     end
    if j==3 & alphabet=='062F'
        alphabets(1,(y-3):y) = '0688'%%dd?l
        haroof(1,(n-9):n) = 'ddal      '
     end
    if j == 1 & alphabet =='0631' %%%raa
        alphabets(1,(y-3):y) = '0632'%%ze
        haroof(1,(n-9):n) = 'ze        '
     end
    if j==2 & alphabet =='0631'
        alphabets(1,(y-3):y) = '0698'%%zhe
        haroof(1,(n-9):n) = 'zhe       '
    end
    if j== 3 & alphabet =='0631'
        alphabets(1,(y-3):y) ='0691'%%%rre
        haroof(1,(n-9):n) = 'rre       '
     end
    if j==1 & alphabet == '0635'%%%soad
        alphabets(1,(y-3):y) = '0636'%%%zu'?d
        haroof(1,(n-9):n) = 'zuad      '
     end
    if j==2 & alphabet== '0633'%%%seen
        alphabets(1,(y-3):y) = '0634'%%%sh?n
        haroof(1,(n-9):n) = 'shin      '
     end
    if j==1 & alphabet== '0637'%%%toa
        alphabets(1,(y-3):y)='0638'%%%zo'e
        haroof(1,(n-9):n) = 'zoe       '

    end
     if j ==1 & alphabet== '0639'%%%aaen
        alphabets(1,(y-3):y) = '063A'%%ghain
        haroof(1,(n-9):n) = 'ghain     '
     end
     if j ==4 & alphabet== '06A9'%%%kaaf
        alphabets(1,(y-3):y) = '06AF'%%g?f
        haroof(1,(n-9):n) = 'gaf       '
     end

end
[m n] = size(alphabets)
set(handles.text5,'string',n/5)
set(handles.text4,'string',haroof)

save('alphabets','alphabets')

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

%%%% step# 05 Export Alphabets %%%
load alphabets

fid = fopen('text.RTF','w');

fprintf(fid,alphabets);
fclose(fid)

    winopen('text.RTF')

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

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

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

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

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

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

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

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

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

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

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

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

%%
% --- Executes on selection change in listbox1.
function listbox1_Callback(hObject, eventdata, handles)
% hObject    handle to listbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns listbox1 contents as cell array
%        contents{get(hObject,'Value')} returns selected item from listbox1

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

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


function [c,ceq] = snd_nl_terminalconstraints(t, x, varargin)
    if nargin >=3
        battery = cell2mat(varargin(1));
    else
    end

    c(1) = x(2)-battery.range(2);
    c(2) = battery.range(1)-x(2);
    c(3) = -x(3);
    c(4) = x(3)-100;
    ceq = [];
end


function [features, sp2reg] = computeFeatures(imName, paths, typ, param, data)

	clusters = data.clusters;
	superpixels = data.superpixels;
	nSP = max(superpixels(:));

	%For each region set compute the regions features
	for i = 1:size(clusters, 2),
		%calclate the sp2reg for
		cluster = clusters(:,i);
		nR = max(cluster);
		sp2reg{i} = false(nSP,nR);
		sp2reg{i}(sub2ind(size(sp2reg{i}),[1:nSP]',cluster)) = true;
		if(i > 1)
			[TF LOC] = ismember(sp2reg{i}', sp2reg{i-1}', 'rows');
			features{i}(:,find(TF)) = features{i-1}(:,LOC(find(TF)));
			if(~isempty(find(~TF)))
				features{i}(:,find(~TF)) = param.fName(superpixels, sp2reg{i}(:,find(~TF)), param, data);
			end
		else
			%Get features.
			features{i} = param.fName(superpixels, sp2reg{i}, param, data);
		end
		fprintf('.');
	end

	features = features;
	sp2reg = sp2reg;

	%Save the things
	fileName = fullfile(paths.featuresDir, typ, strcat(imName, '.mat'));
	save(fileName, 'clusters', 'superpixels', 'sp2reg', 'features');
end


report_this_filefun(mfilename('fullpath'));

% plot the results
% old and re3 (initially ) is the b-value matrix
%
re3=zvg;
r=ra;

zv2 = zvg;
l = ra > 30.00;
zvg(l)=nan;
figure
clf
[X,Y,Z] = meshgrid(gy,gx,gz);
zs = [-16 -12 -7 -1];
sl = slice(X,Y,Z,zvg,[mean(gy)] ,[ mean(gx)],[-20 -50]);

clf
sl = slice(X,Y,Z,pro,X2,Y2,Z2);
hold on
sl = slice(X,Y,Z,pro,X2,Y2,Z2);

hold on
rotate3d on
caxis([0 0.3])
%set(gca,'XLim',[s1_east s2_west],'xgrid','off')
%set(gca,'YLim',[s4_south s3_north],'ygrid','off')
%set(gca,'ZLim',[ -max(a.Depth)-2 0 ],'zgrid','off')

shading interp
cob = colorbar('vert')
set(cob,'TickDir','out','pos',[0.8 0.3 0.07 0.3])
set(gca,'Box','on','vis','on')
tmp = ra*nan;
tmp(1,1,1) = 0;
tmp(1,1,2) = 1;
hold on
sl = slice(X,Y,Z,tmp,[mean(gy)] ,[ -118.6],zs);
caxis([0 0.4])
set(sl(:),'EdgeColor',[0.5 0.5 0.5]);
view([-36 10])
axis([min(gy) max(gy) min(gx) max(gx) min(gz) max(gz)]);
grid off
plot3(a.Latitude,a.Longitude,-a.Depth,'yo','MarkerSize',2)
hold on

main =  [ -118.5370   34.2133   94.0453    1.0000   17.0000    6.7000   18.4010];

epimax = plot3(main(:,2),main(:,1),-main(:,7),'hm');
set(epimax,'LineWidth',2.5,'MarkerSize',18,...
    'MarkerFaceColor','w','MarkerEdgeColor','r')
hold on
aft1 = [ -118.6700   34.3692   97.3163    4.0000   26.0000    5.1000   16.4510];
epimax = plot3(aft1(:,2),aft1(:,1),-aft1(:,7),'^m');
set(epimax,'LineWidth',2.5,'MarkerSize',16,...
    'MarkerFaceColor','w','MarkerEdgeColor','m')


classdef AlignMTB < handle
    %ALIGNMTB  Aligns images of the same scene with different exposures
    %
    % This algorithm converts images to median threshold bitmaps (1 for pixels
    % brighter than median luminance and 0 otherwise) and than aligns the
    % resulting bitmaps using bit operations.
    %
    % It is invariant to exposure, so exposure values and camera response are
    % not necessary.
    %
    % In this implementation new image regions are filled with zeros.
    %
    % For more information see [GW03].
    %
    % ## References
    % [GW03]:
    % > Greg Ward. "Fast, robust image registration for compositing high
    % > dynamic range photographs from hand-held exposures".
    % > Journal of graphics tools, 8(2):17-30, 2003.
    %
    % See also: cv.AlignMTB.AlignMTB
    %

    properties (SetAccess = private)
        % Object ID
        id
    end

    properties (Dependent)
        % logarithm to the base 2 of maximal shift in each dimension.
        %
        % Values of 5 and 6 are usually good enough (31 and 63 pixels shift
        % respectively).
        MaxBits
        % range for exclusion bitmap that is constructed to suppress noise
        % around the median value.
        ExcludeRange
        % if true cuts images, otherwise fills the new regions with zeros.
        Cut
    end

    %% AlignMTB
    methods
        function this = AlignMTB(varargin)
            %ALIGNMTB  Creates AlignMTB object
            %
            %     obj = cv.AlignMTB()
            %     obj = cv.AlignMTB('OptionName',optionValue, ...)
            %
            % ## Options
            % * __MaxBits__ default 6
            % * __ExcludeRange__ default 4
            % * __Cut__ default true
            %
            % See also: cv.AlignMTB.process
            %
            this.id = AlignMTB_(0, 'new', varargin{:});
        end

        function delete(this)
            %DELETE  Destructor
            %
            %     obj.delete()
            %
            % See also: cv.AlignMTB
            %
            if isempty(this.id), return; end
            AlignMTB_(this.id, 'delete');
        end

        function shift = calculateShift(this, img0, img1)
            %CALCULATESHIFT  Calculates shift between two images
            %
            %     shift = obj.calculateShift(img0, img1)
            %
            % ## Input
            % * __img0__ first image (`uint8` grayscale).
            % * __img1__ second image of same size and type as `img0`.
            %
            % ## Output
            % * __shift__ calculated shift `[x,y]`.
            %
            % Calculates shift between two images, i. e. how to shift the
            % second image to correspond it with the first.
            %
            % See also: cv.AlignMTB.shiftMat
            %
            shift = AlignMTB_(this.id, 'calculateShift', img0, img1);
        end

        function dst = shiftMat(this, src, shift)
            %SHIFTMAT  Helper function, that shift Mat filling new regions with zeros
            %
            %     dst = obj.shiftMat(src, shift)
            %
            % ## Input
            % * __src__ input image.
            % * __shift__ shift value `[x,y]`.
            %
            % ## Output
            % * __dst__ result image, same size and type as `src`.
            %
            % See also: cv.AlignMTB.calculateShift
            %
            dst = AlignMTB_(this.id, 'shiftMat', src, shift);
        end

        function [tb, eb] = computeBitmaps(this, img)
            %COMPUTEBITMAPS  Computes median threshold and exclude bitmaps of given image
            %
            %     [tb, eb] = obj.computeBitmaps(img)
            %
            % ## Input
            % * __img__ input image (`uint8` grayscale).
            %
            % ## Output
            % * __tb__ median threshold bitmap, of same size as `img` and
            %   `uint8` type.
            % * __eb__ exclude bitmap, of same size as `img` and `uint8` type.
            %
            % See also: cv.AlignMTB.process
            %
            [tb, eb] = AlignMTB_(this.id, 'computeBitmaps', img);
        end
    end

    %% AlignExposures
    methods
        function dst = process(this, src)
            %PROCESS  Aligns images
            %
            %     dst = obj.process(src)
            %
            % ## Input
            % * __src__ cell array of input images (RGB), all of the same size
            %   and `uint8` type.
            %
            % ## Output
            % * __dst__ cell array of aligned images, of same length as `src`.
            %
            % See also: cv.AlignMTB.AlignMTB
            %
            dst = AlignMTB_(this.id, 'process', src);
        end
    end

    %% Algorithm
    methods (Hidden)
        function clear(this)
            %CLEAR  Clears the algorithm state
            %
            %     obj.clear()
            %
            % See also: cv.AlignMTB.empty, cv.AlignMTB.load
            %
            AlignMTB_(this.id, 'clear');
        end

        function b = empty(this)
            %EMPTY  Returns true if the algorithm is empty
            %
            %     b = obj.empty()
            %
            % ## Output
            % * __b__ Returns true if the object is empty (e.g in the
            %   very beginning or after unsuccessful read).
            %
            % See also: cv.AlignMTB.clear, cv.AlignMTB.load
            %
            b = AlignMTB_(this.id, 'empty');
        end

        function name = getDefaultName(this)
            %GETDEFAULTNAME  Returns the algorithm string identifier
            %
            %     name = obj.getDefaultName()
            %
            % ## Output
            % * __name__ This string is used as top level XML/YML node tag
            %   when the object is saved to a file or string.
            %
            % See also: cv.AlignMTB.save, cv.AlignMTB.load
            %
            name = AlignMTB_(this.id, 'getDefaultName');
        end

        function save(this, filename)
            %SAVE  Saves the algorithm parameters to a file
            %
            %     obj.save(filename)
            %
            % ## Input
            % * __filename__ Name of the file to save to.
            %
            % This method stores the algorithm parameters in the specified
            % XML or YAML file.
            %
            % See also: cv.AlignMTB.load
            %
            AlignMTB_(this.id, 'save', filename);
        end

        function load(this, fname_or_str, varargin)
            %LOAD  Loads algorithm from a file or a string
            %
            %     obj.load(fname)
            %     obj.load(str, 'FromString',true)
            %     obj.load(..., 'OptionName',optionValue, ...)
            %
            % ## Input
            % * __fname__ Name of the file to read.
            % * __str__ String containing the serialized model you want to
            %   load.
            %
            % ## Options
            % * __ObjName__ The optional name of the node to read (if empty,
            %   the first top-level node will be used). default empty
            % * __FromString__ Logical flag to indicate whether the input is a
            %   filename or a string containing the serialized model.
            %   default false
            %
            % This method reads algorithm parameters from the specified XML or
            % YAML file (either from disk or serialized string). The previous
            % algorithm state is discarded.
            %
            % See also: cv.AlignMTB.save
            %
            AlignMTB_(this.id, 'load', fname_or_str, varargin{:});
        end
    end

    %% Getters/Setters
    methods
        function value = get.MaxBits(this)
            value = AlignMTB_(this.id, 'get', 'MaxBits');
        end
        function set.MaxBits(this, value)
            AlignMTB_(this.id, 'set', 'MaxBits', value);
        end

        function value = get.ExcludeRange(this)
            value = AlignMTB_(this.id, 'get', 'ExcludeRange');
        end
        function set.ExcludeRange(this, value)
            AlignMTB_(this.id, 'set', 'ExcludeRange', value);
        end

        function value = get.Cut(this)
            value = AlignMTB_(this.id, 'get', 'Cut');
        end
        function set.Cut(this, value)
            AlignMTB_(this.id, 'set', 'Cut', value);
        end
    end

end


function ShowCmap(M, h)
% ShowCmap(M, h)
% a function to display and examine a colormap
% M (nx3): color map
% h: figure handle
%
% see also readXcol, ROIcmap, rgbdectohex, and ScaleToMap
%
   figure(h); clf
   subplot (211);
   colormap(M);
   image ([1:1:size(M,1)]);
   str = sprintf('%d colors color map. Pick colors with mouse\nHit "enter" to quit', size(M,1));
   title(str, 'fontsize',14);
   drawnow;

   i = 0;
   subplot (269);cla

   x1 = 1;
   while (~isempty(x1)),
      [x1,y] = ginput (1);
      if (~isempty(x1)),
         x1 = floor(x1(1)-0.5)+1;
         subplot (269);
         addsquare([0 i], [2.5 1+i], M(x1,:)); hold on
         plot (-0.2, i+0.5, 'k*');
         axis ([-1 3 -1 11]);
         str = sprintf ('Col %d: %.3g %.3g %.3g', x1, M(x1,1), M(x1,2), M(x1,3));
         ht = text (3, 0.3+i, 0, str, 'fontsize',14, 'color', M(x1,:));
         title (str);
         i = rem(i +1, 10);
      end
   end
return;