function montage_clusters_text(ovl,clusters,varargin)
% :Inputs:
%
%   **varargin:**
%        additional clusters structures
%        this function puts text cluster numbers on cluster centers
%
%   **color:**
%        cell array of text strings indicating colors {'r' 'g'} etc...
%
% ..
%    Tor Wager
% ..

if isempty(ovl), ovl = which('scalped_single_subj_T1.img');, end

myc = {'b' 'r' 'y' 'g' 'm' 'c'};

XYZmm = cat(2,clusters.XYZmm);

if length(varargin) > 0
    for i = 1:length(varargin)
        cl = varargin{i};
        clXYZmm = cat(2,cl.XYZmm);
        XYZmm = [XYZmm clXYZmm];
    end
end

% ----------------------------------------
% * overlay image
% ----------------------------------------
V = spm_vol(ovl);
oimg = spm_read_vols(V);
V.M = V.mat;

textx = size(oimg,2) - 50;
texty = size(oimg,1) - 6;

%[array,hdr,h,whichslices,rows,cols,figh] = readim2(ovl,'p');

% how many slices, which ones

XYZ = mm2voxel(XYZmm,V,2)';
whsl = unique(XYZ(3,:));
nsl = length(whsl) + 1;
rc = ceil(sqrt(nsl));
h = [];

% get centers for text plotting
cen = getcenters(clusters);

figure; colormap gray; set(gcf,'Color','w')

% plot first cluster structure
for i = 1:length(clusters)
    index = plot_cluster(clusters(i),oimg,rc,V,whsl,myc{1},textx,texty,1,size(oimg),cen(i,:),num2str(i));
    drawnow
end

% plot additional cluster structures

if length(varargin) > 0
    for i = 1:length(varargin)
        cl = varargin{i};
        cen = getcenters(cl);
        index = plot_cluster(cl,[],rc,V,whsl,myc{i+1},textx,texty,i+1,size(oimg),cen);

    end
end

return

% sub-functions
%

function index = plot_cluster(clusters,oimg,rc,V,whsl,myc,textx,texty,clind,odims,varargin)
% var argument is list of centers, x y z are rows, cols are coords

XYZmm = cat(2,clusters.XYZmm);
XYZ = mm2voxel(XYZmm,V)';

% text numbers, if plotting text at xyz coords of centers (varargin)
if length(varargin) > 0
    cencoo = varargin{1};
    cencoo = mm2voxel(cencoo,V)';
    centext = varargin{2};
    %cenind = 1;
end

% surface patch method
% ----------------------------------------------------------------------------------------
vol = voxel2mask(XYZ',odims);
vol = smooth3(vol);

index = 1;
for z = whsl

    subplot(rc,rc,index);

    if ~isempty(oimg)
        set(gca,'YDir','reverse');
        imagesc(oimg(:,:,z))
        hold on; axis image; axis off
        zmm = voxel2mm([1 1 z]',V.mat);
        text(textx,texty,['z = ' num2str(zmm(3))],'Color','w')
    else
        hold on
    end

    if z>1,FVC = isocaps(vol(:,:,z-1:z),0,'zmax');
    else FVC = isocaps(vol(:,:,z:z+1),0,'zmax');
    end
    try
	patch(FVC,'EdgeColor','none','FaceColor',myc,'FaceAlpha',.7)
    catch
	patch(FVC,'EdgeColor','none','FaceColor',myc)
    end

    % text numbers, if plotting text at xyz coords of centers (varargin)
    if length(varargin) > 0
        cencooz = cencoo(:,cencoo(3,:) == z);
        for i = 1:size(cencooz,2)
            text(cencooz(2,i),cencooz(1,i),centext,'Color','k'); %num2str(cenind),'Color','k')
            %cenind = cenind + 1;
        end
    end

    % plot method

    %myXYZ = XYZ(1:2,XYZ(3,:) == z);
    %plot(myXYZ(2,:),myXYZ(1,:),[myc 's'],'MarkerFaceColor',myc,'MarkerSize',3)

    index = index + 1;
    drawnow

end

subplot(rc,rc,index)
a = pwd; a = a(end-6:end);
b = num2str(clusters(1).threshold);

c = num2str(length(clusters));
text(0,clind-1,[myc ': ' clusters(1).title ' ' a ' u = ' b ', ' c ' clusters'])
axis off
axis([0 1 -1 clind])

return

function cen = getcenters(clusters)
    for i = 1:length(clusters)
        cen(i,:) = clusters(i).mm_center;
    end
    cen = cen';
return


function saverd3(fname,A,timewindow,timeinterval,antennasep)
% saverd3(fname,A,timewindow,timeinterval,antennasep)
%
% timewindow: [ns]
% timeinterval: seconds between traces
%
% Aslak Grinsted feb 2004

fname=strrep(lower(fname),'.rd3','');

fid=fopen([fname '.rd3'],'w');
A=(A-mean(mean(A)));
A=A*32767./max(max(abs(A)));
fwrite(fid,A,'short'); % should it be transposed?
fclose(fid);

fid=fopen([fname '.rad'],'w');

freq=size(A,1)*1000/timewindow;
freqsteps=1;
syscal=1/(freqsteps*freq);

stacks=1;
stacktime=size(A,1)*stacks/100000;

fprintf(fid,'SAMPLES:%i\r\n',size(A,1)); % SAMPLES:1024
fprintf(fid,'FREQUENCY:%0.6f\r\n',freq); % FREQUENCY:9410.717437
fprintf(fid,'FREQUENCY STEPS:%i\r\n',freqsteps);% FREQUENCY STEPS:12                    ??????????????
fprintf(fid,'SIGNAL POSITION:%0.6f\r\n',0); % SIGNAL POSITION:-0.156152          ????????????
fprintf(fid,'RAW SIGNAL POSITION:%i\r\n',1); % RAW SIGNAL POSITION:50401      ????????????
fprintf(fid,'DISTANCE FLAG:%i\r\n',0); % DISTANCE FLAG:0
fprintf(fid,'TIME FLAG:%i\r\n',1); % TIME FLAG:1
fprintf(fid,'PROGRAM FLAG:%i\r\n',0); % PROGRAM FLAG:0
fprintf(fid,'EXTERNAL FLAG:%i\r\n',0); % EXTERNAL FLAG:0
fprintf(fid,'TIME INTERVAL:%0.6f\r\n',timeinterval); % TIME INTERVAL:0.100000
fprintf(fid,'DISTANCE INTERVAL:%0.6f\r\n',0.1); % DISTANCE INTERVAL:0.100000
fprintf(fid,'OPERATOR:\r\n'); % OPERATOR:
fprintf(fid,'CUSTOMER:\r\n');% CUSTOMER:
fprintf(fid,'SITE:\r\n');% SITE:
fprintf(fid,'ANTENNAS:unknown\r\n');% ANTENNAS:800 MHz
fprintf(fid,'ANTENNA ORIENTATION:NOT VALID FIELD\r\n');% ANTENNA ORIENTATION:NOT VALID FIELD
fprintf(fid,'ANTENNA SEPARATION:%0.6f\r\n',antennasep);% ANTENNA SEPARATION:0.150000    ?????????????????
fprintf(fid,'COMMENT:Saved from matlab\r\n'); % COMMENT:
fprintf(fid,'TIMEWINDOW:%0.6f\r\n',timewindow); % TIMEWINDOW:108.812108   --nanoseconds for all samples
fprintf(fid,'STACKS:%i\r\n',stacks); % STACKS:1
fprintf(fid,'STACK EXPONENT:%i\r\n',0); % STACK EXPONENT:0
fprintf(fid,'STACKING TIME:%0.6f\r\n',stacktime); % STACKING TIME:0.010240                ??????????
fprintf(fid,'LAST TRACE:%i\r\n',size(A,2)); %LAST TRACE:18461

fprintf(fid,'STOP POSITION:%0.2f\r\n',size(A,2)*timeinterval); % STOP POSITION:53.16                 ??????????
fprintf(fid,'SYSTEM CALIBRATION:%0.10f\r\n',syscal);% SYSTEM CALIBRATION:0.0000088552   ?????? this has some effect on y-axis???
fprintf(fid,'START POSITION:%0.2f\r\n',0);% START POSITION:0.00
fprintf(fid,'SHORT FLAG:%i\r\n',1);% SHORT FLAG:1
fprintf(fid,'INTERMEDIATE FLAG:%i\r\n',0);% INTERMEDIATE FLAG:0
fprintf(fid,'LONG FLAG:%i\r\n',0);% LONG FLAG:0
fprintf(fid,'PREPROCESSING:%i\r\n',0);% PREPROCESSING:0
fprintf(fid,'HIGH:%i\r\n',5);% HIGH:5
fprintf(fid,'LOW:%i\r\n',15);% LOW:15
fprintf(fid,'FIXED INCREMENT:%0.3f\r\n',0.3);% FIXED INCREMENT:0.300
fprintf(fid,'FIXED MOVES UP:%i\r\n',0);% FIXED MOVES UP:0
fprintf(fid,'FIXED MOVES DOWN:%i\r\n',1);% FIXED MOVES DOWN:1
fprintf(fid,'FIXED POSITION:%0.3f\r\n',0); % FIXED POSITION:0.000
fclose(fid);


function im = read_tiny_gist_binary(words_in,ind)
%
%%% Routine to read in tiny images from giant binary file holding all
% 384-dim gist descriptors.
%
%%% There are two modes of operation:
%
% 1. raw indexing mode
% --------------------
% Inputs:
% 1. words_in - 1 x nImages vector, each element being an integer
% in the range 1 to 73,777,893 (or whatever the total number of images in the dataset is).
% Outputs:
% 1. im - 384 x nImages single data of Gist descriptors.
%
% ++++++++++++++++++++++++++++++++++++++++++++++++++++
%
% 2. word based indexing.
% -----------------------
% Inputs:
% 1. word_in - 1 x nWords cell array, each entry holding one noun
% 2. ind - 1 x nWords cell array, each holding indices of images
% for the corresponding noun
% Outputs:
% 1. im - 384 x nImages single data of Gist descriptors.
%
% Requires: read_tiny_binary_gist_core.mex file
%
%%%% Hints regarding operation:
% The access time per image drops as the total number of images to be
% gathered increases. e.g. for 500,000 images load time is
% 1ms/image. For 100,000 images it is 2ms/image. So try and pass in big
% blocks of indices.

% path to giant binary file (currently ~114Gb)
binary_fname = '/mit/tiny/data/tinygist80million.bin';
% indexing info .mat file
binary_data_fname = '/mit/tiny/data/tiny_index.mat';

% total # imgs
TOTAL_NUM_IMGS = 79302017;

if (nargin==1)
    RAW_INDEX_MODE = 1;
else
    RAW_INDEX_MODE = 0;
end

if (nargin==2)
    if iscell(ind)
        % do nothing
    else
        % convert to cell arrays
        words_in = {words_in};
        ind = {ind};
    end

    nWords = length(words_in);
end

if RAW_INDEX_MODE
    %% just go and call binary with raw indices
    %% check that all indices are >0 and <TOTAL_NUM_IMGS
    if ((sum(words_in<1)==0) & (sum(words_in>TOTAL_NUM_IMGS)==0))

        % now sort for speed
        [sorted_words,sort_ind] = sort(words_in);

        %% use MEX for sppedy reading in
        im = read_tiny_binary_gist_core(binary_fname, uint64(sorted_words));

        % sort back
        im(:,sort_ind) = im;
    else
        error('indices <0 or greater than total number of images');
    end

else % words_in and indices passed in

    % load up index data
    load(binary_data_fname);

    % compute hashes for all words_in
    hashes = compute_hash_function(words_in,hash_key);

    img_offsets = [];

    for a=1:nWords

        % find word using hash
        match_ind = find(hashes(a) == hash);

        if any(match_ind)
            % check all ind are >=1 and <=total number of images

            if ((sum(ind{a}<1)==0) & (sum(ind{a}>num_imgs(match_ind))==0))
                word_offset = offset(match_ind);
                img_offsets = [img_offsets , uint64(double(word_offset) + [ind{a}])];
            else
                error('indices <0 or greater than number per image');
            end
        else
           error('word not found');
        end

        % now sort for speed
        [sorted_offsets,sort_ind] = sort(img_offsets);

        im = read_tiny_binary_gist_core(binary_fname, uint64(sorted_offsets));

        % sort back
        im(:,sort_ind) = im;
    end
end


clear
close all

plotx2east

load martensite_single_grain

[grains,ebsd('indexed').grainId] =...
    calcGrains(ebsd('indexed'),'angle',3*degree);

cond_grains = ismember(grains.id,unique(ebsd(ids_of_interest).grainId));

%%
job = parentGrainReconstructor(ebsd,grains) % define job
job.useBoundaryOrientations = true;
clearvars grains ebsd

job.p2c = orientation.KurdjumovSachs(job.p2c.CS,job.p2c.SS);
job.calcParent2Child('quantile',0.6,'c2c'); % get representative OR

%%
job.calcHyperGraph3('threshold',5*degree,'c2c','mergeSimilar','mergethreshold',8*degree,'keepGraph')

numIters = [0 1 3 10 50];
grainId = 4691;

%%

for k = 1:length(numIters);
    if k == 1
    job.clusterHyperGraph3('numIter',numIters(k),...
        'inflationPower',1,'merged','mergethreshold',8*degree,'keepGraph')
        graphplotfunc(job,cond_grains,grainId,k,numIters)
    else
    job.clusterHyperGraph3('numIter',numIters(k) - numIters(k-1),...
        'inflationPower',1,'merged','mergethreshold',8*degree,'keepGraph')
        graphplotfunc(job,cond_grains,grainId,k,numIters)
    end
end

%%
p2c = orientation.NishiyamaWassermann(job.p2c.CS,job.p2c.SS);
p2c = p2c.project2FundamentalRegion(job.p2c);
job.p2c = p2c;

job.calcParentFromVote;
nextAxis
plot(job.grains(cond_grains & job.grains.phase == 2),...
    job.grains(cond_grains & job.grains.phase == 2).meanOrientation)
lims = job.ebsd.extent;
xlim([lims(1) lims(2)])
ylim([lims(3) lims(4)])

function graphplotfunc(job,cond_grains,grainId,k,numIters)

p2c = orientation.NishiyamaWassermann(job.p2c.CS,job.p2c.SS);
p2c = p2c.project2FundamentalRegion(job.p2c);

numV = length(variants(p2c,'parent'));

[i,j] = find(tril(job.graph));
i1 = ceil(i/numV);
i2 = i-(i1-1)*numV;
j1 = ceil(j/numV);
j2 = j-(j1-1)*numV;
prob = nonzeros(tril(job.graph));

cond = i1 ~= j1;

i1 = i1(cond);
j1 = j1(cond);

cond2 = (i1 == grainId | j1 == grainId);
i1 = i1(cond2);
j1 = j1(cond2);

i2 = i2(cond);
j2 = j2(cond);

i2 = i2(cond2);
j2 = j2(cond2);

prob = prob(cond);
prob = prob(cond2);

pOri = variants(p2c, job.grains(j1).meanOrientation, j2);
ipfKey = ipfHSVKey(job.csParent);
colors = ipfKey.orientation2color(pOri);

%%
%Equivalency:
z = unique([i1;j1]);
ord = zeros(max(z),1);
ord(z) = 1:length(z);

[x,y] = centroid(job.grains);
G = graph(ord(i1),ord(j1),prob);

if k == 1
    newMtexFigure('layout',[2,3])
else
    nextAxis
end

plot(job.grains(cond_grains).boundary)
hold on
plot(job.grains(unique([i1;j1])).boundary,'linecolor','red')
hold on
plot(G,'XData',x(unique([i1;j1])),'YData',y(unique([i1;j1])),...
    'EdgeColor',colors,'NodeColor','none','NodeLabel',{})
hold on
lims = job.ebsd.extent;
text(lims(2)-40,lims(3)+15, {[num2str(numIters(k)) ' iterations'],...
    [num2str(length(z)) ' nodes'],...
    [num2str(length(i1)) ' edges']}, 'HorizontalAlignment','left',...
    'FontSize',20, 'FontWeight','bold','BackgroundColor', 'white')

xlim([lims(1) lims(2)])
ylim([lims(3) lims(4)])

end


function cellInfo = Auto_Cmd_Bus(varargin)
% AUTO_CMD_BUS returns a cell array containing bus object information
%
% Optional Input: 'false' will suppress a call to Simulink.Bus.cellToObject
%                 when the MATLAB file is executed.
% The order of bus element attributes is as follows:
%   ElementName, Dimensions, DataType, SampleTime, Complexity, SamplingMode, DimensionsMode, Min, Max, DocUnits, Description

suppressObject = false;
if nargin == 1 && islogical(varargin{1}) && varargin{1} == false
    suppressObject = true;
elseif nargin > 1
    error('Invalid input argument(s) encountered');
end

cellInfo = { ...
  { ...
    'Auto_Cmd_Bus', ...
    '', ...
    '', ...
    'Auto', ...
    '-1', {...
{'timestamp', 1, 'uint32', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'p_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('rad/s'), sprintf('rate x command in body frame')}; ...
{'q_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('rad/s'), sprintf('rate y command in body frame')}; ...
{'r_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('rad/s'), sprintf('rate z command in body frame')}; ...
{'phi_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('rad'), sprintf('roll command')}; ...
{'theta_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('rad'), sprintf('pitch command')}; ...
{'psi_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'psi_rate_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('rad/s'), sprintf('yaw rate command')}; ...
{'x_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'y_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'z_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'lat_cmd', 1, 'int32', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'lon_cmd', 1, 'int32', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'alt_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'u_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('m/s'), sprintf('velocity x command in control frame')}; ...
{'v_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('m/s'), sprintf('velocity y command in control frame')}; ...
{'w_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], sprintf('m/s'), sprintf('velocity z command in control frame')}; ...
{'ax_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'ay_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'az_cmd', 1, 'single', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'throttle_cmd', 1, 'uint16', -1, 'real', 'Sample', 'Fixed', [], [], '', sprintf('throttle command')}; ...
{'frame', 1, 'uint8', -1, 'real', 'Sample', 'Fixed', [], [], '', sprintf('Coordinate Frame:\n0:FRAME_GLOBAL_NED\n1:FRAME_LOCAL_FRD\n2:FRAME_BODY_FRD')}; ...
{'reserved', 1, 'uint8', -1, 'real', 'Sample', 'Fixed', [], [], '', ''}; ...
{'cmd_mask', 1, 'uint32', -1, 'real', 'Sample', 'Fixed', [], [], '', sprintf('Type mask for auto command:\n  1: p_cmd valid\n  2: q_cmd valid\n  3: r_cmd valid\n  4: phi_cmd valid\n  5: theta_cmd valid\n  6: psi__cmd_valid\n  7: psi_rate_cmd_valid\n  8: x_cmd valid\n  9: y_cmd valid\n10: z_cmd valid\n11: lat_cmd valid\n12: lon_cmd valid\n13: alt_cmd valid\n14: u_cmd valid\n15: v_cmd valid\n16: w_cmd valid\n17: ax_cmd valid\n18: ay_cmd valid\n19: ax_cmd valid\n20: throttle_cmd valid')}; ...
    } ...
  } ...
}';

if ~suppressObject
    % Create bus objects in the MATLAB base workspace
    Simulink.Bus.cellToObject(cellInfo)
end


%**************************************************************
%* mex interface to Andy Liaw et al.'s C code (used in R package randomForest)
%* Added by Abhishek Jaiantilal ( abhishek.jaiantilal@colorado.edu )
%* License: GPLv2
%* Version: 0.02
%
% Calls Classification Random Forest
% A wrapper matlab file that calls the mex file
% This does prediction given the data and the model file
% Options depicted in predict function in http://cran.r-project.org/web/packages/randomForest/randomForest.pdf
%**************************************************************
%function [Y_hat votes] = classRF_predict(X,model, extra_options)
% requires 2 arguments
% X: data matrix
% model: generated via classRF_train function
% extra_options.predict_all = predict_all if set will send all the prediction.
%
%
% Returns
% Y_hat - prediction for the data
% votes - unnormalized weights for the model
% prediction_per_tree - per tree prediction. the returned object .
%           If predict.all=TRUE, then the individual component of the returned object is a character
%           matrix where each column contains the predicted class by a tree in the forest.
%
%
% Not yet implemented
% proximity

function [Y_new, votes, prediction_per_tree] = classRF_predict(X,model, extra_options)

    if nargin<2
		error('need atleast 2 parameters,X matrix and model');
    end

    if exist('extra_options','var')
        if isfield(extra_options,'predict_all')
            predict_all = extra_options.predict_all;
        end
    end

    if ~exist('predict_all','var'); predict_all=0;end

	[Y_hat,prediction_per_tree,votes] = mexClassRF_predict(X',model.nrnodes,model.ntree,model.xbestsplit,model.classwt,model.cutoff,model.treemap,model.nodestatus,model.nodeclass,model.bestvar,model.ndbigtree,model.nclass, predict_all);
	%keyboard
    votes = votes';

    clear mexClassRF_predict

    Y_new = double(Y_hat);
    new_labels = model.new_labels;
    orig_labels = model.orig_labels;

    for i=1:length(orig_labels)
        Y_new(find(Y_hat==new_labels(i)))=Inf;
        Y_new(isinf(Y_new))=orig_labels(i);
    end

    1;


function varargout = patchGraph(nodes, edges, faces) %#ok<INUSL>
%PATCHGRAPH Transform 3D graph (mesh) into a patch handle
%
%   [PX, PY, PZ] = PATCHGRAPH(NODES, EDGES, FACES)
%   Transform the graph defined as a set of nodes, edges and faces in a
%   patch which can be drawn usind matlab function 'patch'.
%   The result is a set of 3 array of size [NV*NF], with NV being the
%   number of vertices per face, and NF being the total number of faces.
%   each array contains one coordinate of vertices of each patch.
%
%
%   ---------
%
%   author : David Legland
%   INRA - TPV URPOI - BIA IMASTE
%   created the 28/06/2004.
%

if iscell(faces)
    p = zeros(length(faces), 1);
    for i = 1:length(faces)
        p(i) = patch( ...
            'Faces', faces{i}, ...
            'Vertices', nodes, ...
            'FaceColor', 'r', ...
            'EdgeColor', 'none') ;
    end
else
    p = patch( ...
        'Faces', faces, ...
        'Vertices', nodes, ...
        'FaceColor', 'r', ...
        'EdgeColor', 'none') ;
end

if nargout>0
    varargout{1}=p;
end


function J = image2Cell(I)

    numChannels = size(I,3);
    for channelIdx = 1:numChannels
        J{channelIdx} = squeeze(I(:,:,channelIdx));
    end


function PlotAnnotations(GT_IMG,ALG_IMG,FileName)
nRows=size(GT_IMG,1);
nCols=size(GT_IMG,2);
O=zeros(nRows,nCols,3);
for n=1:nRows
    for k=1:nCols
        if(GT_IMG(n,k)~=0&&ALG_IMG(n,k)~=0)
            O(n,k,:)=[255 255 255];
        elseif(GT_IMG(n,k)==0&&ALG_IMG(n,k)==0)
            O(n,k,:)=[0 0 0];
        elseif(GT_IMG(n,k)~=0&&ALG_IMG(n,k)==0)
            O(n,k,:)=[255 0 0];
        else
            O(n,k,:)=[0 255 0];
        end
    end
end
[~,name,~] = fileparts(FileName);
imwrite(O,['./Results/OutAnnotation/' name '_Diff.jpg'],'jpg');


function test_suite = test_modelassesment2

%   Run specific demo and save values for comparison.
%
%   See also
%     TEST_ALL, DEMO_MODELASSESMENT2

% Copyright (c) 2011-2012 Ville Tolvanen

initTestSuite;

  function testDemo
    % Set random number stream so that test failing isn't because randomness.
    % Run demo & save test values.
    prevstream=setrandstream(0);

    disp('Running: demo_modelassesment2')
    demo_modelassesment2
    path = which('test_modelassesment2.m');
    path = strrep(path,'test_modelassesment2.m', 'testValues');
    if ~(exist(path, 'dir') == 7)
      mkdir(path)
    end
    path = strcat(path, '/testModelAssesment2');
    save(path, 'DIC', 'DIC2', 'DIC_latent', 'p_eff', ...
      'p_eff2', 'p_eff_latent', 'p_eff_latent2', 'mlpd_cv', 'mlpd_loo');

    % Set back initial random stream
    setrandstream(prevstream);
    drawnow;clear;close all

  % Compare test values to real values.

  function testDICParameters
    values.real = load('realValuesModelAssesment2.mat', 'DIC');
    values.real.DIC(isnan(values.real.DIC)) = 0;
    values.test = load(strrep(which('test_modelassesment2.m'), 'test_modelassesment2.m', 'testValues/testModelAssesment2.mat'),'DIC');
    values.test.DIC(isnan(values.test.DIC)) = 0;
    assertVectorsAlmostEqual(values.real.DIC, values.test.DIC, 'relative', 0.05);

  function testDICAll
    values.real = load('realValuesModelAssesment2.mat', 'DIC2');
    values.real.DIC2(isnan(values.real.DIC2)) = 0;
    values.test = load(strrep(which('test_modelassesment2.m'), 'test_modelassesment2.m', 'testValues/testModelAssesment2.mat'),'DIC2');
    values.test.DIC2(isnan(values.test.DIC2)) = 0;
    assertVectorsAlmostEqual(values.real.DIC2, values.test.DIC2, 'relative', 0.05);

  function testDICLatent
    values.real = load('realValuesModelAssesment2.mat', 'DIC_latent');
    values.real.DIC_latent(isnan(values.real.DIC_latent)) = 0;
    values.test = load(strrep(which('test_modelassesment2.m'), 'test_modelassesment2.m', 'testValues/testModelAssesment2.mat'),'DIC_latent');
    values.test.DIC_latent(isnan(values.test.DIC_latent)) = 0;
    assertVectorsAlmostEqual(values.real.DIC_latent, values.test.DIC_latent, 'relative', 0.05);

  function testPeffLatentsMarginalized
    values.real = load('realValuesModelAssesment2.mat', 'p_eff');
    values.real.p_eff(isnan(values.real.p_eff)) = 0;
    values.test = load(strrep(which('test_modelassesment2.m'), 'test_modelassesment2.m', 'testValues/testModelAssesment2.mat'),'p_eff');
    values.test.p_eff(isnan(values.test.p_eff)) = 0;
    assertVectorsAlmostEqual(values.real.p_eff, values.test.p_eff, 'relative', 0.4);

	function testPeffLatent
    values.real = load('realValuesModelAssesment2.mat', 'p_eff_latent');
    values.real.p_eff_latent(isnan(values.real.p_eff_latent)) = 0;
     values.test = load(strrep(which('test_modelassesment2.m'), 'test_modelassesment2.m', 'testValues/testModelAssesment2.mat'),'p_eff_latent');
     values.test.p_eff_latent(isnan(values.test.p_eff_latent)) = 0;
    assertVectorsAlmostEqual(values.real.p_eff_latent, values.test.p_eff_latent, 'relative', 0.05);

	function testPeffLatent2
    values.real = load('realValuesModelAssesment2.mat', 'p_eff_latent2');
    values.real.p_eff_latent2(isnan(values.real.p_eff_latent2)) = 0;
    values.test = load(strrep(which('test_modelassesment2.m'), 'test_modelassesment2.m', 'testValues/testModelAssesment2.mat'),'p_eff_latent2');
    values.test.p_eff_latent2(isnan(values.test.p_eff_latent2)) = 0;
    assertVectorsAlmostEqual(values.real.p_eff_latent2, values.test.p_eff_latent2, 'relative', 0.25);

	function testLogPredDensity10foldCV
    values.real = load('realValuesModelAssesment2.mat', 'mlpd_cv');
    values.test = load(strrep(which('test_modelassesment2.m'), 'test_modelassesment2.m', 'testValues/testModelAssesment2.mat'), 'mlpd_cv');
    assertVectorsAlmostEqual(values.real.mlpd_cv, values.test.mlpd_cv, 'relative', 0.05);

  function testLogPredDensityLOOPRED
    values.real = load('realValuesModelAssesment2.mat', 'mlpd_loo');
    values.test = load(strrep(which('test_modelassesment2.m'), 'test_modelassesment2.m', 'testValues/testModelAssesment2.mat'), 'mlpd_loo');
    assertVectorsAlmostEqual(values.real.mlpd_loo, values.test.mlpd_loo, 'relative', 0.05);


% Demo for Structured Edge Detector (please see readme.txt first).

error(['This is a demo for Stuctured Edges and not for our RGB-D edge detector.', ...
  ' Please look at run_all.m for how to run our RGB-D edge detector and look at scripts/script_edges.m' ...
  ' for how to train the RGB-D edge detector.']);

%% set opts for training (see edgesTrain.m)
opts=edgesTrain();                % default options (good settings)
opts.modelDir='models/';          % model will be in models/forest
opts.modelFnm='modelBsds';        % model name
opts.nPos=5e5; opts.nNeg=5e5;     % decrease to speedup training
opts.useParfor=0;                 % parallelize if sufficient memory

%% train edge detector (~20m/8Gb per tree, proportional to nPos/nNeg)
tic, model=edgesTrain(opts); toc; % will load model if already trained

%% set detection parameters (can set after training)
model.opts.multiscale=0;          % for top accuracy set multiscale=1
model.opts.sharpen=2;             % for top speed set sharpen=0
model.opts.nTreesEval=4;          % for top speed set nTreesEval=1
model.opts.nThreads=4;            % max number threads for evaluation
model.opts.nms=0;                 % set to true to enable nms

%% evaluate edge detector on BSDS500 (see edgesEval.m)
if(0), edgesEval( model, 'show',1, 'name','' ); end

%% detect edge and visualize results
I = imread('peppers.png');
tic, E=edgesDetect(I,model); toc
figure(1); im(I); figure(2); im(1-E);


function imgHiRes = sr_demo(filePath, opt)
% SR_DEMO
%
% Input:
%     - filePath: filePath contains
%       (1) dataPath: path to the input images
%       (2) imgFileName: the file name of the input low-resolution image
%     - opt: algorithm parameters, obtained by
%            opt = sr_init_opt(SRF);
% Output:
%     - imgHiRes: the super-resolved images
%
% Example usage:
%   filePath.dataPath    = 'data\Urban100\image_SRF_4';
%   filePath.imgFileName = 'img_001_SRF_4_LR.png';
%
%   imgHiRes = sr_demo(filePath, opt);
% Disclaimer:
%
%   It is provided for educational/researrch purpose only.
%   If you find the software useful, please consider cite our paper.
%
%   Single Image Super-Resolution using Transformed Self-Exemplars
%   Jia-Bin Huang, Abhishek Singh, and Narendra Ahuja
%   IEEE Conference on Computer Vision and Pattern Recognition, CVPR 2015
%
% Contact:
%   Jia-Bin Huang
%   Electrical and Computer Engineering
%   University of Illinois, Urbana-Champaign
%   www.jiabinhuang.com

% =========================================================================
% Extract planar structures
% =========================================================================
fprintf('- Extract planar structures \n');
tic;
modelPlane = sr_extract_plane(filePath.dataPath, filePath.imgFileName, opt);
tAnalysis = toc;
fprintf('Done in %6.3f seconds.\n\n', tAnalysis);

% =========================================================================
% Construct image pyramid for coarse-to-fine image super-resolution
% =========================================================================
tic;
% Load the input low-resolution image:
img = im2single(imread(fullfile(filePath.dataPath, filePath.imgFileName)));
if(ndims(img)~=3) % support only RGB images
    img = cat(3, img, img, img);
end
tImgPyramid = toc;
fprintf('Done in %6.3f seconds.\n\n', tImgPyramid);

% Create image pyramid and multi-level planar structure constraints
fprintf('- Construct plane pyramid: \n');
tic;
[imgPyrH, imgPyrL, scaleImgPyr] = sr_create_img_pyramid(img, opt);
modelPlane = sr_planar_structure_pyramid(scaleImgPyr, modelPlane, opt.topLevel);
tPlanePyramid = toc;
fprintf('Done in %6.3f seconds.\n\n', tPlanePyramid);

% =========================================================================
% Super-resolution by patch-based synthesis
% =========================================================================
fprintf('- Single Image Super-Resolution using Transformed Self-Exemplars \n');
tic;
imgPyr = sr_synthesis(imgPyrH, imgPyrL, scaleImgPyr, modelPlane, filePath, opt);
tSynthesis = toc;
fprintf('Synthesis took %6.3f seconds.\n', tSynthesis);

% Get the level corresponding to the desired high-resolution image
if(mod(opt.SRF,2) == 0 )
    lvlInd = opt.origResLvl - log(opt.SRF)/log(2)*opt.nLvlToRedRes;
else
    lvlInd = opt.origResLvl - log(opt.SRF)/log(3)*opt.nLvlToRedRes;
end

imgHiRes = imgPyr{uint8(lvlInd)};

% Visualize plane parameters
% if(0)
%     imgTformVis = sr_vis_planar_tform(imgPyr{opt.origResLvl-6}, modelPlane{opt.origResLvl-6});
%
%     imgVisResName = [filePath.imgFileName(1:end-4), '_vis.png'];
%     imwrite(imgTformVis, fullfile('result\vis', imgVisResName));
% end

end


% path planner
%
% Modified:
%   - 4/06/2010 - RWB
%
% output is a vector containing P.num_waypoints waypoints
%
% input is the map of the environment and desired goal location
function out = path_planner1(in,P,map)
load  'uavW.mat'
i1 = uavW;
clear uavW;

 NN = 0;
  pn        = in(1+NN);
  pe        = in(2+NN);
  h         = in(3+NN);
  % Va      = in(4+NN);
  % alpha   = in(5+NN);
  % beta    = in(6+NN);
  % phi     = in(7+NN);
  % theta   = in(8+NN);
  chi     = in(9+NN);
  % p       = in(10+NN);
  % q       = in(11+NN);
  % r       = in(12+NN);
  % Vg      = in(13+NN);
  % wn      = in(14+NN);
  % we      = in(15+NN);
  % psi     = in(16+NN);
  flag_new_waypoints =  in(17+NN);
  NN = NN + 17;
  t         =  in(1+NN);

  persistent num_waypoints
  persistent wpp

  if (t==0) || flag_new_waypoints
    % format for each point is [pn, pe, pd, chi, Va^d] where the position
    % of the waypoint is (pn, pe, pd), the desired course at the waypoint
    % is chi, and the desired airspeed between waypoints is Va
    % if chi!=-9999, then Dubins paths will be used between waypoints.
    switch 1
          case 1

        [num_waypoints , wpp] = getWpp(P,i1);

          case 2  % Dubins
            num_waypoints = 4;
            wpp = [...
                    0, 0, -100, 0, P.Va0;...
                    300, 0, -100, 45*pi/180, P.Va0;...
                    0, 300, -100, 45*pi/180, P.Va0;...
                    300, 300, -100, -135*pi/180, P.Va0;...
                  ];
          case 3 % path through city using Dubin's paths
               % current configuration
              wpp_start = [pn, pe, -h, chi, P.Va0];
              % desired end waypoint
              if norm([pn; pe; -h]-[map.width; map.width; -h])<map.width/2,
                  wpp_end = [0, 0, -h, 0, P.Va0];
              else
                  wpp_end = [map.width, map.width, P.pd0, 0, P.Va0];
              end
              waypoints = planRRTDubins(wpp_start, wpp_end, P.R_min, map);
              num_waypoints = size(waypoints,1);
              wpp = [];
              for i=1:num_waypoints
                  wpp = [...
                            wpp;...
                            waypoints(i,1), waypoints(i,2), waypoints(i,3), waypoints(i,4), P.Va0;...
                        ];
              end
          case 4  % path through city using straight-line RRT
               % current configuration
              wpp_start = [pn, pe, -h, chi, P.Va0];
              % desired end waypoint
              if norm([pn; pe; -h]-[map.width; map.width; -h])<map.width/2,
                  wpp_end = [0, 0, -h, 0, P.Va0];
              else
                  wpp_end = [map.width, map.width, P.pd0, 0, P.Va0];
              end
              waypoints = planRRT(wpp_start, wpp_end, map);
              num_waypoints = size(waypoints,1);
              wpp = [];
              for i=1:num_waypoints
                  wpp = [...
                            wpp;...
                            waypoints(i,1), waypoints(i,2), waypoints(i,3), waypoints(i,4), P.Va0;...
                        ];
              end
          case 5  % cover path through city using Dubin's paths
               % current configuration
              wpp_start = [pn, pe, -h, chi, P.Va0];
              waypoints = planCoverRRTDubins(wpp_start, P.R_min, map);
              num_waypoints = size(waypoints,1);
              wpp = [];
              for i=1:num_waypoints
                  wpp = [...
                            wpp;...
                            waypoints(i,1), waypoints(i,2), waypoints(i,3), waypoints(i,4), P.Va0;...
                        ];
              end
    end
    for i=num_waypoints+1:P.size_waypoint_array
          wpp = [...
                    wpp;...
                    -9999, -9999, -9999, -9999, -9999;...
                ];
    end

  end

  out = [num_waypoints; reshape(wpp', 5*P.size_waypoint_array, 1)];

end


function write_neuralynx_nse(filename, nse)

% WRITE_NEURALYNX_NSE writes spike timestamps and waveforms to a NSE file
% The input data should be scaled in uV.
%
% Use as
%   write_neuralynx_nse(filename, nse)
%
% See also READ_NEURALYNX_NSE

% Copyright (C) 2005-2007, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

if ~isa(nse.TimeStamp, 'uint64')
  ft_error('timestamps should be uint64');
end

% convert the data from uV into V
nse.dat = nse.dat * 1e-6;
% scale the data and convert to 16 bits,
% this has to be done prior to writing the header
ADMaxValue = double(intmax('int16'));
ADMaxVolts = max(abs(nse.dat(:)));
if ADMaxVolts>0
  ADBitVolts = ADMaxVolts / ADMaxValue;
else
  ADBitVolts = 1;
end
nse.dat = int16(nse.dat / ADBitVolts);
% update the header with the calibration values
nse.hdr.ADBitVolts = ADBitVolts;
nse.hdr.ADMaxValue = ADMaxValue;

% construct the header
buf  = [];
buf  = [buf sprintf('######## Neuralynx Data File Header\r\n')];
buf  = [buf sprintf('## File Name: %s\r\n', filename)];
buf  = [buf sprintf('## Time Opened: (m/d/y): %s  At Time: %s\r\n', datestr(clock, 'mm/dd/yy'), datestr(clock, 'HH:MM:SS'))];
f = fieldnames(nse.hdr);
for i=1:length(f)
  v = getfield(nse.hdr, f{i});
  switch class(v)
    case 'char'
      buf = [buf sprintf('-%s\t%s\r\n', f{i}, v)];
    case 'double'
      buf = [buf sprintf('-%s\t%g\r\n', f{i}, v)];
    otherwise
      ft_error('unknown class in writing header');
  end
end

% pad the rest of the header with zeros
buf((end+1):16384) = 0;

% write the header to file
fid  = fopen(filename, 'wb', 'ieee-le');
fwrite(fid, buf);

% The format of a single electrode record is
%   int64 TimeStamp
%   int32 ScNumber
%   int32 CellNumber
%   int32 Param[0] ... Param[7]
%   int16 Samp[0] ... int16 Samp[31]

for i=1:size(nse.dat,2)
  % write a single continuous data record
  fwrite(fid, nse.TimeStamp(i) , 'int64');
  fwrite(fid, nse.ScNumber(i)  , 'int32');
  fwrite(fid, nse.CellNumber(i), 'int32');
  fwrite(fid, nse.Param(:,i)   , 'int32');
  fwrite(fid, nse.dat(:,i)     , 'int16');
end

% close the file
fclose(fid);


function [statslice,cesslice] = er_stxgslice(hAvgFile,contrast,varargin);
% [statslice,cesslice] = er_stxgslice(hAvgFile,contrast,[options]);
%
% er_stxgslice: fs-fast stx slice grinder script, ported for use with
% mrLoadRet
%
% Computes one (inplane) slice of a contrast map, across one or more input
% scans. Returns the specified statistic as statslice.
%
% hAvgFile: path to the tSeries for this slice (e.g.
% Inplane/Original/Tseries/Scan1/tSeries1.mat)
%
% contrast: a structure with the same format as that produced by the
% FS-FAST function mkcontrast-sess. It has at least the following fields:
%       ContrastMtx_0: specifies the condition contrast. For block-design
%       (non-deconvolved) experiments, it should have the following format:
%       1 row, nConds columns, where nConds does not include the fixation/
%       baseline condition (usually specified as condition 0). Active
%       conditions should have positive sign, control conditions should
%       have negative sign, conditions which are not to be considered
%       should be 0. The sum of the active conditions should be 1, control
%       conditions should be -1. E.g. for 5 conditions, comparing 1 and 2
%       vs. 4 and 5 and ignoring condition 3:
%
%               contrast.ContrastMtx_0 = [0.5 0.5 0 -0.5 -0.5];
%
% Right now this doesn't save anything, just hands off two matrices,
% statslice and cesslice. statslice contains the results of a statistic, by
% default the -log10 p value from a t test between the active Versus
% control conditions. cesslice is a measure (still not sure the
% mathematical basis) of the size of the contrast effect. In mrLoadRet
% terms, these might have analogous functions to the coherence (statslice)
% and amplitude (cesslice) of the corAnal.
%
% Options: hand in options in pairs, e.g. 'ihDelta',1.25. Can be strings or
% numeric values (if the parameter is numeric). You can set any of the
% parameters set at the top of the code (sorry this is so hands on; in exchange
% I hope to make the code much more legible as I go over several iterations).

% $Id: er_stxgslice.m,v 1.12 2005/08/09 22:58:27 sayres Exp $
% er_stxgslice: ported from fmri_stxgslice by ras, 10/1/03
% 03/05/04 ras: changed from a script to a function. Doesn't save any
% output files, but instead returns a matrix containing the requested stat
% matrix for the given slice.
%
% See also: computeContrastMap,er_stxgrinder,er_mkcontrast.
% ras 04/03/04: fixed the scaling issue (wasn't taking estimated
% variance.^2)
statslice = []; cesslice = [];

% fprintf(1,' ---------- StXGSlice.m : Starting ------------\n');

%%%%% PARAMS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
QuitOnError = 1;
OutputFormat = 1; % 0 = log(p) (natural log)
                  %  1 = log10(p)
                  %  2 = p
                  %  3 = test value
ActiveCond = contrast.condNums(find(contrast.WCond > 0));
ControlCond = contrast.condNums(find(contrast.WCond < 0));
CorrIdeal = 0;
CmpIdeal = 0;
TestType = 'tm'; % for list of test types, help fmri_mrestriction
ihDelta = 1.25;
ihTau = 2.5;
dataSize = [];  % [X Y] size of inplanes; enter through varargin if functional is not square (e.g., cropped)
datfile = fullfile(fileparts(hAvgFile),'h.dat'); % this should be produced by selxavg
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% parse the option flags
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for i = 1:length(varargin)
    if (i < length(varargin)) & (ischar(varargin{i}))
		if (isnumeric(varargin{i+1}))
	        cmd = sprintf('%s = [%s];',varargin{i},num2str(varargin{i+1}));
		elseif ischar(varargin{i+1})
	        cmd = sprintf('%s = ''%s'';',varargin{i},varargin{i+1})
		elseif iscell(varargin{i+1});
			tmp = unNestCell(varargin{i+1});
	        cmd = sprintf('%s = {',varargin{i});
			for j = 1:length(tmp)-1
				cmd = [cmd '''' tmp{j} ''','];
			end
			cmd = [cmd '''' tmp{end} '''};']
	    end
        eval(cmd);
	end
end

if (CmpIdeal) | (CorrIdeal) % still trying to figure out what CorrIdeal is -- it's for deconvolved data, at least
    if isempty(ihDelta)
        error('er_stxgslice: need to input ihDelta if correlating w/ Ideal HRF.')
    end

    if isempty(ihTau)
        error('er_stxgslice: need to input ihTau if correlating w/ Ideal HRF.')
    end
end

%%%% ----- Check that variables are the proper values ---- %%%%%
% Check the Test Type %
if ( isempty( strmatch(upper(TestType),{'T ','TM','FM','F0','FD','FC','FCD','FDC'},'exact')))
    fprintf(2,'Error: Unkown TestType %s',TestType);
    if (QuitOnError) quit;
    else            return;
    end
end

if ( OutputFormat < 0 | OutputFormat > 3)
    fprintf(2,'Error: OutputFormat=%d, must be within 0 to 3\n',OutputFormat);
    if (QuitOnError) quit;
    else            return;
    end
end

%% -- check that input files exist -- %%
if ~exist(hAvgFile,'file')
    error(['Can''t find file ' hAvgFile '.']);
end
if ~exist(datfile,'file')
    error(['Can''t find file ' datfile '.']);
end

%% --- Read the h.dat Header File ---- %%%
% fprintf(1,'Reading h.dat Header \n');
hd = fmri_lddat3(datfile);
if isempty(dataSize) % if not entered through varargin
    dataSize = [hd.Nrows hd.Ncols];
end

%% --- Read the hAvg File ---- %%%
% fprintf(1,'Reading hAvg File \n');
load(hAvgFile)
if ~exist('tSeries','var')
    error([hAvgFile ' does not contain a tSeries variable!']);
end

%% --- This should always be 1 until I add deconvolution support ---- %%%
if (hd.GammaFit > 0)
    HDelTest = 1;
else
   newHDelMin = hd.TER*round(HDelMin/hd.TER)+hd.TER*round(hd.TPreStim/hd.TER);
   newHDelMax = hd.TER*round(HDelMax/hd.TER)+hd.TER*round(hd.TPreStim/hd.TER);
   fprintf(1,'Info: newHDelMin = %g, newHDelMax = %g\n',newHDelMin,newHDelMax);
   HDelTest = round([newHDelMin/hd.TER:newHDelMax/hd.TER]') + 1; %'
   fprintf(1,'Info: HDelTest ');
   fprintf(1,' %d',HDelTest);
   fprintf(1,'\n');
end

%% --- From the sxa format of the tSeries, grab hAvg and eVar ---- %%%
% These are the average planes for each condition and the estimated
% residual variance. I may be incorrect--I need to verify this--but I
% believe the format selxavg saves as contains the residual variance as the
% estimated variances for the null, 0, condition. This is the first plane.
% So for block design expts (Nh = 1), the format of the rows of the tSeries
% is: zeros for baseline, eVar, hAvg for Cond 1, variance for Cond 1, hAvg
% for Cond 2, variance for cond 2, etc. er_stxgrinder requires hAvg and
% eVar:
eVar = reshape(tSeries(2,:),dataSize);
eVar = eVar .* eVar;
ind = 3:2:size(tSeries,1);
for i = 1:length(ind)
	hAvg(:,:,i) = reshape(tSeries(ind(i),:),dataSize);
end

if ( exist('HDelMin') & hd.GammaFit > 0)
    msg = 'Cannot specify a delay range with gamma-fit average files';
    qoe(msg); error(msg);
end

if (CorrIdeal & hd.GammaFit > 0)
    msg = 'Cannot correlate ideal HDR with gamma-fit average files';
    qoe(msg); error(msg);
end

nVoxels = hd.Nrows*hd.Ncols;

nPreStim = floor(hd.TPreStim/hd.TER);

% set up params for er_stxgrinder, which does the actual GLM contrast
% computation:
%Ch = fmri_ldbfile(hcovFile);
Ch = hd.hCovMtx;              % covariance matrix
RM = contrast.ContrastMtx_0;  % restriction matrix
nRM = size(RM,2);
nh  = size(hAvg,3);
if (nRM ~= nh)
    msg = sprintf('er_stxgslice: hAvg size (%d) is inconsistent with CMtx (%d)',nh,nRM);
    error(msg);
else
    RM = contrast.ContrastMtx_0;
end

q = zeros(size(hAvg,3),1);

% The meat of the calculation -- create the maps
[vSig pSig ces] = er_stxgrinder(TestType,hAvg,eVar,Ch,hd.DOF,RM,q);

if nargout > 1
    % ---- Compute ces as percent of baseline --- %
    inputdir = fileparts(hAvgFile);
    a = findstr('hAvg',hAvgFile)+4;
    b = findstr('.mat',hAvgFile)-1;
    sliceno = str2num(hAvgFile(a:b));
    hoffsetname = fullfile(inputdir,sprintf('mean_%03d.mat',sliceno));
    hoffset = er_ldtfile(hoffsetname);
    if (isempty(hoffset))
        fprintf('ERROR: could not load %s\n',hoffsetname);
        return;
    elseif size(hoffset,2)==1
        % somehow the mean image (hoffset) gets saved
        % as a column rather than row vector
        hoffset = hoffset';
    end
    indz = find(hoffset==0);
    hoffset(indz) = 10^10;
    nces = size(ces,3);
    cesslice = ces./repmat(reshape(hoffset,size(ces)),[1 1 nces]);
end

if (CmpIdeal)
    pSig = 1 - pSig ;
end

if (strncmp('T',upper(TestType),1))
    SignMask = ((vSig>=0) - (vSig<0));
    pSig = pSig .* SignMask;
else
    SignMask = [];
end

% Dont let pSig = zero (messes up log10)
iz = find(abs(pSig) < 10^-300);
pSig(iz) = sign(pSig(iz)) * 10^-300;
iz = find(pSig == 0);
pSig(iz) = 10^-300; % Have to do this because sign(0) = 0

if (OutputFormat == 0)     pSig = -log(abs(pSig))  .*sign(pSig);
elseif (OutputFormat == 1) pSig = -log10(abs(pSig)).*sign(pSig);
end

statslice = pSig;

return


function [g1, g2] = lfmwhiteXrbfwhiteKernGradient(lfmKern, rbfKern, t1, varargin)

% LFMWHITEXRBFWHITEKERNGRADIENT Compute a cross gradient between an LFM-WHITE
% and an RBF-WHITE kernels.
% FORMAT
% DESC computes cross gradient of parameters of a cross kernel between an
% LFM-WHITE and an RBF-WHITE kernels for the multiple output kernel.
% ARG lfmKern : the kernel structure associated with the LFM-WHITE kernel.
% ARG rbfKern : the kernel structure associated with the RBF-WHITE kernel.
% ARG t1 : inputs for which kernel is to be computed.
% ARG covGrad : gradient of the objective function with respect to
% the elements of the cross kernel matrix.
% RETURN g1 : gradient of the parameters of the LFM-WHITE kernel, for
% ordering see lfmwhiteKernExtractParam.
% RETURN g2 : gradient of the parameters of the RBF-WHITE kernel, for
% ordering see rbfwhiteKernExtractParam.
%
% FORMAT
% DESC computes cross gradient of parameters of a cross kernel between an
% LFM-WHITE and an RBF-WHITE kernels for the multiple output kernel.
% ARG lfmKern : the kernel structure associated with the LFM-WHITE kernel.
% ARG rbfKern : the kernel structure associated with the RBF-WHITE kernel.
% ARG t1 : row inputs for which kernel is to be computed.
% ARG t2 : column inputs for which kernel is to be computed.
% ARG covGrad : gradient of the objective function with respect to
% the elements of the cross kernel matrix.
% RETURN g1 : gradient of the parameters of the LFM-WHITE kernel, for
% ordering see lfmwhiteKernExtractParam.
% RETURN g2 : gradient of the parameters of the RBF-WHITE kernel, for
% ordering see rbfwhiteKernExtractParam.
%
% SEEALSO : multiKernParamInit, multiKernCompute, lfmwhiteKernParamInit,
% rbfwhiteKernParamInit, lfmwhiteKernExtractParam, rbfwhiteKernExtractParam
%
% COPYRIGHT : David Luengo, 2009

% KERN

if nargin < 5
    t2 = t1;
else
    t2 = varargin{1};
end
covGrad = varargin{end};

if size(t1, 2) > 1 | size(t2, 2) > 1
  error('Input can only have one column');
end
if lfmKern.variance ~= rbfKern.variance
  error('Kernels cannot be cross combined if they have different variances.')
end
if lfmKern.isStationary ~= rbfKern.isStationary
  error('Stationary and non-stationary kernels cannot be cross combined.')
end

g1 = zeros(1, lfmKern.nParams);
g2 = zeros(1, rbfKern.nParams);

T1 = repmat(t1, 1, size(t2, 1));
T2 = repmat(t2.', size(t1, 1), 1);
deltaT = T1 - T2;
indT = double(T1 >= T2);

% Parameters required in the computation of the kernel
isStationary = lfmKern.isStationary;
mass = lfmKern.mass;
spring = lfmKern.spring;
damper = lfmKern.damper;
variance = lfmKern.variance;
sensitivity = lfmKern.sensitivity;

invWidth = rbfKern.inverseWidth;

alpha = lfmKern.alpha;
omega = lfmKern.omega;
gamma = lfmKern.gamma;
gammaTilde = alpha - j*omega;

% Gradients of theta w.r.t. mass, spring and damper

gradThetaMass = [1 0 0];
gradThetaAlpha = [-damper/(2*(mass^2)) 0 1/(2*mass)];
gradThetaOmega = [(damper^2-2*mass*spring)/(2*(mass^2)*sqrt(4*mass*spring-damper^2)) ...
    1/(sqrt(4*mass*spring-damper^2)) -damper/(2*mass*sqrt(4*mass*spring-damper^2))];
gradThetaGamma = gradThetaAlpha + j*gradThetaOmega;
gradThetaGammaTilde = gradThetaAlpha - j*gradThetaOmega;

% Computation of the normalised kernel (i.e. variance = 1 and sensitivity = 1)
% and auxiliary functions and constants

lfmKern.variance = 1;
lfmKern.sensitivity = 1;
rbfKern.variance = 1;
K = lfmwhiteXrbfwhiteKernCompute(lfmKern, rbfKern, t1, t2);

c = 1 / (j*4*mass*omega);

varphiT1T2 = gamma * deltaT .* indT + 0.5 * invWidth * (deltaT.^2) .* (1-indT);
zT1T2 = sqrt(0.5*invWidth) * (-deltaT .* (1-indT) + gamma / invWidth);
varphiT1T2Tilde = gammaTilde * deltaT .* indT + 0.5 * invWidth * (deltaT.^2) .* (1-indT);
zT1T2Tilde = sqrt(0.5*invWidth) * (-deltaT .* (1-indT) + gammaTilde / invWidth);
if (isStationary == false)
    varphiT10 = gamma * T1;
    varphi0T2 = 0.5 * invWidth * (T2.^2);
    z0T2 = sqrt(0.5*invWidth) * (T2 + gamma/invWidth);
    varphiT10Tilde = gammaTilde * T1;
    z0T2Tilde = sqrt(0.5*invWidth) * (T2 + gammaTilde/invWidth);
    %gradThetaVarphiT10 = T1;
end

gradThetaVarphiT1T2 = deltaT .* indT;
%gradThetaZ = 1/sqrt(2*invWidth);

% Gradient w.r.t. the mass, spring and damper (lfmKern)
for i = 1:3
    gradThetaPsi = - exp(-varphiT1T2) ...
        .* (gradThetaGamma(i) * wofzHui(j*zT1T2) .* gradThetaVarphiT1T2 ...
        + sqrt(2/invWidth) * gradThetaGamma(i) * (1/sqrt(pi)-zT1T2.*wofzHui(j*zT1T2)));
    gradThetaPsiTilde = - exp(-varphiT1T2Tilde) ...
        .* (gradThetaGammaTilde(i) * wofzHui(j*zT1T2Tilde) .* gradThetaVarphiT1T2 ...
        + sqrt(2/invWidth) * gradThetaGammaTilde(i) * (1/sqrt(pi)-zT1T2Tilde.*wofzHui(j*zT1T2Tilde)));
    if (isStationary == false)
        gradThetaPsi = gradThetaPsi + exp(-(varphiT10 + varphi0T2)) ...
            .* (gradThetaGamma(i) * T1 .* wofzhui(j*z0T2) ...
            + sqrt(2/invWidth) * gradThetaGamma(i) * (1/sqrt(pi)-z0T2.*wofzHui(j*z0T2)));
        gradThetaPsiTilde = gradThetaPsiTilde + exp(-(varphiT10Tilde + varphi0T2)) ...
            .* (gradThetaGammaTilde(i) * T1 .* wofzhui(j*z0T2Tilde) ...
            + sqrt(2/invWidth) * gradThetaGammaTilde(i) * (1/sqrt(pi)-z0T2Tilde.*wofzHui(j*z0T2Tilde)));
    end
    g1(i) = sensitivity * variance * sum(sum((-(gradThetaMass(i)/mass + gradThetaOmega(i)/omega) ...
        * K + c * (gradThetaPsiTilde - gradThetaPsi)) .* covGrad));
end

% Gradient w.r.t. the inverse width (rbfKern)
gradInvWidthVarphiT1T2 = 0.5 * (deltaT.^2) .* (1-indT);
gradInvWidthZT1T2 = -(deltaT .* (1-indT) + gamma / invWidth) / sqrt(8*invWidth);
gradInvWidthZT1T2Tilde = -(deltaT .* (1-indT) + gammaTilde / invWidth) / sqrt(8*invWidth);
gradInvWidthPsi = - exp(-varphiT1T2) ...
    .* (wofzHui(j*zT1T2) .* gradInvWidthVarphiT1T2 ...
    + 2 * (1/sqrt(pi)-zT1T2.*wofzHui(j*zT1T2)) .* gradInvWidthZT1T2);
gradInvWidthPsiTilde = - exp(-varphiT1T2Tilde) ...
    .* (wofzHui(j*zT1T2Tilde) .* gradInvWidthVarphiT1T2 ...
    + 2 * (1/sqrt(pi)-zT1T2Tilde.*wofzHui(j*zT1T2Tilde)) .* gradInvWidthZT1T2Tilde);
if (isStationary == false)
    gradInvWidthVarphi0T2 = 0.5*(T2.^2);
    gradInvWidthZ0T2 = (T2 - gamma / invWidth) / sqrt(8*invWidth);
    gradInvWidthZ0T2Tilde = (T2 - gammaTilde / invWidth) / sqrt(8*invWidth);
    gradInvWidthPsi = gradInvWidthPsi + exp(-(varphiT10 + varphi0T2)) ...
        .* (gradInvWidthVarphi0T2 .* wofzhui(j*z0T2) ...
        + 2 * (1/sqrt(pi)-z0T2.*wofzHui(j*z0T2)) .* gradInvWidthZ0T2);
    gradInvWidthPsiTilde = gradInvWidthPsiTilde + exp(-(varphiT10Tilde + varphi0T2)) ...
        .* (gradInvWidthVarphi0T2 .* wofzhui(j*z0T2Tilde) ...
        + 2 * (1/sqrt(pi)-z0T2Tilde.*wofzHui(j*z0T2Tilde)) .* gradInvWidthZ0T2Tilde);
end
g2(1) = sensitivity * variance * sum(sum((c * (gradInvWidthPsiTilde - gradInvWidthPsi)) .* covGrad));

% Gradient w.r.t. sigma_r^2
g1(4) = sensitivity * sum(sum(K .* covGrad));
g2(2) = 0; % Otherwise it is counted twice

% Gradient w.r.t. sensitivity (only lfmKern)
g1(5) = variance * sum(sum(K .* covGrad));

% Ensure that the gradients are real
g1 = real(g1);
g2 = real(g2);


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

function test_meeg_baseline_correct_ft_comparison_methods()
    methods={'relative','absolute','relchange'};
    references={'manual','ft','ds'};

    combis=cosmo_cartprod({methods,references});
    ncombis=size(combis,1);

    for k=1:ncombis
        combi=combis(k,:);
        method=combi{1};
        reference=combi{2};

        % random interval
        start=rand(1)*-.25;
        dur=.05+rand(1)*.2;
        interval=start+[0 dur];

        helper_test_meeg_baseline_correct_comparison(interval,...
                                                        method,reference);
    end

function helper_test_meeg_baseline_correct_comparison(interval,method,...
                                                    reference)

    switch reference
        case 'ft'
            if cosmo_skip_test_if_no_external('fieldtrip')
                return;
            end

            if cosmo_wtf('is_octave')
                cosmo_notify_test_skipped(['ft_freqbaseline is not '...
                                                'compatible with Octave']);
            end

        case 'ds'

        case 'manual'

        otherwise
            assert(false,'this should not happen');
    end

    ds=cosmo_synthetic_dataset('type','timefreq','size','big','seed',0);
    ds.samples=randn(size(ds.samples));

    chan_to_select=cosmo_randperm(max(ds.fa.chan),ceil(rand()*3+1));
    freq_to_select=cosmo_randperm(max(ds.fa.freq),ceil(rand()*3+1));

    m=cosmo_match(ds.fa.chan,chan_to_select) & ...
            cosmo_match(ds.fa.freq,freq_to_select);
    ds=cosmo_slice(ds,m,2);
    ds=cosmo_dim_prune(ds);

    y=cosmo_meeg_baseline_correct(ds,interval,method);

    % (unsupported in octave)
    switch reference
        case 'ft'
            ft=cosmo_map2meeg(ds);

            opt=struct();
            opt.baseline=interval;
            opt.baselinetype=method;

            ft_bl=ft_freqbaseline(opt,ft);
            x=cosmo_meeg_dataset(ft_bl);

        case 'ds'
            msk=cosmo_dim_match(ds,'time',...
                        @(t) t>=min(interval) & t<=max(interval));
            ds_ref=cosmo_slice(ds,msk,2);
            x=cosmo_meeg_baseline_correct(ds,ds_ref,method);

        case 'manual'
            msk=cosmo_dim_match(ds,'time',...
                        @(t) t>=min(interval) & t<=max(interval));
            ds_ref=cosmo_slice(ds,msk,2);

            x=ds;

            for chan=1:max(ds.fa.chan)
                for freq=1:max(ds.fa.freq)
                    msk=ds.fa.chan==chan & ds.fa.freq==freq;
                    s=ds.samples(:,msk);

                    ref_msk=ds_ref.fa.chan==chan & ds_ref.fa.freq==freq;
                    r=mean(ds_ref.samples(:,ref_msk),2);

                    switch method
                        case 'absolute'
                            v=bsxfun(@minus,s,r);

                        case 'relative'
                            v=bsxfun(@rdivide,s,r);

                        case 'relchange'
                            v=bsxfun(@rdivide,bsxfun(@minus,s,r),r);

                        otherwise
                            error('not supported: %s', method);
                    end

                   x.samples(:,msk)=v;
                end
            end

        otherwise
            assert(false)

    end

    x_unq=cosmo_index_unique({x.fa.time,x.fa.chan});
    y_unq=cosmo_index_unique({y.fa.time,y.fa.chan});

    n=numel(x_unq);
    max_n_to_choose=10;
    n_to_choose=min(max_n_to_choose,n);
    rp=cosmo_randperm(n,n_to_choose);
    assert(numel(x_unq)==numel(y_unq));
    for j=1:n_to_choose;
        idx=rp(j);
        x_sel=cosmo_slice(x,x_unq{idx},2,false);
        y_sel=cosmo_slice(y,y_unq{idx},2,false);

        p=x_sel.samples;
        q=y_sel.samples;

        desc=sprintf('method %s, reference %s',method,reference);
        assertElementsAlmostEqual(p,q,...
                        'relative',1e-6,desc);
        assertEqual(x_sel.fa,y_sel.fa);

    end

    assertEqual(x.a.fdim,y.a.fdim);

function test_meeg_baseline_correct_regression()
    interval=[-.15 -.04];
    expected_samples={[ 2.7634  -2.6366   2.3689 -0.36892 -0.43043;...
                        -0.49007  -1.0933  0.79082   1.2092   0.1044 ],...
                      [ -0.63503   1.3096 -0.49296  0.49296  0.51511;...
                        -2.5308  -3.5553 -0.35529  0.35529  -1.5211 ],...
                      [ 1.7634  -3.6366   1.3689  -1.3689  -1.4304
                        -1.4901  -2.0933 -0.20918  0.20918  -0.8956 ]};
    [ds,ds_ref]=get_test_dataset(interval);

    methods={'relative','absolute','relchange'};

    ds_feature_msk=ds.fa.chan==3 & ds.fa.freq==2;

    for k=1:numel(methods)
        method=methods{k};

        for j=1:2
            if j==1
                ref=interval;
            else
                ref=ds_ref;
            end

            ds_bl=cosmo_meeg_baseline_correct(ds,ref,method);
            ds_bl_msk=ds_bl.fa.chan==3 & ds_bl.fa.freq==2;
            d=cosmo_slice(ds_bl,ds_bl_msk,2);

            assertElementsAlmostEqual(d.samples,expected_samples{k},...
                                                'absolute',1e-4);
            d_fa=cosmo_slice(ds.fa,ds_feature_msk,2,'struct');
            assertEqual(d.fa,d_fa);
        end
    end

function [ds,ds_ref]=get_test_dataset(interval)
    ds=cosmo_synthetic_dataset('type','timefreq','size','big',...
                                    'senstype','neuromag306_planar',...
                                    'nchunks',1);
    ds.sa=struct();
    ds.sa.rpt=(1:size(ds.samples,1))';
    msk=ds.fa.chan<=4 & ds.fa.freq<=2;
    ds=cosmo_slice(ds,msk,2);
    ds=cosmo_dim_prune(ds);

    matcher=@(x) interval(1) <= x & x <= interval(2);
    ds_ref=cosmo_slice(ds,cosmo_dim_match(ds,'time',matcher),2);
    ds_ref=cosmo_dim_prune(ds_ref);

function test_meeg_baseline_correct_nonmatching_sa
    ds=cosmo_synthetic_dataset('size','big','ntargets',8,...
                            'nchunks',1,'type','timelock');
    nsamples=size(ds.samples,1);

    while true
        rp=cosmo_randperm(nsamples);
        if ~isequal(rp,1:nsamples)
            break;
        end
    end
    ds_ref=cosmo_slice(ds,rp);
    assertExceptionThrown(@()cosmo_meeg_baseline_correct(...
                            ds,ds_ref,'relative'),'');

function test_meeg_baseline_correct_nonmatching_fa
    ds_big=cosmo_synthetic_dataset('size','big','ntargets',8,...
                            'nchunks',1,'type','timefreq');
    ds=cosmo_slice(ds_big,ds_big.fa.chan<=2 & ds_big.fa.freq<=3,2);
    ds_ref=cosmo_slice(ds_big,ds_big.fa.chan<=3 & ds_big.fa.freq<=2,2);

    assertExceptionThrown(@()cosmo_meeg_baseline_correct(...
                                        ds,ds_ref,'relative'),'');

function test_meeg_baseline_correct_illegal_inputs
    bc=@cosmo_meeg_baseline_correct;
    aet=@assertExceptionThrown;
    ds=cosmo_synthetic_dataset('type','timefreq','size','tiny');

    if cosmo_wtf('is_matlab')
        v=cosmo_wtf('version');
        is_prior_to_2012b=str2num(v(1))<=7;

        if is_prior_to_2012b
            id_missing_arg='MATLAB:inputArgUndefined';
        else
            id_missing_arg='MATLAB:minrhs';
        end
    else
        id_missing_arg='Octave:undefined-function';
    end

    aet(@()bc(ds,ds),id_missing_arg);
    aet(@()bc(ds,ds,'foo'),'');

    aet(@()bc(ds,cosmo_slice(ds,1),'relative'),'');
    aet(@()bc(ds,cosmo_slice(ds,1,2),'relative'),'');

    % test slicing
    bc(ds,cosmo_slice(ds,[1 2 3 4 5 6],1),'relative');
    aet(@()bc(ds,cosmo_slice(ds,[1 2 4 6 4 3],1),'relative'),'');


function outputImage = mod(this, divisor, varargin)
% Computes modulus of division with divisor
%
%   Y = MrImage();
%   modY = Y.mod(divisor)
%   modY = mod(Y);
%
%
% This is a method of class MrImage.
%
% IN
%
% OUT
%   outputImage             value modulo
%
% EXAMPLE
%   modY = mod(Y, 2*pi)
%
%   See also MrImage MrImage.perform_unary_operation

% Author:   Saskia Klein & Lars Kasper
% Created:  2014-11-29
% Copyright (C) 2014 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC Toolbox, which is released
% under the terms of the GNU General Public Licence (GPL), version 3.
% You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version).
% For further details, see the file COPYING or
%  <http://www.gnu.org/licenses/>.
%

outputImage = this.perform_unary_operation(@(x) mod(x, divisor), varargin{:});


% MODSELC Model selection
%
%   V = MODSELC(A,W,N,NREP)
%   V = A*(W*MODSELC([],N,NREP))
%
% INPUT
%   A      Dataset used for training base classifiers and/or selection
%   B      Dataset used for testing (executing) the selector
%   W      Set of trained or untrained base classifiers
%   N      Number of crossvalidations, default 10
%   NREP   Number of crossvalidation repetitions
%
% OUTPUT
%   V   Selected classidfer
%
% DESCRIPTION
% This routine selects out of a set of given classifiers stored in W the
% best one on the basis of N-fold crossvalidation (see CROSSVAL), which
% might be repeated NREP times. If W contains a set of already trained
% classifiers, N and NREP are neglected and just the best classifier
% according to the evaluation set A is returned.
%
% This routine can be considered as a classifier combiner based on global
% selection. See DCSC for local, dynamic selection.
%
% SEE ALSO (PRTools Guide)
% DATASETS, MAPPINGS, STACKED, DCSC, CLASSC, TESTD, LABELD

% Copyright: R.P.W. Duin, r.p.w.duin@37steps.com
% Faculty EWI, Delft University of Technology
% P.O. Box 5031, 2600 GA Delft, The Netherlands

function OUT = modselc(par1,par2,par3,par4)

name = 'Classifier Model Selection';
DefaultN = 10;
DefaultNrep = 1;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   Empty Call MODSELC, MODSELC([],N,NREP)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin < 1 | isempty(par1)
	if nargin > 1 & (ismapping(par2) | iscell(par2))
		if nargin < 4 | isempty(par4), par4 = DefaultNrep; end
		if nargin < 3 | isempty(par3), par3 = DefaultN; end
		OUT = prmapping(mfilename,'untrained',{par2,par3,par4});
	else
		if nargin < 3 | isempty(par3), par3 = DefaultNrep; end
		if nargin < 2 | isempty(par2), par2 = DefaultN; end
		% If there are no inputs, return an untrained mapping.
		% (PRTools transfers the latter into the first)
		OUT = prmapping(mfilename,'combiner',{par2,par3});
	end
	OUT = setname(OUT,name);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   Storing Base Classifiers:  W*MODSELC, MODSELC(W,N,NREP)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif ismapping(par1)
	if nargin < 3 | isempty(par3), par3 = DefaultNrep; end
	if nargin < 2 | isempty(par2), par2 = DefaultN; end
	% call like OUT = MODSELC(W,N) or OUT = W*MODSELC([],N)
	% store trained or untrained base classifiers,
	% ready for later training of the combiner
	BaseClassf = par1;
	if ~isparallel(BaseClassf) & ~isstacked(BaseClassf)
		error('Parallel or stacked set of base classifiers expected');
	end
	OUT = prmapping(mfilename,'untrained',{BaseClassf,par2,par3});
	OUT = setname(OUT,name);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   Selection (and training base classifiers if needed):
%   A*(W*MODSELC), A*(W*MODSELC([],N,NREP)), MODSELC(A,W,N,NREP)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif isdataset(par1) & ismapping(par2) & ...
		(isuntrained(par2) | (istrained(par2) & (isstacked(par2) | isparallel(par2))))
	% call like OUT = MODSELC(TrainSet,W,N,NREP) or TrainSet*(W*MODSELC([],N,NREP))
	% (PRTools transfers the latter into the first)
	% W is a set of trained or untrained set classifiers.
	if nargin < 4 | isempty(par4), par4 = DefaultNrep; end
	if nargin < 3 | isempty(par3), par3 = DefaultN; end
	TrainSet = par1;
	BaseClassf = par2;
	N = par3;
	Nrep = par4;
	isvaldfile(TrainSet,1,2); % at least one object per class, 2 classes
	TrainSet = setprior(TrainSet,getprior(TrainSet,0));  % avoid many warnings
	if ~(isstacked(BaseClassf) | isparallel(BaseClassf))
		if iscombiner(BaseClassf)
			error('No base classifiers found')
		end
		Data = getdata(BaseClassf);
		BaseClassf = Data.BaseClassf; % base classifiers were already stored
  end
  if isuntrained(BaseClassf)  % base classifiers untrained, crossval needed
		randstate = randreset; % makes routine reproducing
		if isparallel(BaseClassf)
			BaseClassf = getdata(BaseClassf);
			tsize = BaseClassf{end};
			if ismapping(tsize)
				error(['Training of parallel combined untrained classifier not possible.' ...
						newline 'Feature sizes should be stored in the classifier first.'])
			end
			csize = cumsum([0 tsize(:)']);
			n = length(BaseClassf)-1;
			e = zeros(1,n);
			rstate = randreset;
			s = sprintf('Crossvalidating %i base classifiers: ',n);
			prwaitbar(n,s)
			for j=1:n
				prwaitbar(n,j,[s getname(BaseClassf{j})]);
				randreset(1);
				e(j) = crossval(TrainSet(:,csize(j)+1:csize(j+1)),BaseClassf{j},N,Nrep);
			end
			prwaitbar(0);
			[ee,k] = min(e);
			J = [csize(k)+1:csize(k+1)];
			OUT = TrainSet(:,J)*BaseClassf{k};
			OUT = featsel(csize(end),J)*OUT;
		else
			if isstacked(BaseClassf)
				BaseClassf = getdata(BaseClassf);
			end
			randreset(1);
			e = crossval(TrainSet,BaseClassf,N,Nrep);
			[ee,k] = min(e);
			OUT = TrainSet*BaseClassf{k};
		end
		randreset(randstate);
	else  % base classifiers are trained, check label lists and find best one
		BaseClassf = getdata(BaseClassf);
		n = length(BaseClassf);
		for j=1:n
    	if ~isequal(getlabels(BaseClassf{j}),getlablist(TrainSet))
     		error('Training set and base classifiers should deal with same labels')
    	end
		end
		e = testc(TrainSet,BaseClassf);
		[ee,k] = min([e{:}]);
		OUT = BaseClassf{k};
  end

else

  error('Illegal input');

end


function output = callpensdpm(interfacedata);

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

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

% *******************************
% CONVERT FROM INTERNAL FORMAT
% *******************************
penstruct = sedumi2pen(F_struc,K,c,x0);

% **************************
% COPY OPTIONS
% **************************
ops = struct2cell(options.pensdp);ops = [ops{1:end}];
penstruct.ioptions = ops(1:8);
penstruct.foptions = ops(9:end);
penstruct.ioptions(4) = max(0,min(3,options.verbose+1));
if penstruct.ioptions(4)==1
    penstruct.ioptions(4)=0;
end

% FIX
if penstruct.mconstr == 0
    penstruct.msizes = [];
end

if options.savedebug
    save pensdpdebug penstruct
end

%**************************
% CALL PENSDP
%**************************
showprogress('Calling PENSDP',options.showprogress);
solvertime = tic;
[x, fx, u, iresults, fresults, iflag] = pen(penstruct);
solvertime = toc(solvertime);

% Get dual variable (this must be possible to do easier...)
u = u(:);
D_struc = u(1:1:K.l);
if length(K.s)>0
    if K.s(1)>0
        pos = K.l+1;
        for i = 1:length(K.s)
            temp = zeros(K.s(i),K.s(i));
            vecZ = u(pos:pos+0.5*K.s(i)*(K.s(i)+1)-1);
            top = 1;
            for j = 1:K.s(i)
                len = K.s(i)-j+1;
                temp(j:end,j)=vecZ(top:top+len-1);top=top+len;
            end
            temp = (temp+temp');j = find(speye(K.s(i)));temp(j)=temp(j)/2;
            D_struc = [D_struc;temp(:)];
            pos = pos + (K.s(i)+1)*K.s(i)/2;
        end
    end
end

switch iflag
case 0
    problem = 0;
case 1
    problem = 4;
case 2
    problem = 1;
case 3
    problem = 4;
case 4
    problem = 3;
case 5
    problem = 7;
case 6
    problem = 11;
case 7
    problem = 9;
otherwise
    problem = -1;
end
infostr = yalmiperror(problem,'PENSDP/TOMLAB');

if options.savesolveroutput
    solveroutput.f = f;
    solveroutput.x = x;
    solveroutput.u = u;
    solveroutput.iflag = iflag;
    solveroutput.niter = niter;
    solveroutput.feas = feas;
else
    solveroutput = [];
end
if options.savesolverinput
    solverinput.penstruct = penstruct;
else
    solverinput = [];
end

% Standard interface
output = createOutputStructure(x(:),D_struc,[],problem,infostr,solverinput,solveroutput,solvertime);


function expoTimes = ReadExpoTimes(scenePath)

[~, expPaths, ~] = GetFolderContent(scenePath, '.txt');

fid = fopen(expPaths{1});
expoTimes = 2.^cell2mat(textscan(fid, '%f'));
fclose(fid);


function f = p00_f ( problem, n, x )

%*****************************************************************************80
%
%% P00_F evaluates the objective function for any problem.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 January 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer PROBLEM, the problem number.
%
%    Input, integer N, the number of arguments.
%
%    Input, real X(N), the arguments.
%
%    Output, real F(N), the function at each argument.
%
  if ( problem == 1 )
    f = p01_f ( n, x );
  elseif ( problem == 2 )
    f = p02_f ( n, x );
  elseif ( problem == 3 )
    f = p03_f ( n, x );
  elseif ( problem == 4 )
    f = p04_f ( n, x );
  elseif ( problem == 5 )
    f = p05_f ( n, x );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'P00_F - Fatal error!\n' );
    fprintf ( 1, '  Illegal problem number PROBLEM = %d\n', problem );
    error ( 'P00_F - Fatal error!' );
  end

  return
end


function [X, meta] = xifread(filename, debug)

%xifread version 0.3 - Reads HDILab/ATL xif ultrasound data files.
%Written by Bo Lind - bolind@ikol.dk
%
%Usage: [X, meta] = xifread('myfile.xif');
%or:    [X, meta] = xifread('myfile.xif', 1); for verbose mode
%
%Where meta is an (optional) struct with the following fields:
%
%scanlines   Number of scanlines
%samples     Number of samples per scanline
%frames      Number of frames
%framerate   Frame rate
%width       Width in mm
%height      Height in mm
%
%Note, X is a three-dimensional matrix of type uint8, to save memory.
%Convert to double if needed.

%Check number of arguments. One is required, the filename, if number two
%evaluates to true, verbose/debug mode info will be printed.
if (nargin < 1)
    error('xifread: Bad number of arguments.');
elseif (nargin == 1)
    debug = 0;
elseif (nargin > 1)
    debug = 1;
end

%Open file.
FID = fopen(filename, 'r');

%Abort if error opening file (does not exist, etc.)
if (FID == -1)
    error('Error opening file: %s, aborting...', filename);
end

%Run through the XML header, reading in scanlines, samples etc.
s = [];
while (size(strfind(s, '#SOH')) == 0)
    s = fgets(FID);
        if (strfind(s, 'echoNumLines'))
        s = fgets(FID);
        s = fgets(FID);
        meta.scanlines = str2num(cell2mat(regexp(s, '(\d+)', 'match')));
    end
    if (strfind(s, 'echoNumDisplaySamples'))
        s = fgets(FID);
        s = fgets(FID);
        meta.samples = str2num(cell2mat(regexp(s, '(\d+)', 'match')));
    end
    if (strfind(s, 'numFrames'))
        s = fgets(FID);
        s = fgets(FID);
        meta.frames = str2num(cell2mat(regexp(s, '(\d+)', 'match')));
    end
    if (strfind(s, 'frameRate'))
        s = fgets(FID);
        s = fgets(FID);
        meta.framerate = str2num(cell2mat(regexp(s, '(\d+)', 'match')));
    end
    if (strfind(s, 'echoScan_linearWidth'))
        s = fgets(FID);
        s = fgets(FID);
        %Different regexp, as we need to match a decimal number.
        meta.width = str2num(cell2mat(regexp(s, '(\d+\.\d+)', 'match')));
    end
    if (strfind(s, 'echoDepth_twodDepth'))
        s = fgets(FID);
        s = fgets(FID);
        %Same as above.
        meta.height = str2num(cell2mat(regexp(s, '(\d+\.\d+)', 'match')));
    end
end

if (debug)
    fprintf('numLines: %d\n', meta.scanlines);
    fprintf('numDisplaySamples: %d\n', meta.samples);
    fprintf('numFrames: %d\n', meta.frames);
    fprintf('frameRate: %d\n', meta.framerate);
    fprintf('echoScan_linearWidth: %d\n', meta.width);
    fprintf('echoDepth_twodDepth: %d\n', meta.height);
end

%Read throuh C-style header.
s = [];
while (size(strfind(s, '#EOH')) == 0)
    s = fgets(FID);
end

%Now filepointer is at start of data. We simply read them in.
%Initializing X first, to allocate memory in a sane fashion.
X = uint8(zeros(uint16([meta.samples, meta.scanlines, meta.frames])));
for i = 1:meta.frames
    X(:,:,i) = fread(FID, [meta.samples, meta.scanlines], 'uchar');
end

fclose(FID);


function [norot, rot] = nc2010_plot_rppca_toyexperiment(n,m,d,ncomps)
%
% nc2010_plot_toyexperiment(model,n,m,d,ncomps,flatW)
%

model = 'rppca';

filename = sprintf(['/home/jluttine/matlab/neurocomputing2010/' ...
                    'nc2010_%s_toyexperiment_n=%d_m=%d_d=%d_ncomps=%d'], ...
                   model,n,m,d,ncomps);

norot = load([filename,'_rotate=0.mat'], 'duration', 'cost', 'rmse', 'rmse_test');
rot = load([filename,'_rotate=1.mat'], 'duration', 'cost', 'rmse', 'rmse_test');
plot_results(norot, rot, n,m,d,ncomps);

if nargout < 1
  clear norot;
  clear rot;
end
return
% $$$
% $$$ norot = load('rotationpaper_experiment_n=100_m=10_d=3_ncomps=9_rotate=0.mat');
% $$$ rot = load('rotationpaper_experiment_n=100_m=10_d=3_ncomps=9_rotate=1.mat');
% $$$ plot_results(norot, rot, 100,10,3,9);
% $$$
% $$$ norot = load('rotationpaper_experiment_n=1000_m=50_d=10_ncomps=49_rotate=0.mat');
% $$$ rot = load('rotationpaper_experiment_n=1000_m=50_d=10_ncomps=49_rotate=1.mat');
% $$$ plot_results(norot, rot, 1000,50,10,49);
% $$$
% $$$ norot = load('rotationpaper_experiment_n=1000_m=100_d=10_ncomps=30_rotate=0.mat');
% $$$ rot = load('rotationpaper_experiment_n=1000_m=100_d=10_ncomps=30_rotate=1.mat');
% $$$ plot_results(norot, rot, 1000,100,10,30);
% $$$
% $$$ return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function plot_results(norot, rot, n,m,d,ncomps)

% $$$ norot.cost(norot.cost==-inf) = -1e10;
% $$$ rot.cost(rot.cost==-inf) = -1e10;
suffix = sprintf(' (n=%d m=%d d=%d ncomps=%d)',n,m,d,ncomps);

figure
semilogx([norot.duration(:), rot.duration(:)], -[norot.cost(:), rot.cost(:)])
%title(['Negative loglikelihood', suffix]);
filename = sprintf('fig_cost_n=%d_m=%d_d=%d_ncomps=%d', n,m,d,ncomps);
set(gcf, 'units', 'centimeters', 'paperunits', 'centimeters');
pos = get(gcf, 'position');
set(gcf, 'position', [pos(1:2), 8,8]);
pos = get(gcf, 'paperposition');
set(gcf, 'paperposition', [pos(1:2),8,8])

figure
semilogx([norot.duration(:), rot.duration(:)], [norot.rmse(:), rot.rmse(:)])
%title(['Training set RMSE', suffix]);
filename = sprintf('fig_rmse_n=%d_m=%d_d=%d_ncomps=%d', n,m,d,ncomps);
set(gcf, 'units', 'centimeters', 'paperunits', 'centimeters');
pos = get(gcf, 'position');
set(gcf, 'position', [pos(1:2), 8,8]);
pos = get(gcf, 'paperposition');
set(gcf, 'paperposition', [pos(1:2),8,8])

figure
semilogx([norot.duration(:), rot.duration(:)], [norot.rmse_test(:), rot.rmse_test(:)])
%title(['Test set RMSE', suffix]);
filename = sprintf('fig_rmsetest_n=%d_m=%d_d=%d_ncomps=%d', n,m,d,ncomps);
set(gcf, 'units', 'centimeters', 'paperunits', 'centimeters');
pos = get(gcf, 'position');
set(gcf, 'position', [pos(1:2), 8,8]);
pos = get(gcf, 'paperposition');
set(gcf, 'paperposition', [pos(1:2),8,8])


base_graph_list = 1:2;

Z_c_list = [2, 4, 8, 16, 32, 64, 128, 256, ...
3, 6, 12, 24, 48, 96, 192, 384, ...
5, 10, 20, 40, 80, 160, 320, ...
7, 14, 28, 56, 112, 224, ...
9, 18, 36, 72, 144, 288, ...
11, 22, 44, 88, 176, 352, ...
13, 26, 52, 104, 208, ...
15, 30, 60, 120, 240];

pass_or_failure = 1;
for base_graph = base_graph_list
    for Z_c = Z_c_list
        pass_flag = test_ldpc(base_graph, Z_c);
        if ~pass_flag
          pass_or_failure = 0;
          disp(['The case base_graph = ', num2str(base_graph), ' Z_c= ', num2str(Z_c), ' passed.']);
          break;
        else
          disp(['case base_graph = ', num2str(base_graph), ' Z_c= ', num2str(Z_c), ' passed.']);
        end
    end
end

if pass_or_failure == 1
   disp('test passed.');
else
   disp('test failed.');
end


function [lin_restr,nonlin_restr,markov_chains]=create_restrictions_and_markov_chains5(markov_chains)
% create_restrictions_and_markov_chains5 -- creates restrictions and
% markov chains for the SVAR model in which both coefficients and variance
% for the monetary policy equation are changing with two independent Markov
% processes
%
% ::
%
%
%   [lin_restr,nonlin_restr,tpl]=create_restrictions_and_markov_chains5(tpl)
%
% Args:
%
%    - **markov_chains** [empty|struct]: structure of previously defined
%    markov chains
%
% Returns:
%    :
%
%    - **lin_restr** [cell]: cell array of restrictions (see below).
%
%    - **nonlin_restr** [cell]: cell array of inequality restrictions
%
%    - **markov_chains** [struct]: modified markov chains
%
% Note:
%
%    - The syntax to construct a restriction
%      --> ai(eqtn)
%      --> ai(eqtn,vbl)
%      --> ai(eqtn,vbl,chain_name,state)
%      --> a(eqtn)
%      --> a(eqtn,vbl)
%      --> a(eqtn,vbl,chain_name,state)
%      - **eqtn** [integer]: integer
%      - **vbl** [integer|char]: integer or variable name
%      - **i** [integer]: lag
%      - **chain_name** [char]: name of the markov chain
%      - **state** [integer]: state number
%
%    - The lag coefficients are labelled a0, a1, a2,...,ak, for a model with k
%    lags. Obviously, a0 denotes the contemporaneous coefficients.
%
%    - The constant terms labelled c_1_1, c_2_2,...,c_n_n, for a model with n
%    endogenous variables.
%
%    - The standard deviations labelled s_1_1, s_2_2,...,s_n_n, for a
%    model with n endogenous variables.
%
% Example:
%
%    See also:

if nargin==0||isempty(markov_chains)

    markov_chains=struct('name',{},...
    'states_expected_duration',{},...
    'controlled_parameters',{});

end

% The parameter restrictions are identical to those in the model
% with regime switching in the policy coefficients only. Hence the mp_coef
% markov chain will also be common to those two models.
[lin_restr,nonlin_restr,markov_chains]=create_restrictions_and_markov_chains3(markov_chains);

% We add the volatility Markov chain from the model in which only the
% volatility of the monetary policy equation changes. N.B: In the process,
% we want to make sure we do not over-write the restrictions above!
%--------------------------------------------------------------------------
[~,~,markov_chains]=create_restrictions_and_markov_chains4(markov_chains);

end


function N = numAtomsOfElementInFormula(formula, element, printLevel)
% Returns the number of atoms of a single element in a formula
%
% USAGE:
%
%    N = numAtomsOfElementInFormula(formula, element, printLevel)
%
% INPUTS:
%    formula:       formula in format Element then NumberOfAtoms with no spaces
%    element:       Abbreviation of element e.g. C or Mg
%    printLevel:    verbose level
%
% OUTPUT:
%    N:             number of atoms of this element in the formula provided
%
% .. Author:
%       - Ronan Fleming 9 March 09
%       - Ronan Fleming 21 July 09 handles formulae with same first letter for element e.g.C & Co in 'C55H80CoN15O11'
%       - Ronan Fleming 18 Sept 09 handles composite formulae like C62H90N13O14P.C10H11N5O3.Co
%       - Hulda SH 7 July 2011 Simplified and generalized code. Now handles most or all exceptional formulas.

if nargin < 3
    printLevel = 1;
end

if any(~isletter(element))
    disp(element)
    error('Element must not contain numbers')
end

if length(element)==1
    if ~strcmp(upper(element),element)
        disp(element)
        error('Single letter element must not be lower case')
    end
end

if ~isletter(formula(1))
    disp(formula)
    if printLevel>0
        warning('Formula format expected is element then number of elements, not the other way around')
    end
end

zero='0';
indZero=strfind(formula,zero);
if ~isempty(indZero)
    if isletter(formula(indZero-1))
        fprintf('%s%s\n','Formula before:, ', formula)
        warning('Formula contains a zero with a letter preceeding it, replacing with letter.')
        formula = strrep(formula, formula(indZero-1:indZero), formula(indZero-1));
        fprintf('%s%s\n','Formula after:, ', formula)
    end
end

%Count FULLR and FULLR2 groups as R groups (Human reconstruction)
formula = strrep(formula, 'FULLR3', 'R3');
formula = strrep(formula, 'FULLR2', 'R2');
formula = strrep(formula, 'FULLR', 'R');

element = strrep(element, 'FULLR3', 'R3');
element = strrep(element, 'FULLR2', 'R2');
element = strrep(element, 'FULLR', 'R');

if ischar(element) && ischar(formula)
    elementStart = regexp(formula, '[A-Z]', 'start'); % Get indices of all capital letters in the string formula. Treated as starting indices of elements.
    elementArray = cell(length(elementStart),2); % Initialize cell array for element symbols (Column 1) and numerical subscripts (Column 2)

    for n = 1:length(elementStart) % Loop for each element in formula
        if n < length(elementStart)
            splitFormula = formula(elementStart(n):(elementStart(n+1)-1)); % Extract section of formula from starting index of element n to starting index of element n+1

        else
            splitFormula = formula(elementStart(n):end);

        end

        if ~isempty(regexp(splitFormula, '[^a-z_A-Z]', 'once')) % If current section of formula contains non-alphabetic characters
            elementArray{n,1} = splitFormula(1:(regexp(splitFormula, '[^a-z_A-Z]', 'once')-1)); % Element symbol assumed to extend from beginning of current section to the first non-alphabetic character
            rest = splitFormula(regexp(splitFormula, '[^a-z_A-Z]', 'once'):end); % Rest of section after element symbol.

            if ~isempty(regexp(rest, '\W', 'once')) % Rest of section may contain word characters such as numbers and dots.
                if ~isempty(regexp(rest(1), '\d', 'once')) % If first character following element symbol is numeric it is assumed to represent the number of atoms of that element.
                    elementArray{n,2} = rest(1:(regexp(rest, '\W', 'once')-1)); % Extract element's numeric subscript.

                else
                    elementArray{n,2} = '1'; % If no number follows element symbol the numeric subscript is assumed to be 1.

                end

            else
                elementArray{n,2} = rest;

            end

        else
            elementArray{n,1} = splitFormula;
            elementArray{n,2} = '1';

        end
    end

    elementRows = strmatch(element, elementArray(:,1), 'exact'); % Element may appear in two different locations within formula.

    if ~isempty(elementRows)
        elementCount = zeros(length(elementRows),1);

        for m = 1:length(elementRows)
            elementCount(m,1) = str2double(elementArray{elementRows(m),2}); % Get numeric subscript by each instance of element in formula and convert from char to double

        end

        N = sum(elementCount);

    else
        N = 0;

    end

else
    if ~ischar(element)
        disp(element)
        error('Element must be given by a variable of class char')
    else
        disp(element)
        error('Formula must be given by a variable of class char')
    end
end


function inspect_pull1970

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY ft_databrowser

cfg = [];
cfg.dataset = dccnpath('/home/common/matlab/fieldtrip/data/ftp/test/ctf/Subject01.ds');
cfg = ft_definetrial(cfg);
cfg.trl = cfg.trl(1:20,:);
cfg.trl(:,3) = cfg.trl(:,1)-1;
cfg.demean = 'yes';
cfg.channel = 'MEG';
data = ft_preprocessing(cfg);

%%

cfg = [];
cfg.plotevents = 'no';
cfg.viewmode = 'vertical';
cfg.artfctdef.other.artifact = zeros(0,2);
cfg.artfctdef.blink.artifact = zeros(0,2);
cfg.artfctdef.movement.artifact = zeros(0,2);
ft_databrowser(cfg, data)

%%
% all viewmodes can work with component data

cfg = [];
cfg.method = 'pca';
comp = ft_componentanalysis(cfg, data);

%%

cfg = [];
cfg.plotevents = 'no';
cfg.viewmode = 'vertical';
ft_databrowser(cfg, comp)

%%

cfg = [];
cfg.plotevents = 'no';
cfg.viewmode = 'butterfly';
ft_databrowser(cfg, comp)

%%

cfg = [];
cfg.plotevents = 'no';
cfg.viewmode = 'component';
ft_databrowser(cfg, comp)


function [minC, maxC] = coor_extremals(C)
% usage
%   [minC, maxC] = coor_extremals(C)
%
% input
%   C = cell matrix of nested cell/numeric matrices, with numeric or empty
%       matrices at the bottom nesting level, of coordinates. These belong
%       to different graphics objects.
%
% output
%   minC = minimum coordinate over all graphics objects
%   maxC = maximum coordinate over all graphics objects
%
% See also PLOT_SCALINGS, MIN_CELL, MAX_CELL.

% depends
%   min_cell, max_cell

maxC = max_cell(C);
minC = min_cell(C);


function res = afni_isdigit(s)
% res = afni_isdigit(s);
% res(i) = 1 is s(1) is a digit between 0 and 9 (inclusive)
%
digit_msk=s >= '0' & s <= '9';
res = zeros(size(s));
res(digit_msk) = 1;

return;


function plotFTresult(u,x);
%
%  Plots the piecewise constant function u with discontinuities at x
%
[nc n]=size(u);   % nc = number of components
dp=0.8/nc;dpp=0.05;
for j=1:nc
  yhigh=max(u(j,:)); ylow=min(u(j,:));
  if ylow==yhigh,
    ylow=yhigh-0.5;
    yhigh=ylow+1;
  end;
  dy=0.05*(yhigh-ylow);
  if x(1)==x(n-1),
    xlow=x(1)-0.5;
    xhigh=xlow+1.0;
  else
    xhigh=x(n-1);
    xlow=x(1);
  end;
  dx=0.025*(xhigh-xlow);
  axis([xlow-dx,xhigh+dx,ylow-dy,yhigh+dy]);
  set(gca,'Box','on');
  x1=xlow-dx;
  for i=1:n-1
    line([x1 x(i)],[u(j,i) u(j,i)]);
    x1=x(i);
    line([x1 x1],[u(j,i) u(j,i+1)]);
  end;
  line([x1 xhigh+dx],[u(j,n),u(j,n)]);
end;


classdef Hopkins155 < handle

% The variables inside the ground-truth file are organized as follow:
% . width and height: dimensions (in pixels) of all the frames in the
%   video sequence.
% . points: number of tracked points P.
% . frames: number of frames F.
% . y: a matrix 3xPxF containing the homogeneous coordinates of the P
%   points in the F frames.
% . x: a matrix 3xPxF derived from y by normalizing the first two
%   components of each vector such that they belong to the interval
%   [-1;1].
% . K: the 3x3 normalization matrix used to pass from y to x
%   (x=K^(-1)*x).
% . s: a Px1 vector containing the ground-truth segmentation; for each
%   point it gives the index of the corresponding motion group.

properties(SetAccess=private)
    root_dir
    % names of examples
    example_names
    % paths of example data
    example_paths
    % data of each example
    examples
    % number of motions
    num_motions
end

methods

    function self = Hopkins155()
        self.root_dir = spx.data.local.hopkins155_dir();
        self.example_names = cell(0, 1);
        self.example_paths = cell(0, 1);
        self.load();
    end

    function load(self)
        listing = dir(self.root_dir);
        for i=1:length(listing)
            % we iterate through each directory
            entry = listing(i);
            if ~entry.isdir
                continue;
            end
            % ignore . and .. directories
            if strcmp(entry.name, '.')
                continue;
            end
            if strcmp(entry.name, '..')
                continue;
            end
            subdir = fullfile(self.root_dir, entry.name);
            sub_listing = dir(subdir);
            % the directory must have a file with _truth.mat extension
            valid_data = false;
            for j=1:length(sub_listing)
                subentry = sub_listing(j);
                fname = subentry.name;
                tmp = strfind(fname, '_truth.mat');
                if ~isempty(tmp)
                    valid_data = true;
                    break;
                end
            end
            if ~valid_data
                % we can ignore this directory
                continue;
            end
            self.example_names{end+1} = entry.name;
            self.example_paths{end+1} = fullfile(subdir, fname);
        end
        % data will be loaded in this array
        self.examples = cell(1, length(self.example_names));
        self.num_motions = zeros(1, length(self.example_names));
    end

    function result = num_examples(self)
        result = length(self.example_names);
    end

    function result = get_example(self, n)
        if n < 1 || n > self.num_examples()
            error('Invalid example number.');
        end
        result = self.examples{n};
        if isempty(result)
            % this example is not yet loaded.
            path = self.example_paths{n};
            data = load(path);
            % let's fill up more info
            s = data.s;
            % ensure that s is a row vector
            if iscolumn(s)
                s = s';
            end
            result.num_motions = max(s);
            % let us work through the labels to reorder them
            % such that points from each subspace are adjacent.
            mapping = [];
            counts = [];
            labels = [];
            for k=1:result.num_motions
                % entries for k-th cluster
                entries = find(s == k);
                mapping = [mapping entries];
                count = length(entries);
                counts = [counts count];
                labels = [labels k*ones(1, count)];
            end
            % labels of points
            result.labels = labels;
            % counts of each cluster
            result.counts = counts;
            x = data.x;
            % reorder x
            x = x(:, mapping, :);
            % number of points
            S = size(x, 2);
            % number of frames
            F = size(x, 3);
            result.num_frames = F;
            result.num_points = S;
            % Ambient dimension
            M = 2 * F;
            result.M  = M;
            self.num_motions(n) = result.num_motions;
            % reshape the data in x for clustering purpose
            % drop the third component of each point in x [homogeneous part]
            x = x(1:2,:,:);
            % now x is 2xPxF (P : points, F is frames)
            % bring frames dimension ahead and points dimension behind
            x = permute(x,[1 3 2]);
            % Now map the 2 coordinates of each point in each column
            X = reshape(x,M,S);
            result.X = X;
            % associate example name
            result.name = self.example_names{n};
            % clean up unnecessary fields
            %fields = {'x', 'y', 's', 'width', 'height', 'frames', 'K'};
            %rmfield(result, fields);
            % finally store it.
            self.examples{n} = result;
        end
    end

    function load_all_examples(self)
        n = self.num_examples;
        for i=1:n
            self.get_example(i);
        end
    end

    function result = get_all_examples(self)
        self.load_all_examples();
        result = self.examples;
    end

    function result = get_2_3_motions(self)
        self.load_all_examples();
        index2 = find(self.num_motions == 2);
        index3 = find(self.num_motions == 3);
        index = [index2 index3];
        result = self.examples(index);
    end

    function result = num_2_motions(self)
        result = sum(self.num_motions == 2);
    end

    function result = num_3_motions(self)
        result = sum(self.num_motions == 3);
    end

    function result = num_5_motions(self)
        result = sum(self.num_motions == 5);
    end

    function result = get_2_motions(self)
        self.load_all_examples();
        % identify 2 motions
        indices = find(self.num_motions == 2);
        result = self.examples(indices);
    end

    function result = get_3_motions(self)
        self.load_all_examples();
        % identify 3 motions
        indices = find(self.num_motions == 3);
        result = self.examples(indices);
    end

    function result = get_5_motions(self)
        self.load_all_examples();
        % identify 5 motions
        indices = find(self.num_motions == 5);
        result = self.examples(indices);
    end

    function describe(self)
        % ensure that all examples are loaded
        self.load_all_examples();
        fprintf('2 motions: %d\n', self.num_2_motions());
        fprintf('3 motions: %d\n', self.num_3_motions());
        fprintf('5 motions: %d\n', self.num_5_motions());
    end

end

end