% STD_FILEINFO - Check uniform channel distribution across datasets
%
% Usage:
%   >> [struct filepresent] = std_fileinfo(ALLEEG);
% Inputs:
%   ALLEEG    - EEGLAB ALLEEG structure
%
% Outputs:
%   struct      - structure of the same length as the ALLEEG variable
%                 containing all the fields in the datafiles
%   filepresent - array of 0 and 1 indicating if the file is present for
%                 each dataset
%
% Authors: Arnaud Delorme, SCCN/UCSD, CERCO/CNRS, 2010-

% Copyright (C) Arnaud Delorme
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function [tmpstructout compinds filepresent] = std_fileinfo( ALLEEG, filetype );

    firstpass   = 1;
    notequal = 0;
    compinds = {};
    tmpstructout = [];
    filepresent = zeros(1,length(ALLEEG));
    for dat = 1:length(ALLEEG)

        filename = fullfile(ALLEEG(dat).filepath, [ ALLEEG(dat).filename(1:end-3) filetype ]);
        thisfilepresent = exist(filename);
        if thisfilepresent && firstpass == 1
            %fprintf('Files of type "%s" detected, checking...',  filetype);
        elseif firstpass == 1
            notequal = 1;
        end
        firstpass = 0;
        filepresent(dat) = thisfilepresent;

        if filepresent(dat)
            try
                warning('off', 'MATLAB:load:variableNotFound');
                tmptmpstruct = load( '-mat', filename, 'times', 'freqs', 'parameters', 'labels', 'chanlabels' );
                warning('on', 'MATLAB:load:variableNotFound');
            catch
                passall = 0;
                fprintf(' Error\n');
                break;
            end

            % rename chanlabels and store structure
            if isfield(tmptmpstruct, 'chanlabels')
                tmptmpstruct.labels = tmptmpstruct.chanlabels;
                tmptmpstruct = rmfield(tmptmpstruct, 'chanlabels');
            end

            if filetype(1) ~= 'd' % ICA components
                allvars = whos('-file', filename);
                tmpinds = [];
                for cind = 1:length(allvars)
                    str = allvars(cind).name(5:end);
                    ind_ = find(str == '_');
                    if ~isempty(ind_), str(ind_:end) = []; end
                    tmpinds = [ tmpinds str2num(str) ];
                end
                compinds(dat) = { unique(tmpinds) };
            elseif ~isfield(tmptmpstruct, 'labels')
                allvars = whos('-file', filename);
                allvarnames = { allvars.name };
                tmptmpstruct.labels = allvarnames(strmatch('chan', allvarnames));
            end
            try,
                tmpstruct(dat) = tmptmpstruct;
            catch,
                passall = 0;
                break;
            end
        end
    end
    if exist('tmpstruct') == 1
        tmpstructout = tmpstruct;
    end


function plot_detector_wiggle_voc07()

  colormap = [ ...
    83, 136, 173 ; ...
    219, 135, 45 ; ...
    218, 71, 56 ; ...
    135, 130, 174 ; ...
    142, 195, 129 ; ...
    138, 180, 66 ; ...
    223, 200, 51 ; ...
    92, 172, 158 ; ...
    ] ./ 256;

  config = [];
  config(1).name = 'R-CNN';
  config(1).func = @detector_wiggle_rcnn;
  config(1).filename = '/BS/candidate_detections/work/v1/pascal_voc07_test_rcnn_scoremaps-3d.mat';
  config(2).name = 'LM-LLDA';
  config(2).func = @detector_wiggle_rcnn;
  config(2).filename = '/BS/candidate_detections/work/v1/pascal_voc07_test_dpm_scoremaps-3d.mat';
  config(3).name = 'LM-LLDA bboxpred';
  config(3).func = @detector_wiggle_rcnn;
  config(3).filename = '/BS/candidate_detections/work/v1/pascal_voc07_test_dpm_bboxpred_scoremaps-3d.mat';
  config(4).name = 'Fast R-CNN';
  config(4).func = @detector_wiggle_from_iou_score;
  config(4).filename = '/BS/candidate_detections/work/v1/pascal_voc07_test_frcn_iou_score.mat';
  config(5).name = 'Fast R-CNN bboxpred';
  config(5).func = @detector_wiggle_from_iou_score;
  config(5).filename = '/BS/candidate_detections/work/v1/pascal_voc07_test_frcn_regr_iou_score.mat';

  autoscale = true;

  bin_edges = 0.2:0.05:1;
  bin_centers = (bin_edges(1:end-1) + bin_edges(2:end)) / 2;

  hists = build_histograms(config, bin_edges);
  if autoscale
    hists = autoscale_per_class(hists);
  end

  plot_histograms(config, bin_centers, bin_edges, hists.avg_scores, hists.class_avg_scores, colormap);
%   plot_histograms(config, bin_centers, bin_edges, hists.median_scores, hists.class_median_scores, colormap);

%   figure;
%   bar(bin_centers', hists.bin_counts');
%   legend({config.name}, 'Location', 'SouthEast');

  if false
    scale_factors = [0.8182    0.8485    0.8864    0.9242    0.9621    1.0000    1.0455    1.0833    1.1288  1.1742    1.2273];
    x = (-5:5) .* 4*227/128;
    y = x;
    ticks = [-5 -2 0 2 5] .* 4*227/128;
    tick_labels = arrayfun(@(t) sprintf('%.0f', t), ticks(:), 'UniformOutput', false);
    method_i = 1;
    n_steps = size(hists.avg_cubes{method_i},1);
    class_cubes = hists.method_class_avg_cubes(method_i,:);
    n_classes = numel(class_cubes);
    % normalize per class
    for c = 1:n_classes
      clims = [min(class_cubes{c}(:)), max(class_cubes{c}(:))];
      class_cubes{c} = (class_cubes{c} - clims(1)) ./ (clims(2) - clims(1));
    end
    cube = nanmean(cat(4, class_cubes{:}), 4);

    clims = [min(cube(:)), max(cube(:))];

    figure;
    scale_idxs = [1 3 6 9 11];
    for j = 1:numel(scale_idxs), i = scale_idxs(j); % 1:n_steps
      subplot(1,6,j);
      imagesc(x, y, cube(:,:,i), clims);
      set(gca, 'XTick', ticks, 'XTickLabels', tick_labels);
      set(gca, 'YTick', ticks, 'YTickLabels', tick_labels);
      axis square
      title(sprintf('scale %.2f', scale_factors(i)));
    end
    subplot(1,6,6);
    axis off
    cbh = colorbar();
    P = get(cbh, 'Position');
    set(cbh, 'Position', [P(1)-0.01, P(2)+0.1, P(3)+0.01, P(4)-0.2]);
    hei = 3.5; wid = 25;
    set(gcf, 'Units','centimeters', 'Position',[0 0 wid hei]);
    set(gcf, 'PaperPositionMode','auto');
    printpdf('figures/detector_scoremaps_pos_scale_voc07.pdf');
    printpng('figures/detector_scoremaps_pos_scale_voc07.png');

%     figure;
%     for i = 1:n_steps
%       subplot(4,3,i);
%       imagesc(reshape(hists.avg_cubes{method_i}(:,i,:), [n_steps n_steps]), clims);
%       axis equal
%       title(sprintf('x jitter %d', i - floor((n_steps+1)/2)));
%     end
%
%     figure;
%     for i = 1:n_steps
%       subplot(4,3,i);
%       imagesc(reshape(hists.avg_cubes{method_i}(i,:,:), [n_steps n_steps]), clims);
%       axis equal
%       title(sprintf('y jitter %d', i - floor((n_steps+1)/2)));
%     end
  end
end

function plot_histograms(config, bin_centers, bin_edges, avg_scores, class_avg_scores, colormap)
  ld = load('data/classes.mat');
  classes = ld.classes;

  fh_all_classes = figure; hold on;
  for i = 1:numel(config)
    plot(bin_centers, avg_scores(i,:), '.-', 'LineWidth', 1.5, 'Color', colormap(i,:), 'MarkerSize', 20);
  end
  legend({config.name}, 'Location', 'SouthEast');
  xlabel('IoU with GT'); ylabel('detector score');
  xlim([min(bin_edges), max(bin_edges)]);
  hei = 8; wid = 12;
  set(gcf, 'Units','centimeters', 'Position',[0 0 wid hei]);
  set(gcf, 'PaperPositionMode','auto');
  printpdf('figures/detector_scoremaps_voc07.pdf');

  fh_per_class = figure;
  for c = 1:20
    for i = 1:numel(config)
      figure(fh_per_class); subplot(4,5,c);
      plot(bin_centers, class_avg_scores{c}(i,:), '-o', 'LineWidth', 2, 'Color', colormap(i,:));
      hold on;
      xlim([min(bin_edges), max(bin_edges)]);
      title(classes{c});
    end
  end
end

% function [avg_scores, bin_counts, class_avg_scores, class_bin_counts, avg_cubes] = build_histograms(config, bin_edges)
function hists = build_histograms(config, bin_edges)
  histogram_cache_file = 'data/score_histogram_cache.mat';
  try
    hists = load(histogram_cache_file);
  catch
    n_methods = numel(config);
    n_classes = 20;
    n_bins = numel(bin_edges)-1;

    % allocate
    avg_scores = zeros(n_methods, n_bins);
    median_scores = zeros(n_methods, n_bins);
    bin_counts = zeros(n_methods, n_bins);
    class_avg_scores = cell(1, n_classes);
    class_median_scores = cell(1, n_classes);
    class_bin_counts = cell(1, n_classes);
    for c = 1:n_classes
      class_avg_scores{c} = zeros(n_methods, n_bins);
      class_median_scores{c} = zeros(n_methods, n_bins);
      class_bin_counts{c} = zeros(n_methods, n_bins);
    end
    avg_cubes = cell(n_methods,1);
    method_class_avg_cubes = cell(n_methods,n_classes);

    % compute stuff
    for i = 1:n_methods, conf = config(i);
      fprintf('computing %d/%d %s\n', i, numel(config), conf.name);
      [overlap, score, class_ids, avg_cubes{i}, class_avg_cubes] = conf.func(conf.filename);
      if ~isempty(class_avg_cubes)
        method_class_avg_cubes(i,:) = class_avg_cubes;
      end

      [bin_counts(i,:), avg_scores(i,:), median_scores(i,:)] = build_histogram(overlap, score, bin_edges);

      fprintf('per class: ');
      for c = 1:n_classes
        fprintf('%d ', c);
        class_mask = class_ids == c;
        class_overlap = overlap(class_mask);
        class_score = score(class_mask);
        [class_bin_counts{c}(i,:), class_avg_scores{c}(i,:), class_median_scores{c}(i,:)] = build_histogram(class_overlap, class_score, bin_edges);
      end
      fprintf('\n');
    end

    save(histogram_cache_file, 'avg_scores', 'median_scores', 'bin_counts', ...
      'class_avg_scores', 'class_median_scores', 'class_bin_counts', ...
      'avg_cubes', 'method_class_avg_cubes');
    hists = load(histogram_cache_file);
  end
end

function [hists] = autoscale_per_class(hists)
  n_classes = 20;
  n_methods = size(hists.avg_scores,1);
  n_bins = size(hists.avg_scores,2);

  denom = zeros(n_methods,n_bins);
  hists.avg_scores = zeros(n_methods,n_bins);
  hists.median_scores = zeros(n_methods,n_bins);
  for c = 1:n_classes
    hists.class_avg_scores{c} = autoscale_scores(hists.class_avg_scores{c});
    hists.class_median_scores{c} = autoscale_scores(hists.class_median_scores{c});

    hists.avg_scores = hists.avg_scores + hists.class_avg_scores{c} .* hists.class_bin_counts{c};
    hists.median_scores = hists.median_scores + hists.class_median_scores{c} .* hists.class_bin_counts{c};
    denom = denom + hists.class_bin_counts{c};
  end
  hists.avg_scores = hists.avg_scores ./ denom;
  hists.median_scores = hists.median_scores ./ denom;
  assert(all(denom(:) == hists.bin_counts(:)));
end

function scaled_scores = autoscale_scores(avg_scores)
  minscore = min(avg_scores, [], 2);
  maxscore = max(avg_scores, [], 2);
  minscore = repmat(minscore, [1, size(avg_scores, 2)]);
  maxscore = repmat(maxscore, [1, size(avg_scores, 2)]);
  scaled_scores = (avg_scores - minscore) ./ (maxscore - minscore);
end

function [counts, avg_scores, median_scores] = build_histogram(overlap, score, bin_edges)
%     [counts,~,bin_idxs] = histcounts(overlap, bin_edges);
  [counts,bin_idxs] = histc(overlap, bin_edges);
  counts = counts(1:end-1);

  n_centers = numel(bin_edges)-1;
  avg_scores = zeros(1, n_centers);
  median_scores = zeros(1, n_centers);
  % average over the elements in each bin
  for j = 1:n_centers
    bin_scores = score(bin_idxs == j);
    if ~isempty(bin_scores)
      avg_scores(j) = mean(bin_scores);
      median_scores(j) = median(bin_scores);
    end
  end
end


function test_bug542

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

load(dccnpath('/home/common/matlab/fieldtrip/data/test/bug542.mat'));

% this is confusing the plotting function
att_dep_ipsi = rmfield(att_dep_ipsi, 'time');

stopwatch = tic;
ft_multiplotER(cfg, att_dep_ipsi);
toc(stopwatch)


function setupDataOpts(vocYear, testName, datasetDir)

global DATAopts;

% Setup VOC data
devkitroot = [datasetDir, 'VOCdevkit', '/'];
DATAopts.year = vocYear;
DATAopts.dataset = sprintf('VOC%d', DATAopts.year);
DATAopts.datadir        = [devkitroot, DATAopts.dataset, '/'];
DATAopts.resdir         = [devkitroot, 'results', '/', DATAopts.dataset '/'];
DATAopts.localdir       = [devkitroot, 'local', '/', DATAopts.dataset, '/'];
DATAopts.gStructPath    = [DATAopts.resdir, 'GStructs', '/'];
DATAopts.imgsetpath     = [DATAopts.datadir, 'ImageSets', '/', 'Main', '/', '%s.txt'];
DATAopts.imgpath        = [DATAopts.datadir, 'JPEGImages', '/', '%s.jpg'];
DATAopts.clsimgsetpath  = [DATAopts.datadir, 'ImageSets', '/', 'Main', '/', '%s_%s.txt'];
DATAopts.annopath       = [DATAopts.datadir, 'Annotations', '/', '%s.xml'];
DATAopts.annocachepath	= [DATAopts.localdir, '%s_anno.mat'];
DATAopts.classes={...
    'aeroplane'
    'bicycle'
    'bird'
    'boat'
    'bottle'
    'bus'
    'car'
    'cat'
    'chair'
    'cow'
    'diningtable'
    'dog'
    'horse'
    'motorbike'
    'person'
    'pottedplant'
    'sheep'
    'sofa'
    'train'
    'tvmonitor'};
DATAopts.nclasses = length(DATAopts.classes);
DATAopts.testset = testName;
DATAopts.minoverlap = 0.5;


function [grad]= B_linear(future_layers, curr_layer)
grad = GetFutureGrad(future_layers, curr_layer);
end


function [] = savefig(image_name,font_size,formats)
%   SAVEFIG   save current figure in image file
%       [] = SAVEFIG(IMAGE_NAME,FONT_SIZE)
%
%   Created by Alexandre Gramfort on 2008-11-11.
%   Copyright (c) 2007 Alexandre Gramfort. All rights reserved.

% $Id: savefig.m 4 2009-08-15 21:10:35Z gramfort $
% $LastChangedBy: gramfort $
% $LastChangedDate: 2009-08-15 17:10:35 -0400 (Sam, 15 aoû 2009) $
% $Revision: 4 $

% hack
return

if nargin < 3
    formats = {'png'};
end

if nargin < 2
    font_size = 22;
end

if ~exist('image_name')
    image_name = get(gcf,'Name');
end

all_axis = get(gcf,'children');

name_eps = [image_name,'.eps'];
name_jpg = [image_name,'.jpg'];
name_png = [image_name,'.png'];
name_pdf = [image_name,'.pdf'];

for ii=1:length(all_axis)
    try
        title(all_axis(ii),' ')
        set(all_axis(ii),'FontSize',font_size);
        set(get(all_axis(ii),'xlabel'),'FontSize',font_size);
        set(get(all_axis(ii),'ylabel'),'FontSize',font_size);
        set(get(all_axis(ii),'zlabel'),'FontSize',font_size);
    end
end

if any(strcmp('png',formats))
    saveas(gcf,name_png,'png');
    %%% try to trim png file
    disp('please wait, trim png file....');
    command = sprintf(['convert -trim %s %s'],name_png,name_png);
    [STATUSVAR,STATUSMESSAGE] = unix(command);

    if STATUSVAR ~= 0
       error( STATUSMESSAGE );
    else
       disp('trim completed');
    end
end

if any(strcmp('pdf',formats))
    print_pdf(name_pdf,gcf);
end

if any(strcmp('eps',formats))
    saveas(gcf,name_eps,'epsc');
end

if any(strcmp('jpg',formats))
    saveas(gcf,name_jpg,'jpg');
end


function pvpmod(x)
% PVPMOD             - evaluate parameter/value pairs
% pvpmod(x) assigns the value x(i+1) to the parameter defined by the
% string x(i) in the calling workspace. This is useful to evaluate
% <varargin> contents in an mfile, e.g. to change default settings
% of any variable initialized before pvpmod(x) is called.
%
% (c) U. Egert 1998

%############################################
% this loop is assigns the parameter/value pairs in x to the calling
% workspace.

if ~isempty(x)
   for i = 1:2:size(x,2)
      assignin('caller', x{i}, x{i+1});
   end;
end;

%############################################


function test_bug2909

% WALLTIME 00:10:00
% MEM 3gb
% DEPENDENCY ft_read_cifti

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

%%
% this is the data mentioned by JM on http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=2865
filename1 = 'RSN-networks.32k_fs_LR.dlabel.nii';
filename2 = 'RSN-networks.32k_fs_LR.dlabel.nii';
surfL = 'Q1-Q6_R440.L.midthickness.32k_fs_LR.surf.gii';
surfR = 'Q1-Q6_R440.R.midthickness.32k_fs_LR.surf.gii';

cii1 = ft_read_cifti(filename1, 'cortexleft', surfL, 'cortexright', surfR, 'mapname', 'field');
cii2 = ft_read_cifti(filename2, 'cortexleft', surfL, 'cortexright', surfR, 'mapname', 'array');

% this is the file I got from Mike Harms over email
filename3 = 'rfMRI_REST1_LR_Atlas_stats_ALLCOL_MEAN.dscalar.nii';
filename4 = 'rfMRI_REST1_LR_Atlas_stats_ALLCOL_MEAN.dscalar.nii';

cii3 = ft_read_cifti(filename3, 'debug', true, 'maplabel', 'field');
cii4 = ft_read_cifti(filename4, 'debug', true, 'maplabel', 'array');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% try writing them and subsequently reading them again

filename1b = tempname;
ft_write_cifti(filename1b, cii1, 'parameter', 'rsn_consensus_communities___pcn11__power_neuron11');
d = dir([filename1b '*.nii']);
filename1b = fullfile(fileparts(filename1b), d.name); % determine the name of the cii file
cii1b = ft_read_cifti(filename1b, 'cortexleft', surfL, 'cortexright', surfR);
assert(isequal(cii1.rsn_consensus_communities___pcn11__power_neuron11, cii1b.dscalar));

%% this one does not work yet
% filename2b = tempname;
% ft_write_cifti(filename2b, cii2, 'parameter', 'x32k_fs_lr');
% d = dir([filename2b '*.nii']);
% filename1b = fullfile(fileparts(filename2b), d.name); % determine the name of the cii file
% cii2b = ft_read_cifti(filename1b, 'cortexleft', surfL, 'cortexright', surfR);


% Init Script
% Remarks:
%   1.  sa
% TODO:
% 	1.  ds
% Release Notes
% - 1.0.000     08/11/2016  Royi Avital
%   *   First release.
%

%% General Parameters
close('all');
clear();
clc();

% set(0, 'DefaultFigureWindowStyle', 'docked');
% defaultLoosInset = get(0, 'DefaultAxesLooseInset');
% set(0, 'DefaultAxesLooseInset', [0.05, 0.05, 0.05, 0.05]);

figPosSmall     = [100, 100, 400, 300];
figPosMedium    = [100, 100, 800, 600];
figPosLarge     = [100, 100, 960, 720];
figPosDefault   = [100, 100, 560, 420];

fontSizeTitle   = 14;
fontSizeAxis    = 12;
fontSizeString  = 12;

lineWidthThin   = 1;
lineWidthNormal = 3;
lineWidthThick  = 4;

markerSizeSmall     = 4;
markerSizeNormal    = 8;
markerSizeLarge     = 10;

randomNumberStream  = RandStream('mlfg6331_64', 'NormalTransform', 'Ziggurat');
subStreamNumber     = round(sum(clock()));
% subStreamNumber     = 162;
% subStreamNumber     = 2122;
set(randomNumberStream, 'Substream', subStreamNumber);
RandStream.setGlobalStream(randomNumberStream);

FALSE   = 0;
TRUE    = 1;

OFF     = 0;
ON      = 1;


function H= grid_addBars(fv, varargin)
%GRID_ADDBARS - Add a Colorbar to the Bottom of Each Subplot of a Grid Plot
%
%Synopsis:
% H= grid_addBars(FV, <opt>)
%
%Input:
% FV: data structure (like epo)
% OPT: struct or property/value list of optional properties:
%  .Height    - Height of the colorbar
%  .HScale    - Handle to the scale of the grid plot (returned by
%               grid_plot as .scale), a colorbar will be placed next to
%               the scale
%  .ShiftAxes - 'position' or 'ylim'
%  .CLim      - Color limit of colorbar, either a 1-by-2 vector giving
%               the limit or 'auto' (default)
%  .Colormap  - The colormap of colorbar, either a x-by-3 vector giving
%               the explicit map, or one of the predefined maps (see
%               help of 'colormap')
%  .Channels  - Channels for which bar should be added, either a cell
%               of strings giving the channels names, or en empty array
%               for all channels, or 'plus'
%  .Scale*    - with * in {'Height','Width','VPos','LeftShift',
%               'FontSize','Digits','Unit'} define the appearance of
%               the scale
%
%Output:
%   H - handle to graphic objects
%
%Caveat:
% You have to make sure that the FV data fits to the data that was displayed
% with grid_plot before (e.g. for the length of the vector in the time
% dimension). The channels are matched automatically. FV may have less
% channels than displayed by grid_plot.
%
%Example:
% H= grid_plot(epo, mnt, defopt_erps)
% epo_rsq= proc_r_square_signed(epo);
% grid_addBars(epo_rsq, 'HScale',H.scale)

props= {'VPos',                 0,                      'DOUBLE';
        'Height',               1/15,                   'DOUBLE';
        'ShiftAxes',            'ylim',                 'CHAR';
        'ShiftAlso',            {'scale'},              'CELL{CHAR}';
        'CLim',                 'auto',                 'CHAR|DOUBLE[2]';
        'Colormap',             flipud(gray(32)),       'DOUBLE[- 3]';
        'UseLocalColormap',     1,                      'BOOL';
        'MoveBack',             0,                      'BOOL';
        'Box',                  'on',                   'CHAR';
        'Visible',              'off',                  'CHAR';
        'AlphaStepsMode',       0,                      'BOOL';
        'HScale',               [],                     'STRUCT(ax)';
        'ScaleHeight',          .66,                    'DOUBLE';
        'ScaleWidth',           .075,                   'DOUBLE';
        'ScaleVPos',            .25,                    'DOUBLE';
        'ScaleLeftShift',       .05,                    'DOUBLE';
        'ScaleFontSize',        get(gca,'FontSize'),    'DOUBLE';
        'ScaleDigits',          4                       'DOUBLE';
        'ScaleUnit',            ''                      'CHAR';
        'Channels',             '*'                     'CHAR|DOUBLE'};

if nargin==0,
  H= props; return
end

opt= opt_proplistToStruct(varargin{:});
[opt, isdefault]= opt_setDefaults(opt, props);
opt_checkProplist(opt, props);

if ndims(fv.x)>2
  error('only one Class allowed');
end

if min(fv.x(:))<0,
  if isdefault.CLim,
    opt.CLim= 'sym';
  end
end
if isdefault.Colormap && ...
        (isequal(opt.CLim,'sym') || (isnumeric(opt.CLim) && opt.CLim(1)<0)),
  opt.Colormap= cmap_posneg(21);
end

if isdefault.AlphaStepsMode && ...
      isfield(fv, 'ClassName') && ...
      ~isempty(findstr(fv.ClassName{1},'alpha-steps')),
  opt.AlphaStepsMode= 1;
end
if opt.AlphaStepsMode,
  nValues= length(fv.alpha);
  [opt, isdefault]= ...
      opt_overrideIfDefault(opt, isdefault, ...
                            'CLim', [0 nValues], ...
                            'Colormap', flipud(gray(nValues+1)), ...
                            'ScaleUnit', '%');
end
if isdefault.ScaleUnit && isfield(fv, 'yUnit'),
  opt.ScaleUnit= fv.yUnit;
end
if isdefault.ScaleVPos && isempty(opt.ScaleUnit),
  opt.ScaleVPos= 0.5;
end
if isdefault.Visible && strcmpi(opt.Box, 'on'),
  opt.Visible= 'on';
end
if isdefault.UseLocalColormap,
  if visutil_isColormapUsed && ~isequal(opt.Colormap, get(gcf, 'colormap')),
    opt.UseLocalColormap= 1;
  end
end

[AxesStyle, lineStyle]= opt_extractPlotStyles(opt);

if opt.UseLocalColormap,
  iswhite= find(all(opt.Colormap==1,2));
  if ~isempty(iswhite),
    opt.Colormap(iswhite,:)= 0.9999*[1 1 1];
  end
  H.image= 'sorry: fakeimage - no handle';
else
  set(gcf, 'colormap',opt.Colormap);
end

if isnumeric(opt.Channels)
  ax= opt.Channels;
else
  ax= gridutil_getSubplots(opt.Channels);
end

% For image_localColormap we have to determine the CLim in advance.
% Therefore we need to determine the depicted channels.
% (If only image was used, this functions would be simpler.)
clab= cell(1, length(ax));
for ii= 1:length(ax),
  clab{ii}= getfield(get(ax(ii), 'userData'), 'chan');
  if iscell(clab{ii}),
    clab{ii}= clab{ii}{1};  % for multiple channels per ax, choose only
                            % the first one
  end
end
if strcmpi(opt.CLim, 'auto'),
  ci= util_chanind(fv, clab);
  mi= min(min(fv.x(:,ci)));
  if mi>=0 && isdefault.CLim,
    warning('know-it-all: switching to CLim mode ''0tomax''');
    opt.CLim= '0tomax';
  else
    opt.CLim= [mi max(max(fv.x(:,ci)))];
  end
elseif strcmpi(opt.CLim, 'sym'),
  ci= util_chanind(fv, clab);
  mi= min(min(fv.x(:,ci)));
  ma= max(max(fv.x(:,ci)));
  mm= max(abs(mi), ma);
  opt.CLim= [-mm mm];
end
if strcmpi(opt.CLim, '0tomax'),
  ci= util_chanind(fv, clab);
  opt.CLim= [0 max(max(fv.x(:,ci)))];
end

jj= 0;
for ii= 1:length(ax),
  set(ax(ii), 'YLimMode','manual');
  ud= get(ax(ii), 'userData');
  if iscell(ud.chan),
    ud.chan= ud.chan{1};  % for multiple channels per axis take only the first
  end
  ci= util_chanind(fv, ud.chan);
  if isempty(ci) && isempty(strmatch(ud.chan,opt.ShiftAlso,'exact')),
    continue;
  end
  pos= get(ax(ii), 'position');
  bar_pos= [pos(1:3) opt.Height*pos(4)];
  bar_pos(2)= pos(2) + opt.VPos*(1-opt.Height)*pos(4);
  switch(opt.ShiftAxes)
    case {1,'position'},
     if opt.VPos<0.5,
       new_pos= [pos(1) pos(2)+bar_pos(4) pos(3) pos(4)*(1-opt.Height)];
     else
       new_pos= [pos(1:3) pos(4)*(1-opt.Height)];
       if opt.VPos==1,
         axis_raiseTitle(ax(ii), opt.Height);
       end
     end
     set(ax(ii), 'position',new_pos);
    case {2,'ylim'},
     yLim= get(ax(ii), 'yLim');
     if opt.VPos<0.5,
       yLim(1)= yLim(1) - opt.Height*diff(yLim);
     else
       yLim(2)= yLim(2) + opt.Height*diff(yLim);
     end
     set(ax(ii), 'yLim',yLim);
   otherwise,
    error('ShiftAxes policy not known');
  end
  if isempty(ci),
    continue;
  end
  jj= jj+1;
  H.ax(jj)= axes('position', bar_pos);
  set(H.ax(jj), AxesStyle{:});
  hold on;      % otherwise axis properties like ColorOrder are lost
  if opt.UseLocalColormap,
    fv.x(fv.x > opt.CLim(2)) = opt.CLim(2);
    fv.x(fv.x < opt.CLim(1)) = opt.CLim(1);
    image_localColormap(fv.x(:,ci)', opt.Colormap, 'CLim',opt.CLim);
  else
    H.image(jj)= image(fv.x(:,ci)', 'cDataMapping','scaled');
  end
  set(H.ax(jj), AxesStyle{:});
  ud= struct('type','ERP plus: bar', 'chan', str_vec2str(fv.clab(ci)));
  set(H.ax(jj), 'userData',ud);
  hold off;
  if strcmp(get(H.ax(jj), 'box'), 'on'),
    set(H.ax(jj), 'LineWidth',0.3);
    axis_redrawFrame(H.ax(jj));
  end
end
if diff(opt.CLim)==0, opt.CLim(2)= opt.CLim(2)+eps; end
set(H.ax, 'xLim',[0.5 size(fv.x,1)+0.5], 'xTick',[], 'yTick',[], ...
          'CLim',opt.CLim);

if opt.MoveBack,
  obj_moveBack(H.ax);
end

if ~isempty(opt.HScale),
  pos= get(opt.HScale.ax, 'position');
  dh= pos(4)*(1-opt.ScaleHeight)*opt.ScaleVPos;
  pos_cb= [pos(1)+(1-opt.ScaleWidth-opt.ScaleLeftShift)*pos(3) pos(2)+dh ...
           opt.ScaleWidth*pos(3) opt.ScaleHeight*pos(4)];
  H.scale.ax= axes('position', pos_cb);
  CLim= opt.CLim;
  colbar= linspace(CLim(1), CLim(2), size(opt.Colormap,1));
  if opt.UseLocalColormap,
    image_localColormap(colbar', opt.Colormap, 'CLim',opt.CLim);
  else
    H.scale.im= imagesc(1, colbar, [1:size(opt.Colormap,1)]');
  end
  axis_redrawFrame(H.scale.ax);
  if opt.AlphaStepsMode,
    yTick= 0:nValues;
    if opt.UseLocalColormap, yTick= yTick+1; end %% Just a hack...
    set(H.scale.ax, 'yTick',yTick, 'yTickLabel',100*[1 fv.alpha]);
  else
    ticks= visutil_goodContourValues(CLim(1), CLim(2), -3);
    tickLabels= util_trunc(ticks, opt.ScaleDigits);
    if opt.UseLocalColormap,
      YLim= get(gca,'YLim');
      ticks= (ticks-CLim(1))*diff(YLim)/diff(CLim)+YLim(1);
    end
    set(H.scale.ax, 'yTick',ticks, 'yTickLabel',tickLabels);
  end
  set(H.scale.ax, 'xTick',[], 'tickLength',[0 0], 'YDir','normal', ...
                  'FontSize',opt.ScaleFontSize);
  if ~isempty(opt.ScaleUnit),
    yLim= get(H.scale.ax, 'yLim');
    H.scale.unit= text(1, yLim(2), opt.ScaleUnit);
    set(H.scale.unit, 'horizontalAli','center', 'verticalAli','bottom');
  end
end

if nargout==0,
  clear H;
end


% Standard text for function documentation
%
% First line: One-line summary description of function
%
% :Usage:
% ::
%
%     [list outputs here] = function_name(list inputs here, [optional inputs])
%
% For objects: Type methods(object_name) for a list of special commands
%              Type help object_name.method_name for help on specific
%              methods.
%
% ..
%     Author and copyright information:
%
%     Copyright (C) <year>  <name of author>
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
% ..
%
% :Inputs:
%
%   **param1:**
%        description of param1
%
%   **param2:**
%        description of param2
%
% :Optional Inputs:
%   **param1:**
%        description of param1
%
%   **param2:**
%        description of param2
%
% :Outputs:
%
%   **out1:**
%        description of out1
%
%   **out2:**
%        description of out2
%
%   **'doplot', [logical flag]:**
%        Create plots; default = true. 'noplot' to turn off.
%
%   **'doverbose', [logical flag]:**
%        Verbose output; default = true. 'noverbose' to turn off.
%
%   **'dooptimize', [logical flag]:**
%        Optimize hyperparameters; default = true. 'nooptimize' to turn off.
%
%   **'doprepeats', [num repeats]:**
%        Repeat cross-val with different partitions; default = 10.
%        Enter number of repeats, 'norepeats' to turn off.
%
% :Examples:
% ::
%
%    % give examples of code here
%    param1 = abc();
%    param2 = xyz();
%    [out1,out2] = func_call(param1, param2)
%
% :References:
%   CITATION(s) HERE
%
% :See also:
%   - list other functions related to this one, and alternatives*
%

% ..
%    Programmers' notes:
%    List dates and changes here, and author of changes
% ..

% BELOW IS A STANDARD TEMPLATE FOR DEFINING VARIABLE (OPTIONAL) INPUT
% ARGUMENTS. MANY FUNCTIONS NEED TO PARSE OPTIONAL ARGS, SO THIS MAY BE
% USEFUL. I (TOR) RECOMMEND COPYING AND PASTING THE DOCUMENTATION ABOVE AND
% ALL THE STUFF THROUGH ARGUMENT VALIDATION, BELOW, AND MODIFYING IT FOR
% YOUR FUNCTION.

% SEE BELOW FOR TEMPLATE FOR OBJECT CONSTRUCTORS. THIS HAS STRUCTURED
% DOCUMENTATION WITH SOME TEXT FORMATTING RULES THAT WILL MAKE IT
% COMPATIBLE WITH MATLAB'S DOC COMMAND, WHICH WILL THEN CREATE AN HTML PAGE
% LISTING METHODS AND ATTRIBUTES. I (TOR) RECOMMEND COPYING AND PASTING THE
% DOCUMENTATION BELOW AND MODIFYING IT FOR YOUR FUNCTION.

% ..
%    DEFAULTS AND INPUTS
% ..

% Some useful display helper functions
% --------------------------------------------------------

n_cols = 80;
sep_str = repmat('_', 1, n_cols);  % see textwrap

dashes = '----------------------------------------------';
printstr = @(dashes) disp(dashes);
printhdr = @(str) fprintf('%s\n%s\n%s\n', dashes, str, dashes);

% Enforce valid variable names in a cell array of strings: Eliminate special characters and leading numbers
[variable_names, namewarnings] = format_text_letters_only(variable_names, 'numbers', 'cleanup', 'squeeze', 'underscore_ok');

% ----------------------------------------------------------------------
% Parse inputs
% ----------------------------------------------------------------------
% This 2019 version uses the inputParser object. Older schemes are below.
% Note: With this, you can pass in EITHER keyword, value pairs OR a
% structure with fields that define keywords.
% Note: You can also make this a subfunction at the end of your function,
% e.g., function ARGS = parse_inputs(varargin)...end, and call it using:

ARGS = parse_inputs(varargin{:});

% If you want to distribute arguments back out to variables, use this:

fn = fieldnames(ARGS);

for i = 1:length(fn)
    str = sprintf('%s = ARGS.(''%s'');', fn{i}, fn{i});
    eval(str)
end

% Logical flags
% ----------------------------------------------------------------------
if any(strcmp(varargin, 'noverbose')), doverbose = false; end
if any(strcmp(varargin, 'noplots')), doplots = false; end

% ======== This goes at the end of the file / after the main function ========
function ARGS = parse_inputs(varargin)

p = inputParser;

% Validation functions - customized for each type of input
% ----------------------------------------------------------------------

valfcn_scalar = @(x) validateattributes(x, {'numeric'}, {'nonempty', 'scalar'});

valfcn_number = @(x) validateattributes(x, {'numeric'}, {'nonempty'}); % scalar or vector

% Validation: Region object, structure, or [x1 x2 x3] triplet
valfcn_custom = @(x) isstruct(x) || isa(x, 'region') || (~isempty(x) && all(size(x) - [1 3] == 0) && all(isnumeric(x)));

% Validation: [x1 x2 x3] triplet
valfcn_xyz = @(x) validateattributes(x, {'numeric'}, {'nonempty', 'size', [1 3]});

valfcn_logical = @(x) validateattributes(x, {'numeric'}, {'nonempty', 'scalar', '>=', 0, '<=', 1}); % could enter numeric 0,1 or logical

% Required inputs
% ----------------------------------------------------------------------
p.addRequired('x', valfcn_custom);
p.addRequired('y', valfcn_custom);

% Optional inputs
% ----------------------------------------------------------------------
% Pattern: keyword, value, validation function handle

p.addParameter('color', [.9 .2 0], valfcn_xyz);
p.addParameter('bendpercent', .15, valfcn_number); % can be scalar or vector
p.addParameter('thickness', .1, valfcn_scalar);
p.addParameter('nstreamlines', 30, valfcn_scalar);

% Parse inputs and distribute out to variable names in workspace
% ----------------------------------------------------------------------
% e.g., p.parse([30 1 0], [-40 0 10], 'bendpercent', .1);
p.parse(varargin{:});

ARGS = p.Results;

end % parse_inputs

% ==================== end pattern =====================================

% Next is the previously used scheme for CANlab tools for several years

% -------------------------------------------------------------------------
% DEFAULT ARGUMENT VALUES
% -------------------------------------------------------------------------

rowsz = [];
doplot = 0;
basistype = 'spm+disp';
% initalize optional variables to default values here.

% -------------------------------------------------------------------------
% OPTIONAL INPUTS
% -------------------------------------------------------------------------

% This is a compact way to assign multiple variables. The input argument
% names and variable names must match, however:

allowable_inputs = {'var_names' 'p_thr' 'dospearman' 'dopartial' 'dofdr' 'dofigure' 'doimage' 'docircles' 'dotext' 'colorlimit' 'text_x_offset' 'text_y_offset' 'text_fsize' 'text_nonsig_color' 'text_sig_color' 'partitions' 'partitioncolors' 'partitionlabels'};

keyword_inputs = {'noorthviews'};

% optional inputs with default values - each keyword entered will create a variable of the same name

for i = 1:length(varargin)
    if ischar(varargin{i})
        switch varargin{i}

            case allowable_inputs

                eval([varargin{i} ' = varargin{i+1}; varargin{i+1} = [];']);

            case keyword_inputs
                % Skip deal with this below

            otherwise, warning(['Unknown input string option:' varargin{i}]);
        end
    end
end

% 2nd pass: Keyword inputs. These supersede earlier inputs
for i = 1:length(varargin)
    if ischar(varargin{i})
        switch varargin{i}

            case 'writetofile'
                writetofile = true;
                if isempty(movieoutfile)
                    movieoutfile = fullfile(pwd, 'rmssd_movie_file');
                    fprint('Writing file with default name:\n%s\n', movieoutfile);
                end

            case {'nomovie' 'nodisplay'}
                showmovie = false;

        end
    end
end

% 2nd pass: Keyword inputs. These supersede earlier inputs

if any(strcmp(varargin{i}, 'writetofile'))

    writetofile = true;
    if isempty(movieoutfile)
        movieoutfile = fullfile(pwd, 'rmssd_movie_file');
        fprint('Writing file with default name:\n%s\n', movieoutfile);
    end

end

if any(strcmp(varargin{i}, 'nomovie')) || any(strcmp(varargin{i}, 'nodisplay'))

    showmovie = false;

end

% This pattern will flexibly assign arguments based on keywords.
% The names of the input keyword and variable created do not need to match.
% Multiple input keywords can be mapped to the same variable.

% optional inputs with default values
for i = 1:length(varargin)
    if ischar(varargin{i})
        switch varargin{i}

            case {'rows', 'rowsz'}, rowsz = varargin{i+1}; varargin{i+1} = [];
            case 'plot', doplot = 1;
            case 'basistype', basistype = varargin{i+1}; varargin{i+1} = [];

            case allowable_inputs
                % skip - handled above

            otherwise, warning(['Unknown input string option:' varargin{i}]);
        end
    end
end

% -------------------------------------------------------------------------
% VALIDATE ATTRIBUTES OF INPUTS
% -------------------------------------------------------------------------

validateattributes(X,{'numeric'},{'2d'},'plot_correlation_matrix','X', 1);

logical_args = {'dofdr' 'false' 'dospearman' 'dofigure' 'doimage' 'docircles' 'dotext'};
for i = 1:length(logical_args)

    my_arg = eval([logical_args{i} ';']);
    validateattributes(my_arg,{'logical'},{'scalar'},'plot_correlation_matrix',logical_args{i});

end

cell_args = {'partitioncolors' 'partitionlabels' 'var_names'};
for i = 1:length(cell_args)

    my_arg = eval([cell_args{i} ';']);
    validateattributes(my_arg,{'cell'},{},'plot_correlation_matrix',cell_args{i});

end

vector_args = {'text_sig_color' 'text_nonsig_color'};
for i = 1:length(vector_args)

    my_arg = eval([vector_args{i} ';']);
    validateattributes(my_arg,{'numeric' 'vector' 'nonnegative' 'nonnan'},{},'plot_correlation_matrix',vector_args{i});

end

supportedImageClasses    = {'int8','uint8','int16','uint16','int32','uint32','single','double','logical'};
supportedImageAttributes = {'real','nonsparse','nonempty'};
validateattributes(V,supportedImageClasses,supportedImageAttributes,mfilename,'V');

% SEE:
%  validateattributes Check validity of array.
%     validateattributes(A,CLASSES,ATTRIBUTES) validates that array A belongs
%     to at least one of the specified CLASSES and has all of the specified
%     ATTRIBUTES.
%
% See also inputParser.m

% ==================== end pattern =====================================

% THIS IS ANOTHER WAY THAT IS MORE STREAMLINED, BUT ACTUALLY LESS INTUITIVE

% -------------------------------------------------------------------------
% DEFAULTS AND INPUTS
% -------------------------------------------------------------------------

% Defaults
% -----------------------------------
% Set color maps for + / - values
poscm = colormap_tor([1 0 .5], [1 1 0], [.9 .6 .1]);  %reddish-purple to orange to yellow
negcm = colormap_tor([0 0 1], [0 1 1], [.5 0 1]);  % cyan to purple to dark blue

% optional inputs with default values
% -----------------------------------
% - allowable_args is a cell array of argument names
% - avoid spaces, special characters, and names of existing functions
% - variables will be assigned based on these names
%   i.e., if you use an arg named 'cl', a variable called cl will be
%   created in the workspace

allowable_args = {'cl', 'ycut_mm', 'pos_colormap', 'neg_colormap', ...
    'surface_handles', 'existingfig'};

default_values = {[], [], poscm, negcm, ...
    [], 0};

% define actions for each input
% -----------------------------------
% - cell array with one cell for each allowable argument
% - these have special meanings in the code below
% - allowable actions for inputs in the code below are: 'assign_next_input' or 'flag_on'

actions = {'assign_next_input', 'assign_next_input', 'assign_next_input', 'assign_next_input', ...
    'assign_next_input', 'flag_on'};

% logical vector and indices of which inputs are text
textargs = cellfun(@ischar, varargin);
whtextargs = find(textargs);

for i = 1:length(allowable_args)

    % assign default
    % -------------------------------------------------------------------------

    eval([allowable_args{i} ' =  default_values{i};']);

    wh = strcmp(allowable_args{i}, varargin(textargs));

    if any(wh)
        % Optional argument has been entered
        % -------------------------------------------------------------------------

        wh = whtextargs(wh);
        if length(wh) > 1, warning(['input ' allowable_args{i} ' is duplicated.']); end

        switch actions{i}
            case 'assign_next_input'
                eval([allowable_args{i} ' = varargin{wh(1) + 1};']);

            case 'flag_on'
                eval([allowable_args{i} ' = 1;']);

            otherwise
                error(['Coding bug: Illegal action for argument ' allowable_args{i}])
        end

    end % argument is input
end

% END DEFAULTS AND INPUTS
% -------------------------------------------------------------------------

% Below are some default headers

% -------------------------------------------------------------------------
% -------------------------------------------------------------------------
%
% Sub-functions
%
% -------------------------------------------------------------------------
% -------------------------------------------------------------------------

% -------------------------------------------------------------------------
% -------------------------------------------------------------------------

% OBJECT FUNCTION DEFINITION - followed by one-line description
% image_vector: An object that allows for storage and manipulation of neuroimaging data
%
% -------------------------------------------------------------------------
% Features and philosophy:
% -------------------------------------------------------------------------
%
% - Store image data in a flat (2-d), space-efficient voxels x images matrix
% - Save space: Tools to remove out-of-image voxels and empty (zero/NaN) voxels, store data in single-precision format
% - Analysis-friendly: 2-d matrices can be read and analyzed in multiple packages/algorithms
% - Meta-data included to convert back to 3-d image volume space,
%   with easy tools (methods) to reconstruct and visualize images
%   Built-in resampling makes it easy to compare/combine datasets with different voxel sizes and image bounding boxes
%   Reduces overhead for statisticians/data scientists unfamiliar with neuroimaging to apply their algorithms.
% - Multiple images can be stored in a single object
% - Methods have short, intuitive names, and perform high-level functions specialized for neuroimaging:
% - Visualization (plot, orthviews, surface, montage, histogram, isosurface methods)
% - Image manipulation (apply_mask, get_wh_image, resample_space, compare_space, flip, threshold methods)
% - Data extraction (apply_atlas, apply_parcellation, extract_gray_white_csf, extract_roi_averages)
% - Analysis (ica, mahal, image_math, and many more in the fmri_data subclass)
% - Provenance: Ability to track and update history of changes to objects
%
% image_vector is a superclass of several other object types:
% fmri_data
% statistic_image
% atlas
%
% These object types have additional analysis methods and properties, and
% are most often used. You will rarely create an image_vector object
% directly. Typically you would create instances of one of the classes above.
%
% -------------------------------------------------------------------------
% To construct/create a new instance of an object:
% -------------------------------------------------------------------------
%
% As with any neuroimaging-data object class in this toolbox
% (image_vector, fmri_data, statistic_image, atlas), you can create an object by
% specifying the names of a set of images you want to load in and passing them into the
% function with the same name as the object class (e.g., fmri_data). This
% will create an object with image data and image space information attached.
%
% Use fmri_data instead of image_vector to load image data:
% data_obj = fmri_data(image_names);
%
% ...where image_names is a character array or 1 x n cell array of strings
%
% -------------------------------------------------------------------------
% Properties and methods
% -----------------------------------------------------------------------
% Properties are data fields associated with an object.
% Type the name of an object (class instance) you create to see its
% properties, and a link to its methods (things you can run specifically
% with this object type). For example: After creating an fmri_data object
% called fmri_dat, as above, type fmri_dat to see its properties.
%
% There are many other methods that you can apply to fmri_data objects to
% do different things.
% - Try typing methods(fmri_data) for a list.
% - You always pass in an fmri_data object as the first argument.
% - Methods include utilities for many functions - e.g.,:
% - resample_space(fmri_dat) resamples the voxels
% - write(fmri_dat) writes an image file to disk (careful not to overwrite by accident!)
% - regress(fmri_dat) runs multiple regression
% - predict(fmri_dat) runs cross-validated machine learning/prediction algorithms
%
% Key properties and methods (a partial list; type doc image_vector for more):
% -------------------------------------------------------------------------
% image_vector Properties:
%   dat                     - Image data, a [voxels x images] matrix, single-format
%   fullpath                - List of image names loaded into object with full paths
%   history                 - History of object processing, for provenance
%   image_names             - List of image names loaded into object, no paths
%   removed_images          - Vector of images that have been removed (saves space; see remove_empty.m, replace_empty.m)
%   removed_voxels          - Vector of empty in-mask voxels that have been removed (saves space; see remove_empty.m, replace_empty.m)
%   volInfo                 - Structure with info on brain mask (saves space) and mapping voxels to brain space
%
% image_vector Methods:
%   General:
% . 	descriptives        -  Get descriptives for an fmri_data or other image_vector object
%       enforce_variable_types	-  Re-casts variables in objects into standard data types, which can save
%       flip                - Flips images stored in an object left-to-right
%     	history             - Display history for image_vector object
%       write               - Write an image_vector object to hard drive as an Analyze image (uses .fullpath field for image names)
%   Data extraction:
%       apply_atlas         - Computes the mean value or pattern expression for each reference region specified in an atlas object
%       apply_mask          - Apply a mask image (image filename or fmri_mask_image object) to an image_vector object
%       apply_parcellation  - Computes the mean value or pattern expression for each parcel specified in a data object
%       extract_gray_white_csf	- Extracts mean values (values) and top 5 component scores (components)
%       extract_roi_averages	- This image_vector method a extracts and averages data stored in an fmri_data object
%
%   Handling brain space and image selection:
%       compare_space           - Compare spaces of two image_vector objects
%       get_wh_image            - For an image_vector with multiple images (cases, contrasts, etc.), select a subset.
%       reconstruct_image       - Reconstruct a 3-D or 4-D image from image_vector object obj
%       remove_empty            - remove vox: logical vector of custom voxels to remove, VOX x 1
%       reparse_contiguous      - Re-construct list of contiguous voxels in an image based on in-image
%       replace_empty           - Replace empty/missing values in an image data object
%       resample_space          - Resample the images in an fmri_data object (obj) to the space of another
%
%   Display and visualization:
%   	display_slices      - Creates 3 separate montage views - ax, cor, sagg in a special figure window
%       histogram           - Create a histogram of image values or a series of histograms for each
%       image_similarity_plot - Associations between images in object and set of 'spatial basis function' images (e.g., 'signatures' or pre-defined maps)
%       isosurface          - Create and visualize an isosurface created from the boundaries in an image object.
%       montage             - Create a montage of an image_vector (or statistic_image or fmri_data)
%       orthviews               - display SPM orthviews for CANlab image_vector (or fmri_data, statistic_image) object
%       pattern_surf_plot_mip	- axial maximum intensity projection pattern surface plot
%   	sagg_slice_movie	- Movie of successive differences (sagittal slice)
%       slices              - Create a montage of single-slice results for every image in an image_vector object
%       surface             - Render image data on brain surfaces; options for cutaways and canonical surfaces
%       wedge_plot_by_atlas	- Plot a data object or 'signature' pattern divided into local regions
%
%   Data processing and analysis:
%   	ica                 - Spatial ICA of an fmri_data object
%       image_math          - Perform simple mathematical and boolean operations on image objects (see also plus, minus, power)
%       mahal               - Mahalanobis distance for each image in a set compared to others in the set
%       mean                - Mean across a set of images. Returns a new image_vector object.
%       preprocess          - Preprocesses data in an image_vector (e.g., fmri_data) object; many options for filtering and outlier id
%       qc_metrics_second_level	- Quality metrics for a 2nd-level analysis (set of images from different subjects)
%       searchlight         - Run searchlight multivariate prediction/classification on an image_vector
%       threshold           - Threshold image_vector (or fmri_data or fmri_obj_image) object based on raw threshold values
%       union               - ...and intersection masks for two image_vector objects
%
% -------------------------------------------------------------------------
% Examples and help:
% -------------------------------------------------------------------------
%
% To list properties and methods for this object, type:
% doc image_vector, methods(image_vector)
%
% Example 1:
% Load a sample dataset into an fmri_data object (subclass of image_vector)
% This loads one of a set of named image collections used in demos/help:
% data_obj = load_image_set('emotionreg');
%
% You can load the same images manually, by locating the files, listing
% their names in a character array (or 1 x n cell array of strings), and
% then passing those into fmri_data:
%
% filedir = what(fullfile('CanlabCore', 'Sample_datasets', 'Wager_et_al_2008_Neuron_EmotionReg'));
% image_names = filenames(fullfile(filedir.path, '*img'));
% data_obj = fmri_data(image_names);
%
% Now you can interact with the object.  Try, e.g.,:
% methods(data_obj)                               % List methods for object type
% plot(data_obj)                                  % Custom fmri_data specific plots
% t = ttest(data_obj);                            % Perform a voxel-wise one-sample t-test across images
% t = threshold(t, .005, 'unc', 'k', 10);         % Re-threshold with extent threshold of 10 contiguous voxels
% r = region(t);                                  % Turn t-map into a region object with one element per contig region
%
% For more examples and walkthroughs, see the CANlab_help_examples
% repository at https://github.com/canlab/CANlab_help_examples
%
% Some example tutorials:
% canlab_help_1_installing_tools
% canlab_help_2_load_a_sample_dataset
% canlab_help_3_voxelwise_t_test_walkthrough
% canlab_help_4_write_data_to_image_file_format
% canlab_help_5_regression_walkthrough
%
% License and authors:
% -------------------------------------------------------------------------
% By Tor Wager and CANlab members and collaborators
% GNU General Public License; see http://www.gnu.org/licenses/
% See Programmers' Notes in code for more info
%
%
% -------------------------------------------------------------------------
% See also:
% fmri_data
% statistic_image
% atlas
% region


function overtopo()
    % provide controls that would go around a topographic map

    ZG=ZmapGlobal.Data; % used by get_zmap_globals
    report_this_filefun();

    to1 = figure_w_normalized_uicontrolunits( ...
        'Name','Topographic Map',...
        'NumberTitle','off', ...
        'backingstore','on',...
        'NextPlot','add', ...
        'Visible','on', ...
        'Position',position_in_current_monitor(ZG.map_len(1), ZG.map_len(2)));

    add_controls()

    function add_controls()
        labelPos = [0.9 0.93 0.10 0.05];
        uicontrol(...
            'Style','popup',...
            'Units','normalized',...
            'Position',labelPos,...
            'Value',1,...
            'String',cb_shader(),...
            'BackgroundColor',[0.7 0.7 0.7]',...
            'callback',@cb_shader);

        labelPos = [0.9 0.75 0.10 0.05];
        uicontrol(...
            'Style','popup',...
            'Units','normalized',...
            'Position',labelPos,...
            'Value',1,...
            'String',cb_volcanoes(),...
            'BackgroundColor',[0.7 0.7 0.7]',...
            'callback',@cb_volcanoes);

        uicontrol('Units','normal',...
            'Position',[.0 .0 .28 .04],'String','Plot using Mapping Toolbox ',...
            'callback', @(~,~)zmaptopo.overmaptb)

        labelPos = [0.9 0.65 0.10 0.05];
        uicontrol(...
            'Style','popup',...
            'Units','normalized',...
            'Position',labelPos,...
            'Value',1,...
            'String',cb_eqplot(),...
            'BackgroundColor',[0.7 0.7 0.7]',...
            'callback',@cb_eqplot);

        labelPos = [0.9 0.55 0.10 0.05];
        uicontrol(...
            'Style','popup',...
            'Units','normalized',...
            'Position',labelPos,...
            'Value',1,...
            'String',cb_faultplot(),...
            'BackgroundColor',[0.7 0.7 0.7]',...
            'callback',@cb_faultplot);

        labelPos = [0.9 0.45 0.10 0.05];
        uicontrol(...
            'Style','popup',...
            'Units','normalized',...
            'Position',labelPos,...
            'Value',1,...
            'String',cb_coastplot(),...
            'BackgroundColor',[0.7 0.7 0.7]',...
            'callback',@cb_coastplot);

        labelPos = [0.9 0.35 0.10 0.05];
        uicontrol(...
            'Style','popup',...
            'Units','normalized',...
            'Position',labelPos,...
            'Value',1,...
            'String',cb_mainevent(),...
            'BackgroundColor',[0.7 0.7 0.7]',...
            'callback',@cb_mainevent);

        labelPos = [0.9 0.25 0.10 0.05];
        uicontrol(...
            'Style','popup',...
            'Units','normalized',...
            'Position',labelPos,...
            'Value',1,...
            'String',cb_stations(),...
            'BackgroundColor',[0.7 0.7 0.7]',...
            'callback',@cb_stations);
    end

    %% callbacks
    function labelList = cb_shader(mysrc, ~)
        labelList={'flat', 'interp', 'faceted'};
        if nargin>0
            shading(labelList{mysrc.Value});
        end
    end

    function labelList = cb_volcanoes(mysrc,~)
        labelList= {'Volcanoes on','off'};
        if nargin == 0
            return
        end
        switch mysrc.Value
            case 1 % on
                plot(vo.Longitude, vo.Latitude, '^r', 'LineWidth', 1.5, 'MarkerSize',8,...
                    'MarkerFaceColor', 'w', 'MarkerEdgeColor', 'r', 'Tag', 'overtopo_volcanoes');
            case 2
                delete(findobj(gcf, 'Tag', 'overtopo_volcanoes'));
        end
    end

    function labelList = cb_eqplot(mysrc,~, catalog)
        labelList = {'EQ (dot)', 'EQ (o)', 'No EQ'};
        if nargin == 0
            return
        end

        switch mysrc.Value
            case 1
                plot(catalog.Longitude,catalog.Latitude, '.r', 'MarkerSize', 1, 'Tag', 'overtopo_eq') ;
            case 2
                plot(catalog.Longitude,catalog.Latitude, 'or', 'MarkerSize', 2, 'Tag', 'overtopo_eq') ;
            case 3
                delete(findobj(gcf,'Tag','overtopo_eq'));
        end
    end

    function labelList = cb_faultplot(mysrc, ~)
        labelList = {'Faults', 'No Faults'};
        if nargin == 0
            return
        end
        switch mysrc.Value
            case 1
                plot(faults(:,1), faults(:,2), 'm', 'Linewidth', 2, 'Tag', 'overtopo_faults');
            case 2
                delete(findobj(gcf,'Tag','overtopo_faults')) ;
        end
    end

    function labelList = cb_coastplot(mysrc,~)
        labelList = {'Coast','No Coast'};
        if nargin == 0
            return
        end
        switch mysrc.Value
            case 1
                plot(coastline(:,1),coastline(:,2),'w','Linewidth',2, 'Tag', 'overtopo_coast');
            case 2
                delete(findobj(gcf,'Tag','overtopo_coast')) ;
        end
    end

    function labelList = cb_mainevent(mysrc,~)
        labelList = {' Main','No Main'};
        if nargin == 0
            return
        end
        switch mysrc.Value
            case 1
                plot(ZG.maepi.Longitude, ZG.maepi.Latitude, 'hm',...
                    'LineWidth', 1.5, 'MarkerSize', 12,...
                    'MarkerFaceColor', 'y', 'MarkerEdgeColor', 'k', 'Tag', 'overtopo_mainevts')
                te1 = text(ZG.maepi.Longitude, ZG.maepi.Latitude, stri2);
                set(te1,'FontWeight', 'bold', 'Color', 'k', 'FontSize', 9, 'Clipping', 'on',...
                    'Tag', 'overtopo_mainevts');

            case 2
                delete(findobj(gcf, 'Tag','overtopo_mainevts'));
        end
    end

    function labelList = cb_stations(mysrc,~)
        labelList = {'Stations','No Stations'};
        if mysrc.Value == 1
            h1 = h1topo;
            plotstations ;
        end
    end

end


function kern = diagKernExpandParam(kern, params)

% DIAGKERNEXPANDPARAM Create kernel structure from DIAG kernel's parameters.
% FORMAT
% DESC returns a diagonal noise covariance function kernel structure filled with the
% parameters in the given vector. This is used as a helper function to
% enable parameters to be optimised in, for example, the NETLAB
% optimisation functions.
% ARG kern : the kernel structure in which the parameters are to be
% placed.
% ARG param : vector of parameters which are to be placed in the
% kernel structure.
% RETURN kern : kernel structure with the given parameters in the
% relevant locations.
%
% SEEALSO : diagKernParamInit, diagKernExtractParam, kernExpandParam
%
% COPYRIGHT : Neil D. Lawrence, 2011

% KERN

kern.variance = params(1);


% ctftopo
% EEGLAB script for plotting topo maps of CTF data
% Thomas Ferree @ UCSF
% Revised 2/17/2004

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

clear;

% toggle saving eeglab .set, 0 = no, 1 = yes
saveSet = 0;

% set machine: 1 = TiBoard, 2 = Glutamate/Acetylcholine/Brainmap
machine = 2;

% set input and output paths
if machine == 1
	pathdata = '/Users/tferree/Documents/Data/Attention/HighN/';
	pathersp = '/Users/tferree/Documents/Research/Attention/HighN/Numerical/';
	pathtemp = '/Users/tferree/Documents/Research/Attention/HighN/Temp/';
else
	addpath /home/tferree/EEGLAB42/;
	addpath /home/tferree/Attention/HighN/ctf2eeglab/;
	pathdata = '/home/cdale/HighN/';
	pathersp = '/home/tferree/Attention/HighN/Numerical/';
	pathtemp = '/home/tferree/Attention/HighN/Temp/';
end

% set subject and conditions

%subject = 'HM'
%date = '20040126';

%subject = 'GN'
%date = '20040109';

subject = 'CJ'
date = '20040116';

cue = 'CueL'

% load ERSP results
load([pathersp 'ERSP_' subject '_' cue '.mat']);

% call Darren's scripts
%ctffolder = [pathdata subject '_DNL_' date '_HiN_' cue 'InvNT' '-fEOG.ds'];
ctffolder = [pathdata subject '_epoch' filesep 'processed' filesep subject '_DNL_' date '_HiN_' cue 'InvNT' '-fEOG.ds'];

ctfchannels = 'meg';
ctftime = 'all';
ctftrials = [1];
ctf = ctf_read(ctffolder,ctfchannels,ctftime,ctftrials);
ctf2eeglab;

% make topo maps
freqs = allfreqs(1,:,1);
times = alltimes(1,:,1);
maxcolor = 5;

for plottime = 0:100:1800

    if plottime <= 9
        timestring = ['000' num2str(plottime)];
    elseif plottime >= 10 & plottime <= 99
        timestring = ['00' num2str(plottime)];
    elseif plottime >= 100 & plottime < 1000
        timestring = ['0' num2str(plottime)];
    else
        timestring = num2str(plottime);
    end

    timefreqlist = [plottime 5; plottime 7; plottime 9; plottime 11; plottime 13; plottime 15; plottime 17];
    h3 = figure;
    tftopo(allersp,times,freqs,'mode','ave','signifs', allerspboot,'limits',[min(times) max(times) 1 20 -maxcolor, maxcolor],'vert',[0 1000],'chanlocs',EEG.chanlocs,'timefreqs',timefreqlist,'electrodes','off','maplimits',[-maxcolor,maxcolor]);
    saveas(h3,[pathtemp 'Topo_' subject '_' cue '_' timestring 'msec.jpg'],'jpg');
    close(h3);

end


function [sstate, si] = tapas_sem_hier_get_stored_state(data, model, ...
    inference, state)
%% Get the state that should be stored
%
% aponteeduardo@gmail.com
% copyright (C) 2016
%

sstate = struct('graph', {cell(4, 1)}, 'llh', {cell(4, 1)}, 'v', []);

order = state.graph{2}.u.temperature_ordering;
sstate.graph{2} = state.graph{2}.y(:, order);

sstate.llh{1} = state.llh{1}(:, order);

sstate.v = state.v(:, order);

if state.nsample < inference.nburnin
    si = mod(state.nsample, inference.ndiag) + 1;
else
    si = state.nsample - inference.nburnin + 1;
end

end


function s = read_curry(filename)

% READ_CURRY reads and parses Curry V2 and V4 ascii files and returns the
% content in a structure that is similar to the block-structured layout of
% the file. This function does not interpret the content of the file, but
% is intended as a helper function for READ_CURRY_XXX functions (where XXX
% is the extension of the file).
%
% Use as
%   s = read_curry(filename)

% Copyright (C) 2005, 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$

fid = fopen_or_error(filename, 'rt');

s    = [];
line = [];

while ~feof(fid)
  line = fgetl(fid);
  blockname = '';

  % search for the beginning of a block
  if ~isempty(strfind(line, 'START'))
    [blockname, blocktype] = strtok(line);
    blockname = strtrim(blockname);
    blocktype = strtrim(strtok(blocktype));
    val = {};

    % fprintf('reading block %s\n', blockname);
    while isempty(strfind(line, 'END'))

      % read the next line
      line = fgetl(fid);
      % process the data in the line
      if strcmp(blocktype, 'START') && ~isempty(strfind(line, '='))
        % the line looks like "lhs = rhs"
        [lhs, rhs] = strtok(line, '=');
        lhs = strtrim(lhs);
        rhs(1) = ' ';
        rhs = strtrim(rhs);
        val = str2double(rhs);
        if isnan(val)
          val = rhs;
        end
        s = setfield(s, blockname, lhs, val);
      elseif strcmp(blocktype, 'START_LIST')
        % this contains unstructured data, process this line as being part of a list
        val{end+1} = line;
      else
        % process this line differently
        % FIXME
      end

      if isnumeric(line) || feof(fid)
        ft_error('unexpected end of file');
      end

    end % while ~END
  end % if START of block

  % store the collected cell-array if it was part of an unstructured list
  if strcmp(blocktype, 'START_LIST')
    val = val(1:(end-1));   % remove the last item, which is the end of the block
    val = val(:);           % make it a column array
    s = setfield(s, blockname, val);
  end

  % clear them to prevent confusion on the next loop
  blockname = '';
  blocktype = '';

end  % while ~feof

fclose(fid);


function inputString = writeLineFromVar(defaultClass, variableName, maskVars, maskViz, classNum, structName)
% This function creates a string that is written to a wecSimInputFile.m
% line based on a class abbreviation, variable name and its mask value
%
% It is possible to write the input file with a long list of fprintf lines
% such as:
%     fprintf(fid,'simu.rampTime = %s; \r\n',maskVars.rampTime);
%     fprintf(fid,'simu.endTime = %s; \r\n',maskVars.endTime);

% However this doesn't allow the maskVariable to be checked against a
% default value or its visibility (its necessity) without an excessive
% number of if statements in writeInputFromBlocks.m. Comparing against
% these parameters before writing reduces the number of extraneous values written to the input file.
%
% Parameters
% ------------
%     defaultClass : WEC-Sim Object
%         Default instance of a WEC-Sim class. Must contain the variableName that is
%         being written to the input file
%
%     variableName : string
%         Name of the variable within defaultClass that is being written to
%         the input file.
%
%     maskVars : struct
%         Structure containing all mask parameter values
%
%     maskViz : string
%          Structure containing all mask parameter visibilities
%
%     classNum : int
%          Number specifying the index of a class being written
%          i.e. 1 for body(1), 4 for pto(4), 7 for constraint(7), ...
%
%     structName : string
%          Structure containing all mask parameter visibilities
%
% Returns
% -------
%     inputString : string
%         string to write to the input file
%
% TODO
% ----
%     Link mask tool tips with input line comments
%

    % Track if variable should be written
    hasStruct = ~isempty(structName); % check if variable is in a class' struct (correspond to a mask tab)
    isVisible = strcmp(maskViz.(variableName),'on'); % check if mask variable is visible

    % Get the default value of the variable within its WEC-Sim class
    if hasStruct
        isDefault = isequal(defaultClass.(structName).(variableName), eval(maskVars.(variableName)));
    else
        isDefault = isequal(defaultClass.(variableName), eval(maskVars.(variableName)));
    end

    % Only write parameters if they are visible (turned on and relevant) and
    % are different from the class default
    if isVisible && ~isDefault
        % Append the class index if necessary. E.g. 'body' --> 'body(1)'
        classAbbrev = inputname(1);
        if ~isempty(classNum)
            classAbbrev = [classAbbrev '(' num2str(classNum) ')'];
        end

        if hasStruct
            % e.g. 'body(1).initial.displacement = [1 1 1]; \r\n'
            inputString = [classAbbrev '.' structName '.' variableName ' = ' maskVars.(variableName) '; \r\n'];
        else
            % e.g. 'simu.stateSpace = 'on'; \r\n'
            inputString = [classAbbrev '.' variableName ' = ' maskVars.(variableName) '; \r\n'];
        end
    else
        % Write nothing to input file
        inputString = '';
    end

end


function y = cat(varargin)
%CAT (overloaded)

switch varargin{1}
    case 1
        y = vertcat(varargin{2:end});
    case 2
        y = horzcat(varargin{2:end});
    otherwise
        for i = 2:nargin
            if isa(varargin{i},'sdpvar');
                varargin{i} = ndsdpvar(varargin{i});
            end
        end
        y = cat(varargin{:});
end


function varargout = slinvoke(invoke_descr, varargin)
%SLINVOKE Invokes a function
%
% $ Syntax $
%   - [y1, y2, ..., yn] = slinvoke(invoke_descr, x1, x2, ..., xm)
%
% $ Arguments $
%   - invoke_descr:       the invoking descriptor
%   - x1, x2, ..., xm:    the input arguments
%   - y1, y2, ..., yn:    the output arguments
%
% $ Description $
%   - [y1, y2, ..., yn] = slinvoke(invoke_descr, placepos, x1, x2, ..., xm)
%     invokes some function with a specified manner. The invoking descriptor
%     can be in following form:
%     1. a string representing the function name, a function handle or an
%        inline object. In this case, no fixed argument is binded. The x1,
%        x2, ..., xm are directly fed to the function.
%     2. a cell array like {func, var_pos, fa1, fa2, ... fak}. Here
%        func is the function name, function handle or inline object that
%        is to be invoked. var_pos is the positions of variable arguments.
%        fa1, fa2, ... are the fixed(binded) arguments. If var_pos is [],
%        the variable arguments will be put first.
%
% $ Examples $
%   - Invoke a function without fixed arguments
%     \{
%           slinvoke('plot', x, y);
%           y = slinvoke({'sin', []}, x);
%     \}
%
%   - Invoke a function with fixed arguments binded, the following pairs
%     of statements are equivalent.
%     \{
%           K = slinvoke({'strfind', 1, 'pattern'}, s);
%           K = strfind(s, 'pattern');
%
%           slinvoke({'plot', [1 2], 'r-'}, x, y);
%           plot(x, y, 'r-');
%
%           slinvoke({'plot', 2, x, 'b+'}, y);
%           plot(x, y, 'b+');
%
%           b = slinvoke({'isequal', [], 0}, x);
%           b = isequal(x, 0);
%     \}
%
% $ History $
%   - Created by Dahua Lin on Dec 28th, 2005
%

%% parse input arguments
if ~iscell(invoke_descr)
    func = invoke_descr;
    var_pos =[];
    fix_args = {};
else
    len_invoke_descr = length(invoke_descr);
    func = invoke_descr{1};
    if len_invoke_descr >= 2
        var_pos = invoke_descr{2};
    else
        var_pos = [];
    end
    if len_invoke_descr >= 3
        fix_args = invoke_descr(3:end);
    else
        fix_args = {};
    end
end

if isempty(var_pos) && ~isempty(varargin)
    var_pos = 1:length(varargin);
end
n_fix_args = length(fix_args);
n_var_args = length(var_pos);
if length(varargin) ~= n_var_args
    error('sltoolbox:argmismatch', ...
        'The variable input arguments do not match that described in invoking descriptor');
end

%% organize input arguments
if n_fix_args == 0 && n_var_args == 0
    if nargout == 0
        feval(func);
    else
        [varargout{1:nargout}] = feval(func);
    end
elseif n_var_args == 0
    if nargout == 0
        feval(func, fix_args{:});
    else
        [varargout{1:nargout}] = feval(func, fix_args{:});
    end
else
    n_args = max(n_fix_args + n_var_args, max(var_pos));
    input_args = cell(1, n_args);
    indicator_var = false(1, n_args);
    indicator_var(var_pos) = true;
    fix_pos = find(~indicator_var);

    for i = 1 : n_var_args
        input_args{var_pos(i)} = varargin{i};
    end

    for i = 1 : n_fix_args
        input_args{fix_pos(i)} = fix_args{i};
    end

    if nargout == 0
        feval(func, input_args{:});
    else
        [varargout{1:nargout}] = feval(func, input_args{:});
    end
end


totalNum = 1867290;

% [epsilon_soft_2_DP_test, time_DP_2_test] = DP_loopCompress(1, '/home/yinhuan/mapModel/yq/weightVector.txt', '/home/yinhuan/mapModel/yq/rows_cut/sparse/visMatrix/', '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_rows_cuts_2_test.txt', totalNum, 1000, '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_test/');
%
% point_num_DP_2_test = salientNumCnt('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_test/', totalNum );
%
% min_cost_DP_2_test = get_min_cost('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_test/', '/home/yinhuan/mapModel/yq/weightVector.txt', 1, epsilon_soft_2_DP_test);

%% sparse test
% two nums: section_num search_domain
% [epsilon_soft_5_DP_80_max, time_DP_5_80_max] = DP_loopCompress(1, '/home/yinhuan/mapModel/yq/weightVector.txt', '/home/yinhuan/mapModel/yq/rows_cut/sparse/visMatrix/', '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_rows_cuts_5_80_max.txt', totalNum, 1000, '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_5_80_max/');
%
% point_num_DP_5_80_max = salientNumCnt('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_5_80_max/', totalNum );
%
% min_cost_DP_5_80_max = get_min_cost('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_5_80_max/', '/home/yinhuan/mapModel/yq/weightVector.txt', 1, epsilon_soft_5_DP_80_max);

%
%
% [epsilon_soft_2_DP_50, time_DP_2_50] = DP_loopCompress(1, '/home/yinhuan/mapModel/yq/weightVector.txt', '/home/yinhuan/mapModel/yq/rows_cut/sparse/visMatrix/', '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_rows_cuts_2_50.txt', totalNum, 1000, '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_50/');
%
% point_num_DP_2_50 = salientNumCnt('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_50/', totalNum );
%
% min_cost_DP_2_50 = get_min_cost('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_50/', '/home/yinhuan/mapModel/yq/weightVector.txt', 1, epsilon_soft_2_DP_50);
%
%
%
%
% [epsilon_soft_2_DP_20, time_DP_2_20] = DP_loopCompress(1, '/home/yinhuan/mapModel/yq/weightVector.txt', '/home/yinhuan/mapModel/yq/rows_cut/sparse/visMatrix/', '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_rows_cuts_2_20.txt', totalNum, 1000, '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_20/');
%
% point_num_DP_2_20 = salientNumCnt('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_20/', totalNum );
%
% min_cost_DP_2_20 = get_min_cost('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_20/', '/home/yinhuan/mapModel/yq/weightVector.txt', 1, epsilon_soft_2_DP_20);
%
%
%
% [epsilon_soft_2_DP_10, time_DP_2_10] = DP_loopCompress(1, '/home/yinhuan/mapModel/yq/weightVector.txt', '/home/yinhuan/mapModel/yq/rows_cut/sparse/visMatrix/', '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_rows_cuts_2_10.txt', totalNum, 1000, '/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_10/');
%
% point_num_DP_2_10 = salientNumCnt('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_10/', totalNum );
%
% min_cost_DP_2_10 = get_min_cost('/home/yinhuan/mapModel/yq/rows_cut/sparse/DP_compress_2_10/', '/home/yinhuan/mapModel/yq/weightVector.txt', 1, epsilon_soft_2_DP_10);

%% 11.30

DP_save_rows('/home/yinhuan/mapModel/yq_500/greedy/DP/cut_costs.txt', 2, 4/5, '/home/yinhuan/mapModel/yq_500/greedy/DP/DP_rows_cuts_2_80.txt');

[epsilon_soft_2_80_max, time_DP_2_80_max] = DP_loopCompress(1, '/home/yinhuan/mapModel/yq_500/weightVector.txt', '/home/yinhuan/mapModel/yq_500/visMatrix/', '/home/yinhuan/mapModel/yq_500/greedy/DP/DP_rows_cuts_2_80.txt', totalNum, 1000, '/home/yinhuan/mapModel/yq_500/greedy/DP/DP_rows_cut_2_80/');

point_num_DP_2_80_max = salientNumCnt('/home/yinhuan/mapModel/yq_500/greedy/DP/DP_rows_cut_2_80/', totalNum );

min_cost_DP_2_80_max = get_min_cost('/home/yinhuan/mapModel/yq_500/greedy/DP/DP_rows_cut_2_80/', '/home/yinhuan/mapModel/yq_500/weightVector.txt', 1, epsilon_soft_2_80_max);


classdef VideoMaker_Physical_Problem < VideoMaker

     properties

     end

      methods (Access = public)
        function Make_video_stress(obj,output_video_name,component)
            post = Postprocess_PhysicalProblem;
            field2print = post.stress_name;
            componentfield = [post.stress_component,component];
            obj.Make_video_standard_field(field2print,componentfield,output_video_name)
        end

        function Make_video_strain(obj,output_video_name,component)
            post = Postprocess_PhysicalProblem;
            field2print = post.strain_name;
            componentfield = [post.strain_component,component];
            obj.Make_video_standard_field(field2print,componentfield,output_video_name)
        end

        function Make_video_displacement(obj,output_video_name,component)
            post = Postprocess_PhysicalProblem;
            field2print = post.displ_name;
            componentfield = [post.displ_component,component];
            obj.Make_video_standard_field(field2print,componentfield,output_video_name)
         end

      end

      methods (Access = private)
        function Make_video_standard_field(obj,field2print,componentfield,output_video_name_in)
            file_tcl_name = 'tcl_gid.tcl';
            file_list = obj.create_file_list(obj.iterations_to_print,obj.file_name,obj.files_folder);
            [output_video_name] = obj.replace_special_character(output_video_name_in);
            [file_list] = obj.replace_special_character(file_list);

            file_tcl_name_with_path = fullfile(obj.files_folder,file_tcl_name);
            file_path_in = fullfile(pwd,'FEM','PostProcess','Make_Video_stress.tcl');
            filepath = obj.replace_special_character(file_path_in);

            fid = fopen(file_tcl_name_with_path,'w+');

            fprintf(fid,'GiD_Process PostProcess \n');
            fprintf(fid,'%s\n',['set arg1 "',file_list,'"']);
            fprintf(fid,'%s\n',['set arg2 "',output_video_name,'"']);
            fprintf(fid,'%s\n',['set arg3 "',field2print,'"']);
            fprintf(fid,'%s\n',['set arg4 "',componentfield,'"']);

            fprintf(fid,'%s\n',['source "',filepath,'"']);
            fprintf(fid,'%s\n',['Make_Video_stress $arg1 $arg2 $arg3 $arg4']);
            fprintf(fid,'%s\n',['GiD_Process Mescape Quit']);
            fclose(fid);
            obj.executeTclFiles(obj.gidPath,file_tcl_name_with_path)
        end

      end

end


function svgComposite(s, source1, source2, operator, result, k)
% Adds a feComposite SVG filter
% PRELIMINARY IMPLEMENTATION (Parameters may change)
%
% svgComposite(s, source1, source2, operator, result)
% Parameters:
%   s : Array of plot object handles
%   source1 : Any previous defined filter result string, 'SourceGraphic',
%             or 'SourceAlpha'.
%   source2 : Any previous defined filter result string, 'SourceGraphic',
%             or 'SourceAlpha'.
%   operator : Operator 'over','in','out','atop','xor','arithmetic'
%              -> see SVG 1.1 specification. 'arithmetic' is not yet
%              supported.
%   result : String that identifies the filter result for following filter
%            stages.
for i = 1:length(s)
    userdata = get(s(i),'UserData');
    if isfield(userdata, 'svg') && isfield(userdata.svg, 'Filter')
        next = length(userdata.svg.Filter) + 1;
    else
        next = 1;
    end
    userdata.svg.Filter(next).Subfilter.Type = 'feComposite';
    userdata.svg.Filter(next).Subfilter.Source1 = source1;
    userdata.svg.Filter(next).Subfilter.Source2 = source2;
    userdata.svg.Filter(next).Subfilter.Operator = operator;
    if nargin > 5
        userdata.svg.Filter(next).Subfilter.k = k;
    end
    userdata.svg.Filter(next).Subfilter.Result = result;
    set(s(i),'UserData', userdata);
end


function varargout = process_spikesorting_ultramegasort2000( varargin )
% PROCESS_SPIKESORTING_ULTRAMEGASORT2000:
% This process separates the initial raw signal to nChannels binary signals
% and performs spike sorting individually on each channel with the
% UltraMegaSort2000 spike-sorter. The spikes are clustered and assigned to
% individual neurons. The code ultimately produces a raw_elec(i)_spikes.mat
% for each electrode that can be used later for supervised spike-sorting.
% When all spikes on all electrodes have been clustered, all the spikes for
% each neuron is assigned to an events file in brainstorm format.

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Konstantinos Nasiotis, 2018-2022
%          Martin Cousineau, 2018
%          Francois Tadel, 2022

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'UltraMegaSort2000';
    sProcess.Category    = 'File';
    sProcess.SubGroup    = {'Electrophysiology','Unsupervised Spike Sorting'};
    sProcess.Index       = 1202;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/e-phys/SpikeSorting';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'raw'};
    sProcess.OutputTypes = {'raw'};
    sProcess.nInputs     = 1;
    sProcess.nMinFiles   = 1;
    sProcess.isSeparator = 0;
    % Spike sorter name
    sProcess.options.spikesorter.Type   = 'text';
    sProcess.options.spikesorter.Value  = 'ultramegasort2000';
    sProcess.options.spikesorter.Hidden = 1;
    % RAM limitation
    sProcess.options.binsize.Comment = 'Maximum RAM to use: ';
    sProcess.options.binsize.Type    = 'value';
    sProcess.options.binsize.Value   = {2, 'GB', 1};
    % Parallel processing
    sProcess.options.parallel.Comment = 'Parallel processing';
    sProcess.options.parallel.Type    = 'checkbox';
    sProcess.options.parallel.Value   = 0;
    % Use SSP/ICA
    sProcess.options.usessp.Comment = 'Apply the existing SSP/ICA projectors';
    sProcess.options.usessp.Type    = 'checkbox';
    sProcess.options.usessp.Value   = 1;
    % Separator
    sProcess.options.sep1.Type = 'label';
    sProcess.options.sep1.Comment = '
';
    % === Low bound
    sProcess.options.highpass.Comment = 'Lower cutoff frequency:';
    sProcess.options.highpass.Type    = 'value';
    sProcess.options.highpass.Value   = {700,'Hz ',0};
    % === High bound
    sProcess.options.lowpass.Comment = 'Upper cutoff frequency:';
    sProcess.options.lowpass.Type    = 'value';
    sProcess.options.lowpass.Value   = {5000,'Hz ',0};
    % Separator
    sProcess.options.sep2.Type = 'label';
    sProcess.options.sep2.Comment = '
';
    % Options: Options
    sProcess.options.edit.Comment = {'panel_spikesorting_options', 'UltraMegaSort2000 parameters: '};
    sProcess.options.edit.Type    = 'editpref';
    sProcess.options.edit.Value   = [];
    % Label: Reset options
    sProcess.options.edit_help.Comment = 'To restore default options: re-install the ultramegasort plugin.';
    sProcess.options.edit_help.Type    = 'label';
    % Label: Warning that pre-spikesorted events will be overwritten
    sProcess.options.warning.Comment = '
Warning: Existing spike events will be overwritten';
    sProcess.options.warning.Type    = 'label';
end

%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess) %#ok<DEFNU>
    Comment = sProcess.Comment;
end

%% ===== RUN =====
function OutputFiles = Run(sProcess, sInput) %#ok<DEFNU>
    OutputFiles = {};

    % ===== DEPENDENCIES =====
    % Not available in the compiled version
    if bst_iscompiled()
        bst_report('Error', sProcess, sInput, 'This function is not available in the compiled version of Brainstorm.');
        return
    end
    % Load plugin
    [isInstalled, errMsg] = bst_plugin('Install', 'ultramegasort2000');
    if ~isInstalled
        error(errMsg);
    end

    % ===== OPTIONS =====
    % Get option: bin size
    BinSize = sProcess.options.binsize.Value{1};
    if (BinSize <= 0)
        bst_report('Error', sProcess, sInput, 'Invalid maximum amount of RAM specified.');
        return
    end
    % Get other options
    isParallel = sProcess.options.parallel.Value;
    UseSsp = sProcess.options.usessp.Value;
    LowPass = sProcess.options.lowpass.Value{1}(1);
    HighPass = sProcess.options.highpass.Value{1}(1);

    % ===== LOAD INPUTS =====
    % Get protocol info
    ProtocolInfo = bst_get('ProtocolInfo');
    BrainstormTmpDir = bst_get('BrainstormTmpDir');
    % File path
    [fPath, fBase] = bst_fileparts(file_fullpath(sInput.FileName));
    % Remove "data_0raw" or "data_" tag
    if (length(fBase) > 10 && strcmp(fBase(1:10), 'data_0raw_'))
        fBase = fBase(11:end);
    elseif (length(fBase) > 5) && strcmp(fBase(1:5), 'data_')
        fBase = fBase(6:end);
    end

    % Load input files
    DataMat = in_bst_data(sInput.FileName, 'F');
    sFile = DataMat.F;
    % Check filtering frequencies
    nyq = floor(sFile.prop.sfreq/2);
    if (LowPass >= nyq)
        bst_report('Error', sProcess, sInput, ['Higher cutoff frequency must be lower than Nyquist frequency (' num2str(nyq) ' Hz).']);
        return;
    elseif (HighPass >= LowPass)
        bst_report('Error', sProcess, sInput, 'Higher cutoff frequency must be lower lower cutoff frequency.');
        return;
    end
    % Load channel file
    ChannelMat = in_bst_channel(sInput.ChannelFile);
    numChannels = length(ChannelMat.Channel);
    % Demultiplex channels
    demultiplexDir = bst_fullfile(BrainstormTmpDir, 'Unsupervised_Spike_Sorting', ProtocolInfo.Comment, sInput.FileName);
    elecFiles = out_demultiplex(sInput.FileName, sInput.ChannelFile, demultiplexDir, UseSsp, BinSize * 1e9, isParallel);

    % ===== OUTPUT FOLDER =====
    outputPath = bst_fullfile(fPath, [fBase '_ums2k_spikes']);
    previous_directory = pwd;
    % If output folder already exists: delete it
    if exist(outputPath, 'dir') == 7
        % Move Matlab out of the folder to be deleted
        if ~isempty(strfind(previous_directory, outputPath))
            cd(bst_fileparts(outputPath));
        end
        % Delete existing output folder
        try
            rmdir(outputPath, 's');
        catch
        	error(['Could not remove spikes folder: ' 10 outputPath 10 ' Make sure this folder is not open in another program.'])
        end
    end
    % Create output folder
    mkdir(outputPath);

    % ===== SPIKE SORTING =====
    cd(outputPath);
    if isParallel
        bst_progress('start', 'Spike-sorting', 'Extracting spikes...');
        parfor ielectrode = 1:numChannels
            do_UltraMegaSorting(elecFiles{ielectrode}, sFile, LowPass, HighPass, sFile.prop.sfreq);
        end
    else
        bst_progress('start', 'Spike-sorting', 'Extracting spikes...', 0, numChannels);
        for ielectrode = 1:numChannels
            do_UltraMegaSorting(elecFiles{ielectrode}, sFile, LowPass, HighPass, sFile.prop.sfreq);
            bst_progress('inc', 1);
        end
    end
    % Restore current folder
    cd(previous_directory);

    % ===== IMPORT EVENTS =====
    bst_progress('start', 'UltraMegaSort2000', 'Gathering spiking events...');
    % Delete existing spike events
    panel_spikes('DeleteSpikeEvents', sInput.FileName);

    % Build output filename
    NewBstFilePrefix = bst_fullfile(fPath, ['data_0ephys_ums2k_' fBase]);
    NewBstFile = [NewBstFilePrefix '.mat'];
    iFile = 1;
    commentSuffix = '';
    while exist(NewBstFile, 'file') == 2
        iFile = iFile + 1;
        NewBstFile = [NewBstFilePrefix '_' num2str(iFile) '.mat'];
        commentSuffix = [' (' num2str(iFile) ')'];
    end
    % Build output structure
    DataMat = struct();
    DataMat.Comment     = ['UltraMegaSort2000 Spike Sorting' commentSuffix];
    DataMat.DataType    = 'raw';
    DataMat.Device      = 'ultramegasort2000';
    DataMat.Name        = file_short(NewBstFile);
    DataMat.Parent      = file_short(outputPath);
    DataMat.RawFile     = sInput.FileName;
    DataMat.Spikes      = struct();
    % Build spikes structure
    spikes = dir(bst_fullfile(outputPath, 'times_raw_elec*.mat'));
    spikes = sort_nat({spikes.name});
    for iSpike = 1:length(spikes)
        DataMat.Spikes(iSpike).Path = file_short(outputPath);
        DataMat.Spikes(iSpike).File = spikes{iSpike};
        if exist(bst_fullfile(outputPath, DataMat.Spikes(iSpike).File), 'file') ~= 2
            DataMat.Spikes(iSpike).File = '';
        end
        DataMat.Spikes(iSpike).Name = ChannelMat.Channel(iSpike).Name;
        DataMat.Spikes(iSpike).Mod  = 0;
    end

    % Save events file for backup
    SaveBrainstormEvents(DataMat, 'events_UNSUPERVISED.mat');

    % Add history field
    DataMat = bst_history('add', DataMat, 'import', ['Link to unsupervised electrophysiology files: ' outputPath]);
    % Save file on hard drive
    bst_save(NewBstFile, DataMat, 'v6');
    % Add file to database
    db_add_data(sInput.iStudy, file_short(NewBstFile), DataMat);
    % Return new file
    OutputFiles{end+1} = NewBstFile;

    % ===== UPDATE DATABASE =====
    % Update links
    db_links('Study', sInput.iStudy);
    panel_protocols('UpdateNode', 'Study', sInput.iStudy);
end

%% ===== SAVE BRAINSTORM EVENTS =====
function SaveBrainstormEvents(SpikeMat, outputFile, eventNamePrefix)
    if nargin < 3
        eventNamePrefix = '';
    end

    numElectrodes = length(SpikeMat.Spikes);
    iNewEvent = 0;
    events = struct();

    % Add existing non-spike events for backup
    DataMat = in_bst_data(SpikeMat.RawFile);
    existingEvents = DataMat.F.events;
    for iEvent = 1:length(existingEvents)
        if ~panel_spikes('IsSpikeEvent', existingEvents(iEvent).label)
            if iNewEvent == 0
                events = existingEvents(iEvent);
            else
                events(iNewEvent + 1) = existingEvents(iEvent);
            end
            iNewEvent = iNewEvent + 1;
        end
    end

    for iElectrode = 1:numElectrodes
        newEvents = panel_spikes(...
            'CreateSpikeEvents', ...
            SpikeMat.RawFile, ...
            SpikeMat.Device, ...
            bst_fullfile(file_fullpath(SpikeMat.Parent), SpikeMat.Spikes(iElectrode).File), ...
            SpikeMat.Spikes(iElectrode).Name, ...
            1, eventNamePrefix);

        if iNewEvent == 0
            events = newEvents;
            iNewEvent = length(newEvents);
        else
            numNewEvents = length(newEvents);
            events(iNewEvent+1:iNewEvent+numNewEvents) = newEvents;
            iNewEvent = iNewEvent + numNewEvents;
        end
    end

    save(bst_fullfile(file_fullpath(SpikeMat.Parent), outputFile),'events');
end

%% ===== ULTRAMEGA SORTING =====
function do_UltraMegaSorting(electrodeFile, sFile, LowPass, HighPass, Fs)
    [path, filename] = fileparts(electrodeFile);
    % Apply BST bandpass filter
    try
        DataMat = load(electrodeFile, 'data');
        filtered_data = bst_bandpass_hfilter(DataMat.data', Fs, HighPass, LowPass, 0, 0);
    catch e
        error(['Frequency filtering failed, try with a different frequency band.' 10 'Error: ' e.message]);
    end
    % Convert to a column vector in a cell array
    filtered_data = {filtered_data'};
    % Run spike sorting
    try
        spikes = ss_default_params(sFile.prop.sfreq);
        spikes = ss_detect(filtered_data,spikes);
        spikes = ss_align(spikes);
        spikes = ss_kmeans(spikes);
        spikes = ss_energy(spikes);
        spikes = ss_aggregate(spikes);
        save(['times_' filename '.mat'], 'spikes')
    catch e
        % If an error occurs, just don't create the spike file.
        clean_label = strrep(filename,'raw_elec_','');
        disp(e);
        disp(['Warning: Spiking failed on electrode ' clean_label '. Skipping this electrode.']);
    end
end


function B = tomatrix(A)
    % Flatten the symbolic expression

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

    % construct the operation string
    sstr = ['ToMatrixForm[' A.s ']'];

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

end


function [debug] = convertERTSimLogs(data_file, parser_config, save_file, slow_on)

% Author: Alexander Wischnewski     Date: 21-12-2018
%
% Description:
%   converts the logs of a GRT target based debug file (e.g. compiled
%   binary simulation on windows or unix) into the common log format.
%
% Input:
%   data_file:              Log data file
%   parser_config:          Parser config
%   save_file:              Output data file
%   slow_on:                true/false value for parsing extended slow
%   dataset
% Output:
%   debug:                  Struct with all timeseries in there

    % check if file ending is given and modify load files accordingly
    if(endsWith(data_file, '.txt'))
        file_standard = data_file;
        file_slow = [data_file(1:end-4) '_slow.txt'];
    else
        file_standard = [data_file '.txt'];
        file_slow = [data_file '_slow.txt'];
    end
    % check if parser config ending is given and modify load files accordingly
    if(endsWith(parser_config, '.txt'))
        config_standard = parser_config;
        config_slow = [parser_config(1:end-4) '_slow.txt'];
    else
        config_standard = [parser_config '.txt'];
        config_slow = [parser_config '_slow.txt'];
    end
    % load and parse data from standard logging file
    try
        data = dlmread(file_standard, ';');
        % skip last data point as it might not be fully written!
        debug = convertArrayToTs(data(1:end-1, :), config_standard);
        disp('Successfully parsed standard logging file!');
    catch
        disp('Could not parse standard logging file!');
        debug = 0;
    end

    % load and parse data from slow logging file
    if slow_on
        data_slow = dlmread(file_slow, ';');
        % skip last data point as it might not be fully written!
        debug_slow = convertArrayToTs(data_slow(1:end-1, :), config_slow);
        debug_slow = convertSeperateTsToArrayTs(debug_slow);
        disp('Successfully parsed slow logging file!');
            % write to file if its wanted by the user
        if(nargin == 4)
          save(save_file, 'debug', 'debug_slow', '-v7.3');
        end
    else
        % write to file if its wanted by the user
        if(nargin == 4)
          save(save_file, 'debug','-v7.3');
        end
    end
end


function z = isequal( x, y )

% This only works if we treat CVX objects as immutable.
z = x.id_ == y.id_;

% Copyright 2005-2014 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function[p] = gui_erp_plot(p)

% gui_erp_plot - eeg_toolbox plot for ERP data
%
%[p] = erp_plot(p)
%
% creates a GUI interface for ERP measurement and
% topographic mapping functions.
%

% $Revision: 1.1 $ $Date: 2009-04-28 22:13:56 $

% Licence:  GNU GPL, no express or implied warranties
% History:  10/2003, Darren.Weber_at_radiology.ucsf.edu
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

plotfig = figure('Name',p.volt.file,...
  'NumberTitle','off',...
  'UserData',p);

movegui(plotfig,'center');

plot(p.volt.timeArray,p.volt.data);
axis tight;
eeg_plot_metric;

[Xpoint,Ypoint] = eeg_crosshair('init',p);

return


function plot_srcColorbar(cmin,cmax)

colormap(abs((gui_Colormap_ReadPovRay('SRC-Discrete.pov'))))
set(gca,'CLim',[cmin cmax]);
colorbar('Location','EastOutside',...
    'YLim',[cmin cmax]);