function [] = aps_spectrometer_PWV_meris(batchfile)
% aps_spectrometer_PWV_comparison(datelist)
% Scipt to load meris data, mask out clouds. The meris data is assumed to
% be structured in date folders. The batchfile contains the full path to the
% meris files in these folders. Note that the first line of the batchfile should read "files".
%
%
% INPUTS:
% batchfile             A txt file containing the full path and file names of the
%                       meris data that needs to be processed. The first
%                       line of this file should read "files". The data
%                       should be structured in date folders.
% xlims                 Limits in the x-direction, either in degrees
% ylims                 Limits in the y-direction, either in degrees
% smpres                The output resolution, either in degrees
%                       Units needs to be consistend with xlims and ylims.
%
%
% By David Bekaert - University of Leeds
% August 2014

fig_test = 1;                   % when 1 show the dem as debug figure

if nargin<1
    fprintf('aps_spectrometer_PWV_meris(batchfile) \n')
    error('myApp:argChk', ['Not enough input arguments...\n'])
end

smpres = getparm_aps('region_res',1); % in degrees
xlims = getparm_aps('region_lon_range',1);
ylims = getparm_aps('region_lat_range',1);
stamps_processed = getparm_aps('stamps_processed',1);

%% the actual scripting
%bounds for all ifgs in degrees or in meters
xmin = xlims(1);
xmax = xlims(2);
ymin = ylims(1);
ymax = ylims(2);

% getting the number of files to be processed
files = char(textread(batchfile,'%s','headerlines',1));
ndates = size(files,1);

% loading the date information
if strcmp(stamps_processed,'y')
   ps = load(getparm_aps('ll_matfile',1));
   ifgs_dates = ps.day;
   fprintf('Stamps processed structure \n')
else
    ifgday_matfile = getparm_aps('ifgday_matfile',1);
    ifgs_dates = load(ifgday_matfile);
    ifgs_dates = ifgs_dates.ifgday;
    ifgs_dates = reshape(ifgs_dates,[],1);
    ifgs_dates = unique(ifgs_dates);
end

fprintf(['Lon range: ' num2str(xmin) ' -- '  num2str(xmax) ' degrees\n'])
fprintf(['Lat range: ' num2str(ymin) ' -- '  num2str(ymax) ' degrees\n'])
fprintf(['Output resolution is assumed to be ' num2str(smpres) ' degrees \n'])

% extracting the dates from the filenames
for k=1:ndates
    [path,filename_temp,ext_temp] = fileparts(files(k,:));
    clear filename_temp ext_temp
    [path_temp,date,ext_temp] = fileparts(path);
    clear path_temp ext_temp

    % save the paths as structures to allow for variable path lengths
    pathlist{k} = path;
    clear path
    % saving the date information
    datelist(k,:) =date;
    clear date
end

%start loop here to calculate atmos correction for each date
fprintf('Starting the masking and writing of the PWV for each SAR date \n')
for n = 1:ndates

    file = [files(n,:)];
    outfile_watervapor = [pathlist{n} filesep datelist(n,:) '_ZPWV_nointerp.xyz'];

    % get info on meris file from tif
    tifinfo = geotiffinfo(file);
    mer_xmin = tifinfo.CornerCoords.X(1);
    mer_xmax = tifinfo.CornerCoords.X(2);
    mer_ymin = tifinfo.CornerCoords.Y(3);
    mer_ymax = tifinfo.CornerCoords.Y(1);
    mer_cols = tifinfo.Width;
    mer_rows = tifinfo.Height;
    mer_x = (mer_xmax - mer_xmin)/mer_cols;
    mer_y = (mer_ymax - mer_ymin)/mer_rows;
    % read in tif
    meris=imread(file,'tif');

    %% Calculate wet delay if desired

    %do masking, interpolating etc here.
    %convert flag matrix to long list of binary numbers e.g. 1000010000010000
    flagbin = dec2bin(meris(:,:,33));

    %% Generating cloud mask
    %take certain bits of binary numbers (e.g. second bit, 1=cloud), and reshape
    %into matrix mask
    cloud = bin2dec(flagbin(:,2));
    cloudmat=reshape(cloud,mer_rows,mer_cols);
    cloudmat(cloudmat==1)=NaN;

    % turn ones (i.e. mask pixels) into NaNs so when we multiply masks together,
    % NaNs will penetrate through the stack
    pconf = bin2dec(flagbin(:,23));
    pconfmat=reshape(pconf,mer_rows,mer_cols);
    pconfmat(pconfmat==1)=NaN;
    lowp = bin2dec(flagbin(:,24));
    lowpmat=reshape(lowp,mer_rows,mer_cols);
    lowpmat(lowpmat==1)=NaN;
    maskmat= cloudmat .*pconfmat .*lowpmat;
    maskmat(isnan(maskmat))=1;

    %extend mask edges
    se = strel('square', 3);
    maskmat = imdilate(maskmat,se);
    maskmat(maskmat==1)=NaN;
    maskmat(maskmat==0)=1;

    %% loading and masking of the data
    %load water vapour
    watervap=meris(:,:,14);   % g/cm^2  water vapour
    %mask out dodgy pixels
    corwatervap = watervap .*maskmat;

    %% mask water additional
    %%% aditonal masking
    % water mask
    water = bin2dec(flagbin(:,3));
    water=reshape(water,mer_rows,mer_cols);

    %decrease water mask edges, to make sure we do not remove land points
    se = strel('square', 3);
    water_new = imerode(water,se);
    water_new(water_new==1)=NaN;
    water_new(water_new==0)=1;
    clear water
    corwatervap = corwatervap.*water_new;

    %% saving the data
    fid = fopen('out.bin','w');
    corwatervap = corwatervap';
    fwrite(fid,corwatervap,'real*4');
    fclose(fid);

    % do gmt resample and cut
    xyz2grd_cmd = ['xyz2grd -R',num2str(mer_xmin),'/',num2str(mer_xmax),'/',num2str(mer_ymin),'/',num2str(mer_ymax),' -I',num2str(mer_cols),'+/',num2str(mer_rows),'+ out.bin -Gtmp.grd  -F -ZTLf'];
    [a,b] = system(xyz2grd_cmd);

    % downsample and output without interpolation files
    grdsmp_cmd = ['grdsample -R',num2str(xmin),'/',num2str(xmax),'/',num2str(ymin),'/',num2str(ymax),' -I',num2str(smpres),' -F tmp.grd -Gtmp_smp.grd'];
    [a,b]=system(grdsmp_cmd);
    grd2xyz_cmd = ['grd2xyz -R',num2str(xmin),'/',num2str(xmax),'/',num2str(ymin),'/',num2str(ymax),' tmp_smp.grd -bo >' outfile_watervapor];
    [a,b]=system(grd2xyz_cmd);

    % load gaussian and nointerp back in, combine, and output as outfile_gauss
    % opening the data file (not-interpolated)
    nointfid = fopen(outfile_watervapor,'r');
    data_vector = fread(nointfid,'double');
    fclose(nointfid);
    % reshaping into the right n column matrix
    data = reshape(data_vector,3,[])';
    noint = data(:,3);
    xy = data(:,[1:2]);
    clear data data_vector

%     figure; scatter3(xy(:,1),xy(:,2),noint,15,noint,'filled'); view(0,90); axis equal; axis tight

    % writing out the date again as a binary table
    data_write = [xy noint]';
    clear noint xy
    %output
    fid = fopen(outfile_watervapor,'w');
    fwrite(fid,data_write,'double');
    fclose(fid);
    clear data_write

    fprintf([num2str(n) ' completed out of ' num2str(ndates) '\n'])

end

[a b] = system('!rm tmp.grd tmp.xyz out.bin tmp2.grd tmp_fil.grd tmp_smp.grd tmp_smp.xyz tmp_smp2.grd tmp_smp_fil.grd');


classdef TestBrightEdges
    %TestBrightEdges

    methods (Static)
        function test_1
            img = imread(fullfile(mexopencv.root(),'test','balloon.jpg'));
            out = cv.BrightEdges(img, 'Contrast',1);
            validateattributes(out, {'uint8'}, ...
                {'size',[size(img,1) size(img,2)]});
        end
    end

end


function b = ne(q1,q2)
% q1 ~= q2 ?

b = ~ (q1 == q2);


function varargout=lpcpp2cw(varargin)
%
% For calling details please see v_lpcpp2cw.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_lpcpp2cw.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: lpcpp2cw.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_lpcpp2cw(varargin{:});
else
    v_lpcpp2cw(varargin{:});
end


function output = memtic(action, counter)

% MEMTIC start a MATLAB memory recorder
%
%   MEMTIC and MEMTOC functions work together to measure memory usage.
%   MEMTIC, by itself, saves the current memory footprint that MEMTOC
%   uses later to measure the memory that was used between the two.
%
% Use as
%   MEMTIC
%   MEMTOC
% to print the estimated memory use on screen, or
%   MEMTIC
%   M = MEMTOC
% to return the estimated memory (in bytes) in variable M, or
%   C = MEMTIC
%   M = MEMTOC(C)
% to specifically estimate the memory use between a well-defined tic/toc pair.
%
% Note that MATLAB uses internal memory allocation, garbage collection, shallow
% copies of variables, and virtual memory. Due to the advanced handling of
% memory for its variables, it is not easy and in certain cases not possible to
% make a reliable and reproducible estimate based on the memory information
% provided by the operating system.
%
% Example: measure the memory increase due to allocating a lot of memory.
% Doing a "clear x" following the allocation and priot to MEMTOC does not
% affect the memory that is reported.
%
%   memtic
%   n = 125; x = cell(1,n);
%   for i=1:n
%     x{i} = randn(1000,1000); % 8kB per item
%     disp(i);
%   end
%   whos x
%   memtoc
%
% See also TIC, TOC

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

persistent state

if nargin<1
  action = 'tic';
end

% the memtic/memtoc functions make use of a low-level mex file that interacts directly with the operating system
% do not fail if the mex file does not exist
if isempty(strfind(which('memprofile'), mexext))
  switch action
    case 'tic'
      if nargout
        output = nan;
      end
    case 'toc'
      if nargout
        output = nan;
      end
    otherwise
      ft_error('invalid input argument #1');
  end % switch
  return
end % if mex file does not exist

% get the current usage, this will start memprofile if needed
memstat = memprofile('info');

switch action
  case 'tic'
    if nargin>1
      ft_error('the counter cannot be specified as imput argument');
    end

    counter = length(state)+1;
    state(counter).running = true;
    state(counter).time    = memstat(end).time;
    state(counter).mem     = memstat(end).mem;

    if nargout
      output = counter;
    end

  case 'toc'
    if nargin<2
      % take the latest
      counter = length(state);
    elseif counter<1 || counter>numel(state)
      ft_error('invalid counter');
    end

    if counter==0
      memused = 0;
    else
      sel = [memstat.time]>=state(counter).time;
      memused = max([memstat(sel).mem]);       % determine the maximum
      memused = memused - state(counter).mem;  % subtract the initial value
    end

    if nargout
      output = memused;
    end

  otherwise
    ft_error('invalid input argument #1');
end % switch


function meshfaces_test ( )

%*****************************************************************************80
%
%% MAIN tests the MESHFACES library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 August 2014
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'MESHFACES_TEST:\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the MESHFACES library.\n' );

  meshfaces_test01 ( );
  meshfaces_test02 ( );
  meshfaces_test03 ( );
  meshfaces_test04 ( );
  meshfaces_test05 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'MESHFACES_TEST:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


%BUILDOPTICALFLOWPYRAMID  Constructs the image pyramid which can be passed to cv.calcOpticalFlowPyrLK
%
%     pyramid = cv.buildOpticalFlowPyramid(img)
%     [pyramid,maxLvl] = cv.buildOpticalFlowPyramid(img)
%     pyramid = cv.buildOpticalFlowPyramid(img, 'OptionName',optionValue, ...)
%
% ## Input
% * __img__ 8-bit input image.
%
% ## Output
% * __pyramid__ output pyramid. A cell-array of matrices (pyramid levels),
%   interleaved with corresponding gradients if `WithDerivatives` flag is
%   true. Each gradient is a matrix of type `int16` of same size as pyramid at
%   that level with 2-channels.
% * __maxLvl__ number of levels in constructed pyramid. Can be less than
%   `MaxLevel`.
%
% ## Options
% * __WinSize__ window size of optical flow algorithm. Must be not less than
%   `WinSize` argument of cv.calcOpticalFlowPyrLK. It is needed to calculate
%   required padding for pyramid levels. default [21,21]
% * __MaxLevel__ 0-based maximal pyramid level number. default 3
% * __WithDerivatives__ set to precompute gradients for the every pyramid
%   level. If pyramid is constructed without the gradients then
%   cv.calcOpticalFlowPyrLK will calculate them internally. default true
% * __PyrBorder__ the border mode for pyramid layers. See cv.copyMakeBorder.
%   default 'Reflect101'
% * __DerivBorder__ the border mode for gradients. See cv.copyMakeBorder.
%   default 'Constant'
% * __TryReuseInputImage__ put ROI of input image into the pyramid if
%   possible. You can pass false to force data copying. default true
%
% See also: cv.calcOpticalFlowPyrLK, cv.buildPyramid
%


function startPreciseHandGuiding1( t,wightOfTool,COMofTool )
%% About:
% This function is used to start the handguiding functionality on the robot

%% Syntax:
% [ output_args ] = startPreciseHandGuiding1( t,wightOfTool,COMofTool )

%% Arreguments:
% t: is the TCP/IP connection object
% wightOfTool: weight of the tool connected to the flange in newton, unit Newtons.
% COMofTool: coordinates of the center of mass of the tool, descirbed in
% the reference frame of the flange (mm).

% Copy right, Mohammad SAFEEA, 22nd of Oct 2017

com=colVec(COMofTool)/1000; % convert from mm to meter
wot=-wightOfTool; % negtive, wight of tool described in base frame of robot

if(sum(size(com)==[3,1])==2)
else
    fprintf('Error: COMofTool vector is not in the right dimention \n');
    disp('Function termintated');
    return;
end

if norm(com)>0.5
    fprintf('Error: COMofTool vector shall not have a norm bigger than 0.5 meters \n');
    disp('Function termintated');
    return;
end

if(sum(size(wot)==[1,1])==2)
else
    fprintf('Error: wightOfTool variable is not in the right dimention \n');
    disp('Function termintated');
    return;
end

s='preciseHandGuiding1';
s=[s,'_',num2str(wot)];
for i=1:3
	s=[s,'_',num2str(com(i))];
end
theCommand=s;
fprintf(t, theCommand);

fprintf('Precise hand gudining functionality is started \n');
fprintf('To terminate the precise hand guding function, press the green button for more than 5 sec');
fprintf('\n keep pressing until the red light starts to flicker then release your hand, ')
fprintf('\n the hand guiding mode will be terminated ');

    message='';
    w = warning ('off','all');
    readingFlag=false;
    while readingFlag==false
        message=fgets(t);

        if checkAcknowledgment(message)
            readingFlag=true;
        end
    end
     w = warning ('on','all');
    fprintf('Hand gudining was terminated by user at robot side \n');
end

function y=colVec(x)
    if(size(x,2)==1)
        y=x;
    else
        y=x';
    end
end


function TS_Init(INP_ts,whatFeatureSet,beVocal,outputFile)
% TS_Init  Produces a formatted HCTSA .mat file from input files
%
% This function is used instead to run hctsa analysis without a linked mySQL database.
%
%---EXAMPLE USAGE:
% Initiate an HCTSA.mat file on a custom time-series dataset using the hctsa
% feature library, using a formatted input file, 'my_TS_INP_file.mat'
% >> TS_Init('my_TS_INP_file.mat','hctsa');
%
%---INPUTS:
% INP_ts: A time-series input file
% whatFeatureSet: EITHER a feature-set name (like 'hctsa' or 'catch22')
%             OR a 1x2 cell of filenames for INP_mops (master operations input file)
%                   and INP_ops (an operations input file)
% beVocal: Whether to display details of the progress of the script to screen.
%           a 3-vector, specifying for 1. time series, 2. master operations,
%           and 3. operations.
% outputFile: Specify an output filename
%
%---OUTPUTS:
% Writes output to HCTSA.mat (or specified custom filename: outputFile)

% ------------------------------------------------------------------------------
% Copyright (C) 2020, Ben D. Fulcher <ben.d.fulcher@gmail.com>,
% <http://www.benfulcher.com>
%
% If you use this code for your research, please cite the following two papers:
%
% (1) B.D. Fulcher and N.S. Jones, "hctsa: A Computational Framework for Automated
% Time-Series Phenotyping Using Massive Feature Extraction, Cell Systems 5: 527 (2017).
% DOI: 10.1016/j.cels.2017.10.001
%
% (2) B.D. Fulcher, M.A. Little, N.S. Jones, "Highly comparative time-series
% analysis: the empirical structure of time series and their methods",
% J. Roy. Soc. Interface 10(83) 20130048 (2013).
% DOI: 10.1098/rsif.2013.0048
%
% This work is licensed under the Creative Commons
% Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of
% this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send
% a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View,
% California, 94041, USA.
% ------------------------------------------------------------------------------

% ------------------------------------------------------------------------------
% Check Inputs:
% ------------------------------------------------------------------------------
if nargin < 1 || isempty(INP_ts)
    error('Please supply a formatted time-series input file (see documentation for details).');
end
if nargin < 2
    whatFeatureSet = 'hctsa';
end
if nargin < 3
    if iscell(whatFeatureSet)
        beVocal = [true,true,true]; % Provided all custom input files--walks you through all of them
    else
        beVocal = [true,false,false]; % by default helps you just for the time series input file you provided
    end
end
if length(beVocal)==1
    beVocal = repmat(beVocal,1,3);
end
if nargin < 4
    outputFile = 'HCTSA.mat';
end

% ------------------------------------------------------------------------------
% First check if you're about to overwrite an existing file
% ------------------------------------------------------------------------------
if exist(['./',outputFile],'file')
    reply = input(sprintf(['Warning: %s already exists -- if you continue, this ' ...
        'file will be overwritten.\n[press ''y'' to continue] '],outputFile),'s');
    if ~strcmp(reply,'y')
        return
    end
end

%-------------------------------------------------------------------------------
% Convert a feature-set name to a set of input files
%-------------------------------------------------------------------------------
if ischar(whatFeatureSet)
    [INP_mops,INP_ops] = TS_GiveMeInputFiles(whatFeatureSet);
elseif iscell(whatFeatureSet)
    INP_mops = whatFeatureSet{1};
    fprintf(1,'Information about master operations taken from ''%s''\n',INP_mops);
    INP_ops = whatFeatureSet{2};
    fprintf(1,'Information about operations taken from ''%s''\n',INP_ops);
else
    error('Unknown format for setting the feature set')
end

%-------------------------------------------------------------------------------
% First check that all input files provided exist:
%-------------------------------------------------------------------------------
checkFiles = {INP_ts,INP_mops,INP_ops};
for i = 1:3
    if ~exist(checkFiles{i},'file')
        error('Unknown file: ''%s''',checkFiles{i});
    end
end

% ------------------------------------------------------------------------------
% Get time series, operations, master operations into structure arrays
% ------------------------------------------------------------------------------
TimeSeries = SQL_Add('ts',INP_ts,false,beVocal(1));
numTS = height(TimeSeries);
if numTS==0
    return; % The user did not approve of the set of inputs
end

MasterOperations = SQL_Add('mops',INP_mops,false,beVocal(2));
numMops = height(MasterOperations);
if numMops==0
    return; % The user did not approve of the set of inputs
end

Operations = SQL_Add('ops',INP_ops,false,beVocal(3));
numOps = height(Operations);
if numOps==0
    return; % The user did not approve of the set of inputs
end

%-------------------------------------------------------------------------------
% Link operations to their masters using label matching
% and update the structure arrays using the TS_LinkOperationsWithMasters function
%-------------------------------------------------------------------------------
[Operations,MasterOperations] = TS_LinkOperationsWithMasters(Operations,MasterOperations);
% MasterOperations may have been trimmed by TS_LinkOperationsWithMasters:
numMops = height(MasterOperations);

% ------------------------------------------------------------------------------
% Generate the TS_DataMat, TS_Quality, and TS_CalcTime matrices
% ------------------------------------------------------------------------------
% All NaNs -> NULL (haven't yet been calculated)
TS_DataMat = nan(numTS,numOps);
TS_Quality = nan(numTS,numOps);
TS_CalcTime = nan(numTS,numOps);

%-------------------------------------------------------------------------------
% Get git information to keep track of the version of code used at the time of TS_Init
%-------------------------------------------------------------------------------
gitInfo = TS_AddGitInfo();

% ------------------------------------------------------------------------------
% Save to file
% ------------------------------------------------------------------------------
% Set a flag, fromDatabase, that tells you that you that this was generated by
% TS_Init and shouldn't be written back to a database
fromDatabase = false;
save(outputFile,'TimeSeries','Operations','MasterOperations',...
            'TS_DataMat','TS_Quality','TS_CalcTime','fromDatabase','gitInfo','-v7.3');

fprintf(1,'Successfully initialized file ''%s'' with %u time series, %u master operations, and %u operations.\n',...
                        outputFile,numTS,numMops,numOps);

end


function varargout=estnoisem(varargin)
%
% For calling details please see v_estnoisem.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_estnoisem.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: estnoisem.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_estnoisem(varargin{:});
else
    v_estnoisem(varargin{:});
end


function [doBvecs, dwParams] = dtiInitBuildBVs(dwDir,dwParams)
%
%   [doBvecs dwDir dwParams] = dtiInitBVs(dwDir,dwParams);
%
% Generate bvecs file and a bvals file from a dwepi.grads file.
%
% *** FIX ME: get the bval and grad dir file number from the dicom header.
% *** IS THIS FUNCTION STILL USED IN THE MODERN AGE?  (BW)
%
% NOTE:
% Most sequences will need the bvecs reoriented based on the
% scanner-to-image transform stored in qto_ijk. But, for the sequence we
% used many years ago from Roland Bammer sequence, the bvecs were rotated
% during image acquisition.
%
% INPUTS
%       (dwDir,dwParams) - passed in from dtiInit
% RETURNS
%       [doBvecs dwDir dwParams] - with paths to built bvecs and bvals
%                                  files
% (C) Stanford VISTA, 8/2011 [lmp]

%% Generate bvecs file and a bvals file from a dwepi.grads file.

warning('** Building bvecs and bvals from dtiInitBuildBVs **')

doBvecs = true;

% Directory with gradient direction code files
gradsDir = fullfile(dwDir.mrDiffusionDir,'gradFiles');

% Get bval and gradient directions code from name file name
if ~exist('dwParams.bvalue','var') || isempty(dwParams.bvalue)
    [dwParams.bvalue, gradDirsCodeTmp] = dtiRawGetBvalVecFromName(dwDir.inBaseName);
end

if(~exist('dwParams.gradDirsCode','var')||isempty(dwParams.gradDirsCode))
    if(exist('gradDirsCodeTmp','var'))
        dwParams.gradDirsCode = gradDirsCodeTmp;
    else
        [dwParams.bvalue, dwParams.gradDirsCode] = dtiRawGetBvalVecFromName(filename);
    end
end

% If we can't guess the gradDirsCode we ask for it.
if(isempty(dwParams.gradDirsCode))
    [f,p] = uigetfile({'*.grads';'*.*'},'Select the GE grads file...',gradsDir);
    if isnumeric(f); error('Canceled.'); end
    dwParams.gradDirsCode = fullfile(p,f);
end

% Set the gradsFile to use
if(ischar(dwParams.gradDirsCode))
    gradsFile = dwParams.gradDirsCode;
else
    gradsFile = fullfile(gradsDir,sprintf('dwepi.%d.grads',dwParams.gradDirsCode));
end

% Actually build the bvecs/vals
dtiRawBuildBvecs(size(dwRaw.data,4), eye(4), gradsFile, dwParams.bvalue,...
                 dwDir.inBaseDir, dwParams.flipLrApFlag);

fprintf('bvalsFile = %s; %% (dwParams.bvalue = %0.3f)\nbvecsFile = %s; %%(dwParams.gradDirsCode = %d)\n', dwDir.bvalsFile,dwParams.bvalue,dwDir.bvecsFile,dwParams.gradDirsCode);

return


function y = gt(X,Y)
%GT (overloaded)

if isa(X,'blkvar')
    X = sdpvar(X);
end

if isa(Y,'blkvar')
    Y = sdpvar(Y);
end

try
    y = constraint(X,'>',Y);
catch
    error(lasterr)
end


function blockface_correct_frame_shifts(indir, files, t, idxnoprop, outdir)
% blockface_correct_frame_shifts  Correct shift between blockface image
% frames.
%
% When the wax block is sliced with a microtome, and photographs taken of
% the blockface, artifacts invariable happen. Artifacts are typically
% caused by the microtome tray not being pushed all the way back
% (translation artifacts), or by the camera, mirrors or any other elements
% in the light path being moved a little (similarity transform artifacts).
%
% This function assumes that the corrective transforms between consecutive
% frames have been already computed with elastix. The user provides a list
% of frames that need to be corrected, and blockface_correct_frame_shifts
% computes the accumulated transform for each frame, and applies it with
% transformix. Corrected images are saved with the same name as input
% images, but to a different directory.
%
% The transformation of images uses a "parfor" loop, so the function can
% take advantage of multiple cores.
%
% blockface_correct_frame_shifts(INDIR, FILES, T, IDXNOPROP, OUTDIR)
%
%   INDIR is a string with the directory where the input files are kept.
%
%   FILES is the result of a dir() command with a list of the files to
%   correct.
%
%   T is a struct array where T(I) is the correction that registers image I
%   to image I-1. T can be obtained with blockface_intraframe_reg.
%
%   IDXNOPROP is a vector with a list of indices of frames that need to be
%   corrected, but whose correction does not propagate. For example, if the
%   microtome tray is not pushed all the way in in frame I=30, that doesn't
%   mean that that problem will appear in frame I = 31. This is useful if
%   e.g. the camera has been very stable, but now and then the human
%   operator doesn't push the tray all the way back, as it avoids
%   unncessary small transforms and resampling of images.
%
%   OUTDIR is a string with the directory for output images. INDIR and
%   OUTDIR must be different to avoid overwriting the input files.
%
% See also: blockface_intraframe_reg.

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2014, 2016 University of Oxford
% Version: 0.2.2
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% 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. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

% check arguments
narginchk(5, 5);
nargoutchk(0, 0);

% safety to prevent us from overwriting the source files
if (strcmp(indir, outdir))
    error('Input and output directory are the same, and files would be overwritten')
end

% if destination directory doesn't exist, create it
if (isempty(dir(outdir)))
    ok = mkdir(outdir);
    if (~ok)
        error(['Cannot create output directory: ' outdir])
    end
end

% first frame will be used as a reference for the rest
% copytogreyfile([pathstr filesep files(1).name], ...
%     [outdir filesep files(1).name]);

% initialize array for the accumulated transform for each frame
tAcc = t(1);

% clear up transform for first frame
tAcc(1).TransformParameters = [1 0 0 0];

% for transforms that do not propagate, we need to cancel them with an
% inverse transform in the next slice
for I = idxnoprop

    % if the slice is the last in the stack, there's no next slice to
    % cancel the transform with
    if (I == length(files))
        continue
    end

    % the next slice must have no transformation, otherwise the list of
    % indices is wrong
    if any(t(I+1).TransformParameters ~= [1 0 0 0])
        error(['User says that T(' num2str(I) ') does not propagate, but T(' ...
            num2str(I+1) ') ~= [1 0 0 0]'])
    end

    % cancel the transformation
    tMatrix = elastix_affine_struct2matrix(t(I));
    t(I+1) = elastix_affine_matrix2struct(inv(tMatrix), t(I+1));

end

% accumulate transforms
for I = 2:length(t)

    % update the accumulated transform with the transform for this
    % frame
    tAcc(I) = elastix_compose_afftransf(tAcc(I-1), t(I));

end

% correct frames
parfor I = 1:length(files)

    % is the transform the identity?
    if (all(tAcc(I).TransformParameters == [1 0 0 0]))

        % simply convert to grayscale and copy
        copytogreyfile([indir filesep files(I).name], ...
            [outdir filesep files(I).name]);

    else

        % affine transformation of image to correct frame shifts
        fileout = transformix(tAcc(I), [indir filesep files(I).name]);

        % copy result to file
        copytogreyfile(fileout, ...
            [outdir filesep files(I).name]);

        % delete the temp result file
        delete(fileout);

    end

end

end

function copytogreyfile(filein, fileout)

% check that the image is grayscale. Otherwise, we convert it,
% because elastix uses the first channel and ignores the rest. As
% all transformed images will be converted to grayscale, we also
% convert images that are not shifted, so that they are all
% grayscale
info = imfinfo(filein);

switch (info.ColorType)
    case 'truecolor'

        % load image
        im = imread(filein);

        % convert to grayscale
        im = rgb2gray(im);

        % write image to destination
        imwrite(im, fileout);

    case 'grayscale'

        % if the image is already grayscale, we can directly copy
        % it
        ok = copyfile(filein, fileout);
        if (~ok)
            error(['Cannot copy image ' filein ' to file ' fileout])
        end

    otherwise

        error('Image in input file is neither RGB nor grayscale')
end

end


% Digital Video Stabilization and Rolling Shutter Correction using Gyroscopes
% Copyright (C) 2011 Alexandre Karpenko
%
% 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
% 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/>.

function [mov num_frames vid_height vid_width frame_rate duration] = import_video(file)

% read corresponding movie
xyloObj = mmreader(['data/' file '.mov']);
display(xyloObj);

num_frames = xyloObj.NumberOfFrames;
vid_height = xyloObj.Height;
vid_width = xyloObj.Width;
frame_rate = xyloObj.FrameRate;
duration = xyloObj.Duration;

% Preallocate movie structure.
mov(1:num_frames) = ...
    struct('cdata', zeros(vid_height, vid_width, 3, 'uint8'),...
           'colormap', []);

% Read one frame at a time.
for k = 1 : num_frames
    mov(k).cdata = read(xyloObj, k);
end
% Play back the movie once at the video's frame rate.
% movie(mov, 1, xyloObj.FrameRate);

%save(['mat/' file], 'gyro', 'frame_time', 'mov', 'num_frames', 'vid_height', 'vid_width', 'frame_rate', 'duration');


function spm_save(f,var,varargin)
% Save text and numeric data to file
% FORMAT spm_save(f,var,opts,...)
% f     - filename (can be gzipped) {csv,tsv,json,txt,mat,npy}
% var   - data array or structure
% opts  - optional inputs to be passed on to lower level function
%__________________________________________________________________________
% Copyright (C) 2018-2019 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_save.m 7668 2019-09-27 10:44:45Z guillaume $

ext = lower(spm_file(f,'ext'));
if isempty(ext), ext = ''; end
switch ext

    case 'gz'
        fgz = spm_file(f,'basename');
        spm_save(fgz,var,varargin{:});
        gzip(fgz);
        delete(fgz);

    case {'csv','tsv'}
        if strcmp(ext,'csv')
            delim = ',';
        else
            delim = sprintf('\t');
        end
        if isstruct(var) || iscell(var) || isnumeric(var) || islogical(var)
            if isstruct(var)
                fn = fieldnames(var);
                var = struct2cell(var)';
                for i=1:numel(var)
                    var{i} = var{i}(:);
                    if ~iscell(var{i})
                        var{i} = cellstr(num2str(var{i},16));
                        var{i}(cellfun(@(x) strcmp(x,'NaN'),var{i})) = {'n/a'};
                    end
                end
                var = [fn'; var{:}];
            elseif iscell(var)
                var = cellfun(@(x) num2str(x,16), var, 'UniformOutput',false);
            elseif isnumeric(var) || islogical(var)
                var = num2cell(var);
                var = cellfun(@(x) num2str(x,16), var, 'UniformOutput',false);
            end
            try, var = strtrim(var); end

            fid = fopen(f,'Wt');
            if fid == -1
                error('Unble to write file %s.', f);
            end
            for i=1:size(var,1)
                for j=1:size(var,2)
                    if isempty(var{i,j})
                        var{i,j} = 'n/a';
                    elseif any(var{i,j} == delim)
                        var{i,j} = ['"' var{i,j} '"'];
                    end
                    fprintf(fid,'%s',var{i,j});
                    if j < size(var,2), fprintf(fid,delim); end
                end
                fprintf(fid,'\n');
            end
            fclose(fid);
        elseif isa(var,'table')
            writetable(var,f,'FileType','text','Delimiter',delim);
        else
            error('Unknown data type.');
        end

    case 'json'
        if nargin < 3, varargin = {struct([])}; end
        spm_jsonwrite(f,var,varargin{:});

    case {'','txt','md'}
        var = cellstr(var);
        fid = fopen(f,'Wt');
        if fid == -1
            error('Unable to write file %s.', f);
        end
        for i=1:numel(var)
            fprintf(fid,'%s\n',var{i});
        end
        fclose(fid);

    case 'mat'
        if nargin < 3, varargin = {spm_get_defaults('mat.format')}; end
        if isstruct(var)
            save(f,'-struct','var',varargin{:});
        else
            error('Unable to write file %s.', f);
        end

    case 'npy'
        fid = fopen(f,'W');
        fwrite(fid,[147 'NUMPY'],'uint8');
        fwrite(fid,[2 0],'uint8');
        dt  = containers.Map(...
            {'logical','uint8','uint16','uint32','uint64','int8','int16','int32','int64','single','double'},...
            {'b1','u1','u2','u4','u8','i1','i2','i4','i8','f4','f8'});
        hdr = ['{''descr'': ''<' dt(class(var)) ''', ' ...
            '''fortran_order'': True, ' ...
            '''shape'': (' sprintf('%d, ',size(var)) '), }' sprintf('\n')];
        len = 6+2+4+numel(hdr);
        hdr = [hdr blanks(ceil(len/8)*8 - len)];
        fwrite(fid,numel(hdr),'uint32');
        fwrite(fid,hdr,'uint8');
        fwrite(fid,var,class(var));
        fclose(fid);

    otherwise
        error('Unknown file format.');

end


function h = plotElipse(center,axesLength,hParent)

% This function plots 2D-ellipses in given axes

try
    haf = hParent;
    isax = isequal(get(haf,'type'),'axes');
    if ~isax
        hf = figure('color',ones(1,3));
        haf = axes('parent',hf,'nextplot','add');
        box(haf,'on')
    end
catch
    hf = figure('color',ones(1,3));
    haf = axes('parent',hf,'nextplot','add');
    box(haf,'on')
end

h = rectangle(...
    'Position',[center(:)'-0.5*axesLength(:)',axesLength(:)'],...
    'Curvature',[1,1],...
    'facecolor',0.8*ones(1,3));


% -*- INTERNAL UNDOCUMENTED FUNCTION -*-
function [geometry, msh, space_v, vel, space_p, press] = ...
                          solve_stokes_3d (problem_data, method_data)

warning ('geopdes:obsolete', 'Function SOLVE_STOKES_3D is obsolete. Using SOLVE_STOKES instead')

[geometry, msh, space_v, vel, space_p, press] = solve_stokes (problem_data, method_data);


%% Documentation
%
%%
% Use the left sidebar to navigate through the different topics. Note that
% all documentation pages are essentially MTEX scripts. You have a copy of
% them in your MTEX download, with a file name equal to the last part of
% the URL with .html swapped for .m (so this page is |Documentation.m|).
% This means you can open them in Matlab by typing
%
%   edit fileName
%
% This allows you to execute the sections by step by step and investiage
% the effect of each single MTEX command. It also should motivate you to
% play around with different parameters, different input files or further
% analysis steps. Eventually, these documentation scripts may serve as a
% good starting point for your own analysis scripts.
%
%% Contributing to the Documentation
%
% Documenting a project like MTEX is a challenging and ongoing task.
% Therefore we are extremely happy about any spelling fixes, examples,
% theoretical explainations, special use cases, etc. As a bonus everybody
% who contributed to MTEX will automatically appear at the
% <https://github.com/mtex-toolbox/mtex/graphs/contributors contributors
% page>.
%
% The easiest way to suggest changes to the MTEX documentation is online
% via Github. This is done as follows:
%
% # sign into <https://github.com GitHub>
% # open the help page you want to change, e.g., this one
% # click
% <https://github.com/mtex-toolbox/mtex/blob/develop/doc/Documentation.m
% edit page> which leads you to the file on <https://github.com GitHub>
% # click the little pencil in the top right corner which allows you to
% edit the script online
% # enter or copy and paste your changes into the site
% # click at the bottom *Propose changes*
% # click create *pull request*
%
% Alternatively, you can send us your changes simply by <mailto:ralf.hielscher@mathematik.tu-chemnitz.de email>.
%
%% The Publish Command
%
% You may get a visual preview of your altered documentation page by using the
% matlab function
% <https://de.mathworks.com/help/matlab/matlab_prog/publishing-matlab-code.html publish>
%
%   publish filename
%
% which creates an folder, named |html|, in your current directory where you can
% find the generated html page.
%


function symb = holdMarker(reset,symbList2)
%HOLDMARKER  Returns a new symbol for use in plotting or rotates through
% symb = holdMarker()
%   returns a new symbol for use in plotting
%
% holdMarker('reset')
%   will reset the rotation
%   (if there is no output, then the rotation is reset)
% holdMarker( {j} )
%   will reset the rotation to start at symbol position "j"
%
%   Use this with plot( ..., 'marker', holdMarker() )
%
% holdMarker('reset',symbList) sets the symbol list (should be cell array)
%
% holdMarker( h )
%   will apply this function to the handles in h
%   (if h=0, uses h = get(gca,'children') )
%   ex.
%       h = plot( myMatrix );
%       holdMarker();  % reset
%       holdMarker( h ); % apply to all the lines in the plot -- each
%                        % will have a unique symbol.
%
% see also:
% set(gcf,'DefaultAxesColorOrder',[1 0 0;0 1 0;0 0 1],...
%   'DefaultAxesLineStyleOrder','-|--|:')
%   (using a 0 instead of gcf will make it permanent for your matlab session)
% Stephen Becker, May 2011
%
%   See also add_few_markers.m

persistent currentLocation symbListP

if isempty( currentLocation)
    currentLocation = 1;
end

if isempty( symbListP )
    %symbList = { '+','o','*','.','x','s',...
    %'d','^','v','>','<','p','h' };

    % Exclude the "."
    symbList = { '+','o','*','x','s',...
        'd','^','v','>','<','p','h' };
else
%     symbList = symbListP;
    % May 2013
    if ~iscell( symbListP )
        symbList = cell(size(symbListP));
        for jj = 1:length( symbListP )
            symbList{jj} = symbListP(jj);
        end
    else
        symbList = symbListP;
    end
end

% April 2013
if nargin > 0 && isequal(reset,0)
    reset = get( gca, 'children' );
end

do_reset = false;
if nargin > 0
    if ischar(reset)
        do_reset = true;
    elseif iscell( reset )
        currentLocation = reset{1};
    elseif all( ishandle(reset) ) && ~( isscalar(reset) && ( reset == 1) )
        % we have handles
        handles     = reset;
        for h = handles(:)'
            symb    = get_symbol;
            set( h, 'Marker', symb );
        end
    elseif isscalar(reset)
        currentLocation = reset;
    else
        error('invalid input');
    end
end
% if nargout == 0 || do_reset
if false;
    do_reset  = true;
else
    symb = get_symbol;
end

if do_reset
    currentLocation = 1;
    if nargin >= 2
        symbListP = symbList2;
    else
        symbListP = [];
    end
    return;
end

% This subfunction has side-effects
function symb = get_symbol
    if currentLocation > length(symbList), currentLocation = 1; end
    symb    = symbList{ currentLocation };
    currentLocation = currentLocation + 1;
end

end % end of main function


function [ state ] = movePTP_ConditionalTorque_HomeJointSpace( t_Kuka , relVel,joints_indices,max_torque,min_torque)
%% This function is used for performing point to point motion
%  in joint space to the home position of the robot, for the KUKA iiwa 7 R 800.
% this motion is interruptible when one or more of the joints-torques exceed the predefined limits

%% Syntax:
% [ state ] = movePTP_ConditionalTorque_HomeJointSpace( t_Kuka , relVel,joints_indices,max_torque,min_torque)

%% About:
% This function is used to move the robot to home position, the motion is
% performed in joint space.

%% Arreguments:
% t_Kuka: is the TCP/IP connection
% relVel: is a double, from zero to one, specifies the over-ride relative
% velocity.
% joints_indices: is a vector of the indices of the joints where the
% torques limits are to be imposed, the joints are indexed starting from one.
% max_torque: is a vector of the maximum torque limits for the joints
% specified in the (joints_indices) vector.
% min_torque: is a vecotr of the minimum torque limits for the joints
% specified in the (joints_indices) vector.

%% Return value:
% state: a number equals to one if the motion is completed sccessfully or a
% zero if the motion was interrupted due to external contact with the
% robot.
% if there is an error, the return value is minus one

% Copy right, Mohammad SAFEEA, 9th of April 2018

if((size(relVel,1)==1)&&(size(relVel,2)==1))
else
    disp('Error, relative velocity is a double and shall not be an array');
    state=-1;
    return;
end
% Check if the inputs "joints_indices,max_torque,min_torque" are vectors
if(isVec(joints_indices)==0)
    disp('Error, joints_indices shall be a vector');
    state=-1;
    return;
end
if(isVec(max_torque)==0)
    disp('Error, max_torque shall be a vector');
    state=-1;
    return;
end
if(isVec(min_torque)==0)
    disp('Error, min_torque shall be a vector');
    state=-1;
    return;
end
joints_indices=colVec(joints_indices);
max_torque=colVec(max_torque);
min_torque=colVec(min_torque);

% Check if size of vectrs are equal
j_num=size(joints_indices,1);
n=size(min_torque,1);
if(j_num==n)
else
    disp('Error, sizes of vectors "joints_indices" and "min_torque" shall be equal');
    state=-1;
    return;
end
n=size(max_torque,1);
if(j_num==n)
else
    disp('Error, sizes of vectors "joints_indices" and "max_torque" shall be equal');
    state=-1;
    return;
end

theCommand=['jRelVel_',num2str(relVel),'_']; % set over ride.
fprintf(t_Kuka, theCommand);
message=fgets(t_Kuka);

jPos=[];
for i=1:7
    jPos{i}=0;
end

sendJointsPositions( t_Kuka ,jPos); % send destination joint positions.

theCommand='doPTP!inJS';
for i=1:j_num
    datemp=joints_indices(i)-1;
    theCommand=[theCommand,'_',num2str(datemp)];
    datemp=min_torque(i);
    theCommand=[theCommand,'_',num2str(datemp)];
    datemp=max_torque(i);
    theCommand=[theCommand,'_',num2str(datemp)];
end

fprintf(t_Kuka, theCommand); % start the point to point motion.
message=fgets(t_Kuka);
if checkAcknowledgment(message)
else
    disp('Error, could not perform the motion due to the acknowledgment message was not received');
    disp('Check connection between PC and Robot');
    state=-1;
    return;
end

%% Check the return from the server
message='';

while true
    message=fgets(t);
    daSize=max(size(message));
    if(daSize>2)
        if(strfind(message,'done')==1)
            state=1;
            return;
        end
        if(strfind(message,'interrupted')==1)
            state=0;
            return;
        end
    end
end

end


function [Wmat, destGridAtlas, destGridLoc, destGridOrient] = tess_interp_mixed( ResultsMat, WmatSurf, srcSurfMat, destSurfMat, sMriSrc, sMriDest, isInteractive )
% TESS_INTERP_MIXED: Compute an interpolation matrix between two surfaces for a mixed source model.
%
% WARNING: All the source files must be flattened first (GridAtlas.Grid2Source is an identity matrix).

% @=============================================================================
% 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: Francois Tadel, 2016

% Parse inputs
if (nargin < 7) || isempty(isInteractive)
    isInteractive = 1;
end

% Check the source model
if isfield(ResultsMat, 'nComponents') && (ResultsMat.nComponents ~= 0)
    error('This function is aimed to process only mixed source models.');
end
% Check that the field GridAtlas is available
if ~isfield(ResultsMat, 'GridAtlas') || ~isfield(ResultsMat.GridAtlas, 'Scouts') || isempty(ResultsMat.GridAtlas.Scouts)
    error('The field GridAtlas is missing.');
end
% Get Structures atlas in the destination surface
iStructDest = find(strcmpi({destSurfMat.Atlas.Name}, 'Structures'));
if isempty(iStructDest)
    error('Destination surface must include an atlas "Structures".');
end
% % Get "Source model" atlas in the destination surface
% iModelDest = find(strcmpi({destSurfMat.Atlas.Name}, 'Source model'));

% GridAtlas: Must be updated to fit the destination surface
destGridAtlas = ResultsMat.GridAtlas;
destGridAtlas.Scouts(:) = [];

% Initialize interpolation matrices
Wmat = sparse(1, size(ResultsMat.GridLoc,1));
destGridLoc    = [];
destGridOrient = [];
iVert2Grid = [];
isFirstMniWarning = 1;
hFig1 = [];

% Process each region separately
for iScoutSrc = 1:length(ResultsMat.GridAtlas.Scouts)
    sScoutSrc = ResultsMat.GridAtlas.Scouts(iScoutSrc);
    sScoutSrc.Vertices = sScoutSrc.Vertices(:)';
    % Check if the source model has been flattened
    if (sScoutSrc.Region(3) ~= 'C')
        error('Source maps must be flattened before being projected with this function.');
    end
    % Get region in destination surface
    iScoutDest = find(strcmpi(sScoutSrc.Label, {destSurfMat.Atlas(iStructDest).Scouts.Label}));
    if isempty(iScoutDest)
        disp(['PROJECT> Warning: Structure not found in destination surface: ' sScoutSrc.Label]);
        continue;
    end
%     % If there is already an atlas "Source model", make sure the constraints match
%     if ~isempty(iModelDest)
%         iScoutDestModel = find(strcmpi(sScoutSrc.Label, {destSurfMat.Atlas(iModelDest).Scouts.Label}));
%         if isempty(iModelDest) || ~isequal(destSurfMat.Atlas(iModelDest).Scouts(iScoutDestModel).Region, sScoutSrc.Region)
%             error(['The atlas "Source model" has different constraints in the destination surface for region "' sScoutSrc.Label '".']);
%         end
%     end
    % Update scout structure
    sScoutDest = sScoutSrc;
    sScoutDest.Vertices = destSurfMat.Atlas(iStructDest).Scouts(iScoutDest).Vertices(:)';
    sScoutDest.Seed     = destSurfMat.Atlas(iStructDest).Scouts(iScoutDest).Seed;

    % Process depends on region type
    switch (sScoutSrc.Region(2))
        % Volume: Compute a grid
        case 'V'
            % Source grid: Get from the source file
            srcLoc = ResultsMat.GridLoc(sScoutSrc.GridRows,:);
            % Compute a grid based on the destination region
            destLoc = dba_anatmodel(sScoutDest.Vertices, sScoutDest, destSurfMat, 'vol');
            destOri = 0 * destLoc;
            % Convert to MNI coordinates
            srcLocMni  = cs_convert(sMriSrc,  'scs', 'mni', srcLoc);
            destLocMni = cs_convert(sMriDest, 'scs', 'mni', destLoc);
            if (isempty(srcLocMni) || isempty(destLocMni))
                if isFirstMniWarning
                    strWarning = 'For accurate results, compute the MNI transformation for both subjects before running this interpolation.';
                    if isInteractive
                        java_dialog('warning', strWarning);
                    else
                        disp(['PROJECT> Warning: ' strWarning]);
                        bst_report('Warning', 'process_project_sources', [], strWarning);
                    end
                    isFirstMniWarning = 0;
                end
                srcLocMni  = srcLoc;
                destLocMni = destLoc;
            end
            % Set the indices of the regions in the Atlas
            sScoutDest.GridRows = size(destGridLoc,1) + (1:size(destLoc,1));
            % Compute interpolation
            Wmat(sScoutDest.GridRows, sScoutSrc.GridRows) = bst_shepards(destLocMni, srcLocMni, 8, 0);

            % === DISPLAY ALIGNMENT ===
            if isInteractive && ~isequal(sMriSrc, sMriDest)
                % Close previous figures
                if ~isempty(hFig1) && ishandle(hFig1)
                    close(hFig1);
                end
                % Compute convex envelopes
                facesSrc  = convhull(srcLoc);
                facesDest = convhull(destLoc);
                % Display figure
                [hFig1, iDS, iFig, hPatch] = view_surface_matrix(destLoc, facesDest, .4, [1 0 0]);
                set(hPatch, 'EdgeColor', 'r');
                [hFig1, iDS, iFig, hPatch] = view_surface_matrix(srcLoc, facesSrc, .4, [], hFig1);
                set(hPatch, 'EdgeColor', [.6 .6 .6]);
                line(destLoc(:,1), destLoc(:,2), destLoc(:,3), ...
                     'LineStyle',   'none', ...
                     'Color',       [1 1 0], ...
                     'MarkerSize',  2, ...
                     'Marker',      'o');
                line(srcLoc(:,1), srcLoc(:,2), srcLoc(:,3), ...
                     'LineStyle',   'none', ...
                     'Color',       [0 0 1], ...
                     'MarkerSize',  2, ...
                     'Marker',      'o');
                set(hFig1, 'Name', [sScoutSrc.Label ' (source grid)']);
                drawnow;
            end

        % Surface: Use the surface-surface interpolation computed previously
        case 'S'
            destLoc = destSurfMat.Vertices(sScoutDest.Vertices, :);
            destOri = destSurfMat.VertNormals(sScoutDest.Vertices, :);
            % Set the indices of the regions in the Atlas
            sScoutDest.GridRows = size(destGridLoc,1) + (1:size(destLoc,1));
            % Re-use surface inteprolation
            Wmat(sScoutDest.GridRows, sScoutSrc.GridRows) = WmatSurf(sScoutDest.Vertices, sScoutSrc.Vertices);
            % Add the match of the vertices in the cortex surface and the GridLoc matrix
            iVert2Grid = [iVert2Grid; sScoutDest.Vertices', sScoutDest.GridRows'];

        otherwise
            disp(['PROJECT> Warning: Structure ignored: ' sScoutSrc.Label]);
            continue;
    end
    % Concatenate GridLoc and GridOrient
    destGridLoc    = [destGridLoc;    destLoc];
    destGridOrient = [destGridOrient; destOri];
    % Add scout to destination atlas
    destGridAtlas.Scouts(end+1) = sScoutDest;
end

% Create sparse conversion matrices between indices
% Vert2Grid: Correspondance between the vertices of the cortex surface and the GridLoc field
destGridAtlas.Vert2Grid   = logical(sparse(iVert2Grid(:,2), iVert2Grid(:,1), ones(size(iVert2Grid,1),1)));
% Grid2Source: Correspondance between the GridLoc and ImageGridamp matrices (identity matrix because the source maps must be flatten before projecting)
destGridAtlas.Grid2Source = logical(speye(size(destGridLoc,1)));


function x = transpose( x )

%   Disciplined convex/geometric programming information for TRANSPOSE:
%      The transpose operation may be applied to CVX variables without
%      restriction.

s = x.size_;
if length( s ) > 2,
    cvx_throw( 'Transpose of an ND array is not defined.' );
elseif any( s > 1 ),
    b = x.basis_;
    if all( s > 1 ),
        b = b(:,reshape( 1 : prod( s ), s )');
    end
    x = cvx( [ s(2), s(1) ], b );
end

% 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 [figsize,figborders]=getfigdim(figh)
% [figsize,figborders]=getfigdim(figh)  GET FIGure DIMensions.
%   Function creates a figure and then measures the appropriate values to
%   obtain border widths and heights of the menu and tool bars and other
%   parameters. This can then be used to size and place figures more exactly.
%   "figh" is the handle of the figure whose dimensions are measured.
%       If "figh" is not specified or empty then a figure will be created.
%   "figsize" is a four element row vector which specifies the figure.
%       The vector is as follows:  [left bottom width height]
%       These are the same values returned by "OuterPosition" property.
%   "figborders" is a 6 element row vector which is defined as:
%       [figureborder titlebarheight menubarheight ...
%                           toolbarheight minfigwidth minfigheight]
%       The figureborder is defined for all four sides of the figure.
%       The minfigwidth, minfigheight are the minimum size of figures that
%       Matlab produces without menu and tool bars.
%
%   Example:
%       [fsize,fborder]=getfigdim;
%       fsize = [227   241   570   504]
%       fborder = [5    26    21    27   125    37]

%   Copyright 2006 Mirtech, Inc.
%   created 08/20/2006  by Mirko Hrovat on Matlab Ver. 7.2
%   Mirtech, Inc.       email: mhrovat@email.com

%Create a figure if it doesn't exist
if nargin==0 || isempty(figh),
    figh=figure;
    clrflg=1;
else
    figure(figh);
    clrflg=0;
end
menbarstate=get(figh,'MenuBar');
toolbarstate=get(figh,'ToolBar');
unitsstate=get(figh,'Units');
set(figh,'Units','pixels');
drawnow
figsize=get(figh,'OuterPosition');
figpos=get(figh,'Position');
if nargout==2,
    set(figh,'MenuBar','none');
    set(figh,'ToolBar','none');
    drawnow
    p1=get(figh,'OuterPosition');
    p =get(figh,'Position');

    set(figh,'MenuBar','figure');
    set(figh,'ToolBar','none');
    drawnow
    p2=get(figh,'OuterPosition');

    set(figh,'MenuBar','none');
    set(figh,'ToolBar','figure');
    drawnow
    p3=get(figh,'OuterPosition');

    set(figh,'MenuBar','none');
    set(figh,'ToolBar','none');
    set(figh,'OuterPosition',[figsize(1),figsize(2),10,10]);
    drawnow
    p4=get(figh,'OuterPosition');

    figborders=zeros(1,6);
    figborders(4)= p3(4)-p1(4);             % calculate height of Toolbar
    figborders(3)= p2(4)-p1(4);             % calculate height of Menubar
    figborders(1)= (p1(3)-p(3))/2;          % calculate width of figure border
    figborders(2)= p1(4)-p(4)-2*figborders(1); % calculate height of title bar
    figborders(5:6)=p4(3:4);                % get minimium figure sizes
end %if nargout==2
% close the figure if created, otherwise return to original state
if clrflg,
    close(figh);
else
    set(figh,'MenuBar',menbarstate);
    set(figh,'ToolBar',toolbarstate);
    set(figh,'Units',unitsstate);
    set(figh,'Position',figpos);
    drawnow
end
% ---------- END ----------


function cvx_tic

%CVX_TIC Resets the CVX timing functionality.
%
%   CVX collects the following timing information:
%   --- Elapsed time since CVX_TIC was last called. If CVX_TIC was never
%       called, this measures the time since CVX was first initialized.
%   --- Elapsed time spent between top-level CVX_BEGIN and CVX_END comamnds
%   --- Elapsed time spent within the top-level CVX_END itself. This
%       includes final problem extraction, presolving, and solving.
%   --- Elapsed time spent calling the numerical solver.
%   To retrieve the current totals for these numbers, type CVX_TOC.
%   CVX_TIC resets these numbers to zero.

global cvx___
cvx_global
if ~isempty( cvx___.problems ),
    error( 'CVX_TIC can only be called when no models are in construction.' );
end
cvx___.timers(1) = tic;
cvx___.timers(2:4) = 0;

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


classdef Zero < CSMaster
    % wrapper class for zero-padded reconstruction
    %
    % (c) Thomas Kuestner
    % ---------------------------------------------------------------------

    properties

    end

    methods
        function obj = Zero(measPara,espresso)
            obj = obj@CSMaster(1, 1, [], [], measPara);
            obj.espresso = espresso;
        end
    end

end


function result  = gomp_mmv(Dict, X, K, L, T, epsilon, options)
    if(isobject(Dict))
        Dict = double(Dict);
    end
    if ~isa(Dict, 'double')
        error('Dict must be a double matrix');
    end
    if nargin < 4
        L = 1;
    end
    if nargin < 5
        T = 1;
    end
    if nargin < 6
        epsilon = 1e-3;
    end
    if nargin < 7
        options = struct;
    end
    if ~isfield(options, 'sparse_output')
        options.sparse_output = 1;
    end
    if ~isfield(options, 'verbose')
        options.verbose = 0;
    end
    result = mex_gomp_mmv(Dict, X, K, L, T, epsilon, ...
        options.sparse_output,...
        options.verbose);
end


% std_precomp() - Precompute measures (ERP, spectrum, ERSP, ITC) for channels in a study.
%                 If channels are interpolated before computing the measures, the updated
%                 EEG datasets are also saved to disk. Called by pop_precomp(). Follow with
%                 pop_plotstudy(). See Example below.
% Usage:
% >> [ALLEEG,STUDY] = std_precomp(STUDY, ALLEEG, chanorcomp, 'key', 'val', ...);
%
% Required inputs:
%   STUDY        - an EEGLAB STUDY set of loaded EEG structures
%   ALLEEG       - ALLEEG vector of one or more loaded EEG dataset structures
%   chanorcomp   - ['components'|'channels'| or channel cell array] The string
%                  'components' forces the program to precompute all selected
%                  measures for components. The string 'channels' forces the
%                  program to compute all measures for all channels.
%                  A channel cell array containing channel labels will precompute
%                  the selected measures. Note that the name of the channel is
%                  not case-sensitive.
% Optional inputs:
%  'design'   - [integer] use specific study index design to compute
%  measure.
%  'erp'      - ['on'|'off'] pre-compute ERPs for each dataset.
%  'spec'     - ['on'|'off'] pre-compute spectrum for each dataset.
%               Use 'specparams' to set spectrum parameters.
%  'ersp'     - ['on'|'off'] pre-compute ERSP for each dataset.
%               Use 'erspparams' to set time/frequency parameters.
%  'itc'      - ['on'|'off'] pre-compute ITC for each dataset.
%               Use 'erspparams' to set time/frequency parameters.
%  'scalp'    - ['on'|'off'] pre-compute scalp maps for components.
%  'allcomps' - ['on'|'off'] compute ERSP/ITC for all components ('off'
%               only use pre-selected components in the pop_study interface).
%  'specparams' - [cell array] Parameters for the spectopo function are given as
%              optional arguments:
%                   'freqrange' = [min max] frequency range to calculate. Changes x-axis limits {default:
%                                1 Hz for the min and Nyquist (srate/2) for the max. If specified
%                                power distribution maps are plotted, the highest mapped frequency
%                                determines the max freq}. Note that it is better here to compute
%                                spectrum over a wide range of frequencies (it will then
%                                be possible to select another subrange for plotting).
%                   'freqfac'  = [integer] ntimes to oversample -> frequency resolution {default: 2}
%                   'nfft'     = [integer] length to zero-pad data to. Overwrites 'freqfac' above.
%                   'winsize'  = [integer] window size in data points
%                   {default: from data}
%                   'overlap'  = [integer] window overlap in data points {default: 0}
%                   'percent'  = [float 0 to 100] percent of the data to sample for computing the
%                                spectra. Values < 100 speed up the computation. {default: 100}.
%                   'mapnorm'  = [float vector] If 'data' contain the activity of an independant
%                                component, this parameter should contain its scalp map. In this case
%                                the spectrum amplitude will be scaled to component RMS scalp power.
%                                Useful for comparing component strengths {default: none}
%                   'rmdc'     = ['on'|'off'] 'on' -> remove DC {default: 'off'}
%
%              Note that it is advised to compute spectrum
%              over all frequencies since plotting function can always reduce
%              the range of plotted frequencies.
%  'erspparams' - [cell array] Optional arguments are 'cycles', 'freqrange',
%              'padratio', 'winsize', 'alpha' (see newtimef()). Note that it
%              is adivised to select the largest frequency range and time window
%              as plotting function are capable of plotting subranges of
%              these. An important optional parameter that is
%                    'savetrials' = ['on'|'off'] save single-trials ERSP.
%                                   Requires a lot of disk space (dataset
%                                   space on disk times 10) but allow for
%                                   refined single-trial statistics.
%  'recompute' - ['on'|'off'] force recomputing ERP file even if it is
%                already on disk.
%
% Outputs:
%   ALLEEG       - the input ALLEEG vector of EEG dataset structures, modified by adding preprocessing
%                  data as pointers to Matlab files that hold the pre-clustering component measures.
%   STUDY        - the input STUDY set with pre-clustering data added, for use by pop_clust()
%
% Example:
%   >> [ALLEEG STUDY] = std_precomp(STUDY, ALLEEG, { 'cz' 'oz' }, 'interpolate', 'on', 'erp', 'on', ...
%          'spec', 'on', 'ersp', 'on', 'erspparams', { 'cycles' [ 3 0.5 ], 'alpha', 0.01, 'padratio' 1 });
%
%           % This prepares, channels 'cz' and 'oz' in the STUDY datasets.
%           % If a data channel is missing in one dataset, it will be
%           % interpolated (see eeg_interp()). The ERP, spectrum, ERSP, and
%           % ITC for each dataset is then computed.
%
% Authors: Arnaud Delorme, SCCN, INC, UCSD, 2006-

% Copyright (C) Arnaud Delorme, SCCN, INC, UCSD, 2006, arno@sccn.ucsd.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function [ STUDY, ALLEEG ] = std_precomp(STUDY, ALLEEG, chanlist, varargin)

    if nargin < 2
        help std_precomp;
        return;
    end;

    if nargin == 2
        chanlist = 'channels'; % default to clustering the whole STUDY
    end
    Ncond = length(STUDY.condition);
    if Ncond == 0
        Ncond = 1;
    end

    g = finputcheck(varargin, { 'erp'         'string'  { 'on' 'off' }     'off';
                                'interp'      'string'  { 'on' 'off' }     'off';
                                'ersp'        'string'  { 'on' 'off' }     'off';
                                'recompute'   'string'  { 'on' 'off' }     'off';
                                'spec'        'string'  { 'on' 'off' }     'off';
                                'scalp'       'string'  { 'on' 'off' }     'off';
                                'allcomps'    'string'  { 'on' 'off' }     'off';
                                'itc'         'string'  { 'on' 'off' }     'off';
                                'savetrials'  'string'  { 'on' 'off' }     'off';
                                'rmicacomps'  'string'  { 'on' 'off' }     'off';
                                'design'      'integer' []                 STUDY.currentdesign;
                                'rmclust'     'integer' []                 [];
                                'rmbase'      'integer' []                 [];
                                'specparams'        'cell'    {}                 {};
                                'erpparams'         'cell'    {}                 {};
                                'erspparams'        'cell'    {}                 {}}, 'std_precomp');
    if isstr(g), error(g); end;
    if ~isempty(g.rmbase), g.erpparams = { g.erpparams{:} 'rmbase' g.rmbase }; end;

    % union of all channel structures
    % -------------------------------
    computewhat = 'channels';
    if isstr(chanlist)
        if strcmpi(chanlist, 'channels')
            chanlist = [];
        else % components
            computewhat = 'components';
            if strcmpi(g.allcomps, 'on')
                chanlist = {};
                for index = 1:length(STUDY.datasetinfo)
                    chanlist = { chanlist{:} [1:size(ALLEEG(STUDY.datasetinfo(index).index).icaweights,1)] };
                end;
            else
                chanlist = { STUDY.datasetinfo.comps };
            end;
        end;
    end;
    if isempty(chanlist)
        alllocs = eeg_mergelocs(ALLEEG.chanlocs);
        chanlist = { alllocs.labels };
    elseif ~isnumeric(chanlist{1})
        alllocs = eeg_mergelocs(ALLEEG.chanlocs);
        [tmp c1 c2] = intersect( lower({ alllocs.labels }), lower(chanlist));
        [tmp c2] = sort(c2);
        alllocs = alllocs(c1(c2));
    end;

    % test if interp and reconstruct channel list
    % -------------------------------------------
    if strcmpi(computewhat, 'channels')
        if strcmpi(g.interp, 'on')
            STUDY.changrp = [];
            STUDY = std_changroup(STUDY, ALLEEG, chanlist, 'interp');
            g.interplocs = alllocs;
        else
            STUDY.changrp = [];
            STUDY = std_changroup(STUDY, ALLEEG, chanlist);
            g.interplocs = struct([]);
        end;
    end;

    % components or channels
    % ----------------------
    if strcmpi(computewhat, 'channels')
         curstruct = STUDY.changrp;
    else curstruct = STUDY.cluster;
    end;

    % compute ERPs
    % ------------
    if strcmpi(g.erp, 'on')
        % check dataset consistency
        % -------------------------
        if length(unique([ALLEEG([STUDY.design(g.design).cell.dataset]).pnts])) > 1
            error([ 'Cannot compute ERPs because datasets' 10 'do not have the same number of data points' ])
        end;

        for index = 1:length(STUDY.design(g.design).cell)
            desset = STUDY.design(g.design).cell(index);
            addopts = { 'savetrials', g.savetrials, 'recompute', g.recompute, 'fileout', desset.filebase, 'trialindices', desset.trials };
            if strcmpi(computewhat, 'channels')
                [tmpchanlist opts] = getchansandopts(STUDY, ALLEEG, chanlist, desset.dataset, g);
                std_erp(ALLEEG(desset.dataset), 'channels', tmpchanlist, opts{:}, addopts{:}, g.erpparams{:});
            else
                if length(desset.dataset)>1 && ~isequal(chanlist{desset.dataset})
                    error(['ICA decompositions must be identical if' 10 'several datasets are concatenated to build' 10 'the design, abording' ]);
                end;
                std_erp(ALLEEG(desset.dataset), 'components', chanlist{desset.dataset(1)}, addopts{:}, g.erpparams{:});
            end;
        end;
        if isfield(curstruct, 'erpdata')
            curstruct = rmfield(curstruct, 'erpdata');
            curstruct = rmfield(curstruct, 'erptimes');
        end;
    end;

    % compute spectrum
    % ----------------
    if strcmpi(g.spec, 'on')
        % check dataset consistency
        % -------------------------
        for index = 1:length(STUDY.design(g.design).cell)
            desset = STUDY.design(g.design).cell(index);
            addopts = { 'savetrials', g.savetrials, 'recompute', g.recompute, 'fileout', desset.filebase, 'trialindices', desset.trials };
            if strcmpi(computewhat, 'channels')
                [tmpchanlist opts] = getchansandopts(STUDY, ALLEEG, chanlist, desset.dataset, g);
                std_spec(ALLEEG(desset.dataset), 'channels', tmpchanlist, opts{:}, addopts{:}, g.specparams{:});
            else
                if length(desset.dataset)>1 && ~isequal(chanlist{desset.dataset})
                    error(['ICA decompositions must be identical if' 10 'several datasets are concatenated to build' 10 'the design, abording' ]);
                end;
                std_spec(ALLEEG(desset.dataset), 'components', chanlist{desset.dataset(1)}, addopts{:}, g.specparams{:});
            end;
        end;
        if isfield(curstruct, 'specdata')
            curstruct = rmfield(curstruct, 'specdata');
            curstruct = rmfield(curstruct, 'specfreqs');
        end;
    end;

    % compute component scalp maps
    % ----------------------------
    if strcmpi(g.scalp, 'on')
        for index = 1:length(STUDY.datasetinfo)

            % find duplicate
            % --------------
            found = [];
            ind1 = STUDY.datasetinfo(index).index;
            inds = strmatch(STUDY.datasetinfo(index).subject, { STUDY.datasetinfo(1:index-1).subject });
            for index2 = inds'
                ind2 = STUDY.datasetinfo(index2).index;
                if isequal(ALLEEG(ind1).icawinv, ALLEEG(ind2).icawinv)
                    found = ind2;
                end;
            end;

            % make link if duplicate
            % ----------------------
            fprintf('Computing/checking topo file for dataset %d\n', ind1);
            if ~isempty(found)
                tmpfile1 = fullfile( ALLEEG(index).filepath, [ ALLEEG(index).filename(1:end-3) 'icatopo' ]);
                tmp.file = fullfile( ALLEEG(found).filepath, [ ALLEEG(found).filename(1:end-3) 'icatopo' ]);
                std_savedat(tmpfile1, tmp);
            else
                std_topo(ALLEEG(index), chanlist{index}, 'none', 'recompute', g.recompute);
            end;
        end;
        if isfield(curstruct, 'topo')
            curstruct = rmfield(curstruct, 'topo');
            curstruct = rmfield(curstruct, 'topox');
            curstruct = rmfield(curstruct, 'topoy');
            curstruct = rmfield(curstruct, 'topoall');
            curstruct = rmfield(curstruct, 'topopol');
        end;
    end;

    % compute ERSP and ITC
    % --------------------
    if strcmpi(g.ersp, 'on') | strcmpi(g.itc, 'on')
        % check dataset consistency
        % -------------------------
        if length(unique([ALLEEG([STUDY.design(g.design).cell.dataset]).pnts])) > 1
            error([ 'Cannot compute ERSPs/ITCs because datasets' 10 'do not have the same number of data points' ])
        end;

        if strcmpi(g.ersp, 'on') & strcmpi(g.itc, 'on'), type = 'both';
        elseif strcmpi(g.ersp, 'on')                   , type = 'ersp';
        else                                             type = 'itc';
        end;

        % check for existing files
        % ------------------------
        guimode = 'guion';
        [ tmpX tmpt tmpf g.erspparams ] = std_ersp(ALLEEG(1), 'channels', 1, 'type', type, 'recompute', 'on', 'getparams', 'on', 'savetrials', g.savetrials, g.erspparams{:});
        if strcmpi(g.recompute, 'off')
            for index = 1:length(STUDY.design(g.design).cell)
                desset = STUDY.design(g.design).cell(index);
                if strcmpi(computewhat, 'channels')
                     filename = [ desset.filebase '.datersp'];
                else filename = [ desset.filebase '.icaersp'];
                end;
                [guimode, g.erspparams] = std_filecheck(filename, g.erspparams, guimode, { 'plotitc' 'plotersp' 'plotphase' });
                if strcmpi(guimode, 'cancel'), return; end;
            end;
            if strcmpi(guimode, 'usedisk') | strcmpi(guimode, 'same'), g.recompute = 'off';
            else                                                       g.recompute = 'on';
            end;
        end;

        % check for existing files
        % ------------------------
        if isempty(g.erspparams),
            tmpparams = {};
        elseif iscell(g.erspparams),
            tmpparams = g.erspparams;
        else
            tmpparams      = fieldnames(g.erspparams); tmpparams = tmpparams';
            tmpparams(2,:) = struct2cell(g.erspparams);
        end;
        tmpparams = { tmpparams{:} 'recompute' g.recompute };
        for index = 1:length(STUDY.design(g.design).cell)
            desset = STUDY.design(g.design).cell(index);
            if strcmpi(computewhat, 'channels')
                [tmpchanlist opts] = getchansandopts(STUDY, ALLEEG, chanlist, desset.dataset, g);
                std_ersp(ALLEEG(desset.dataset), 'channels', tmpchanlist, 'type', type, 'fileout', desset.filebase, 'trialindices', desset.trials, opts{:}, tmpparams{:});
            else
                if length(desset.dataset)>1 && ~isequal(chanlist{desset.dataset})
                    error(['ICA decompositions must be identical if' 10 'several datasets are concatenated to build' 10 'the design, abording' ]);
                end;
                std_ersp(ALLEEG(desset.dataset), 'components', chanlist{desset.dataset(1)}, 'type', type, 'fileout', desset.filebase, 'trialindices', desset.trials, tmpparams{:});
            end;
        end;
        if isfield(curstruct, 'erspdata')
            curstruct = rmfield(curstruct, 'erspdata');
            curstruct = rmfield(curstruct, 'ersptimes');
            curstruct = rmfield(curstruct, 'erspfreqs');
        end;
        if isfield(curstruct, 'itcdata')
            curstruct = rmfield(curstruct, 'itcdata');
            curstruct = rmfield(curstruct, 'itctimes');
            curstruct = rmfield(curstruct, 'itcfreqs');
        end;
    end;

    % components or channels
    % ----------------------
    if strcmpi(computewhat, 'channels')
         STUDY.changrp = curstruct;
    else STUDY.cluster = curstruct;
    end;

    return;

    % find components in cluster for specific dataset
    % -----------------------------------------------
    function rmcomps = getclustcomps(STUDY, rmclust, settmpind);

        rmcomps   = cell(1,length(settmpind));
        for idat = 1:length(settmpind) % scan dataset for which to find component clusters
            currentdat = settmpind(idat);
            for rmi = 1:length(rmclust) % scan clusters
                compinds = STUDY.cluster(rmclust(rmi)).allinds;

                for ind = 1:length(STUDY.cluster(rmclust(rmi)).setinds(:)) % scan datasets of cluster
                    setinds  = [STUDY.design(STUDY.currentdesign).cell(STUDY.cluster(rmclust(rmi)).setinds{ind}).dataset ];
                    indmatch = find(setinds == currentdat);
                    if ~isempty(indmatch)
                        rmcomps{idat} = union( rmcomps{idat}, compinds{ind}(indmatch));
                    end;
                end;
            end;
        end;

    % make option array and channel list (which depend on interp) for any type of measure
    % ----------------------------------------------------------------------
    function [tmpchanlist, opts] = getchansandopts(STUDY, ALLEEG, chanlist, idat, g);

        opts = { };
        if ~isempty(g.rmclust)
            opts = { opts{:} 'rmcomps' getclustcomps(STUDY, g.rmclust, idat) };
        elseif strcmpi(g.rmicacomps, 'on')
            for ind = 1:length(idat)
                rmcomps{ind} = find(ALLEEG(idat(1)).reject.gcompreject);
            end;
            opts = { opts{:} 'rmcomps' rmcomps };
        end;
        if strcmpi(g.interp, 'on')
            tmpchanlist = chanlist;
            allocs = eeg_mergelocs(ALLEEG.chanlocs);
            [tmp ind1 ind2] = intersect({allocs.labels}, chanlist);
            opts = { opts{:} 'interp' allocs(ind1) };
        else
            newchanlist = [];
            tmpchanlocs = ALLEEG(idat(1)).chanlocs;
            chanlocs = { tmpchanlocs.labels };
            for i=1:length(chanlist)
                newchanlist = [ newchanlist strmatch(chanlist(i), chanlocs, 'exact') ];
            end;
            tmpchanlocs =  ALLEEG(idat(1)).chanlocs;
            tmpchanlist = { tmpchanlocs(newchanlist).labels };
        end;


function [lfp,indices] = GetLFP(channels,varargin)

%GetLFP - Get local field potentials.
%
%  Load local field potentials from disk (unlike spikes or positions, LFP data
%  is usually too large to keep in memory).
%
%  USAGE
%
%    [lfp,indices] = GetLFP(channels,<options>)
%
%    channels       list of channels to load (use keyword 'all' for all)
%    <options>      optional list of property-value pairs (see table below)
%
%    =========================================================================
%     Properties    Values
%    -------------------------------------------------------------------------
%     'restrict'    list of time intervals to read from the LFP file
%     'intervals'   same as 'restrict' (for backwards compatibility)
%     'select'      select channel by ID ('id', counted from 0 a la NeuroScope)
%                   or by number ('number', counted from 1 a la Matlab)
%                   (default = 'id')
%    =========================================================================
%
%  OUTPUT
%
%    lfp            list of (time,voltage1,...,voltageN) tuples
%    indices        for each tuple, the index of the interval it falls in
%
%  EXAMPLES
%
%    % channel ID 5 (= # 6), from 0 to 120 seconds
%    lfp = GetLFP(5,'restrict',[0 120]);
%    % same, plus from 240.2 to 265.23 seconds
%    lfp = GetLFP(5,'restrict',[0 120;240.2 265.23]);
%    % multiple channels
%    lfp = GetLFP([1 2 3 4 10 17],'restrict',[0 120]);
%    % channel # 3 (= ID 2), from 0 to 120 seconds
%    lfp = GetLFP(3,'restrict',[0 120],'select','number');

% Copyright (C) 2004-2011 by Michaël Zugaro
%
% 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.

error('This function is now deprecated from /buzcode, try using bz_GetLFP.m')

global DATA;
if isempty(DATA),
	error('No session defined (did you forget to call SetCurrentSession? Type ''help Data'' for details).');
end

% Default values
intervals = [0 Inf];
select = 'id';

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

% Parse parameter list
for i = 1:2:length(varargin),
  if ~ischar(varargin{i}),
    error(['Parameter ' num2str(i+1) ' is not a property (type ''help GetLFP'' for details).']);
  end
  switch(lower(varargin{i})),
    case {'intervals','restrict'},
      intervals = varargin{i+1};
      if ~isdmatrix(intervals) || size(intervals,2) ~= 2,
        error('Incorrect value for property ''intervals'' (type ''help GetLFP'' for details).');
      end
    case 'select',
      select = lower(varargin{i+1});
      if ~isstring_FMAT(select,'id','number'),
        error('Incorrect value for property ''select'' (type ''help GetLFP'' for details).');
      end
    otherwise,
      error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help GetLFP'' for details).']);
  end
end

filename = [DATA.session.path '/' DATA.session.basename '.lfp'];
if ~exist(filename,'file'),
    filename = [DATA.session.path '/' DATA.session.basename '.lfp'];
    if ~exist(filename,'file'),
        error(['File ''' filename ''' not found.']);
    end
end
nChannels = DATA.nChannels;
if isa(channels,'char') && strcmp(lower(channels),'all'),
	channels = (1:nChannels)-1;
end

if strcmp(select,'id'),
	channels = channels + 1;
end

nIntervals = size(intervals,1);
lfp = [];
indices = [];
for i = 1:nIntervals,
	duration = (intervals(i,2)-intervals(i,1));
	start = intervals(i,1);
	% Load data
	data = LoadBinary(filename,'duration',duration,'frequency',DATA.rates.lfp,'nchannels',nChannels,'start',start,'channels',channels);
    if isinteger(data)
        error('GetLFP does not work with integer data - use bz_GetLFP instead');
    end
	t = start:(1/DATA.rates.lfp):(start+(length(data)-1)/DATA.rates.lfp);t=t';
	lfp = [lfp ; t data];
	indices = [indices ; i*ones(size(t))];
end


function [source] = fixsource(source)

% FIXSOURCE converts old style source structures into new style source structures
%
% Use as
%   output = fixsource(input)
% where input is a structure representing source data
%
% Typically, old style source structures contain source.avg.XXX or source.trial.XXX.
% Furthermore. old style source structrures do not contain a dimord field.
%
% The new style source structure contains:
%   source.pos       Nx3 list with source positions
%   source.dim       optional, if the list of positions describes a 3D volume
%   source.XXX       the old style subfields in avg/trial
%   source.XXXdimord string how to interpret the respective XXX field:
%
% For example
%   source.pow             = zeros(Npos,Ntime)
%   source.powdimord       = 'pos_time'
%
%   source.mom             = cell(1,Npos)
%   source.mom{1}          = zeros(Nori,Nrpttap)
%   source.momdimord       = '{pos}_ori_rpttap'
%
%   source.leadfield       = cell(1,Npos)
%   source.leadfield{1}    = zeros(Nchan,Nori)
%   source.leadfielddimord = '{pos}_chan_ori'
%
% See also FT_CHECKDATA, FIXVOLUME

npos = size(source.pos, 1);

if ~isfield(source, 'inside')
  source.inside = 1:npos;
  source.outside = [];
end

% old data structures may use latency/frequency instead of time/freq
if isfield(data, 'frequency'),
  data.freq = data.frequency;
  data      = rmfield(data, 'frequency');
end
if isfield(data, 'latency'),
  data.time = data.latency;
  data      = rmfield(data, 'latency');
end

% copy the fields from the average into the main structure
if isfield(source, 'avg')
  avg    = source.avg;
  source = rmfield(source,  'avg');

  fn = fieldnames(avg);
  for i=1:length(fn)
    source.(fn{i}) = avg.(fn{i});
  end
end

% convering the trials has precedence over the average
if isfield(source, 'trial')
  trial  = source.trial;
  source = rmfield(source,  'trial');
  nrpt   = length(trial);
  for i=1:nrpt
    % FIXME
    keyboard
  end
end

hastime = isfield(source, 'time');
hasfreq = isfield(source, 'freq');

if hastime
  ntime = length(source.time);
else
  ntime = 1;
end

if hasfreq
  nfreq = length(source.freq);
else
  nfreq = 1;
end

% FIXME the code bellow should be repatterned
% first get the dimord string
% then determine the data dimensions
% then determine the dimensions according to the dimord
% if consistent, continue
% if inconsistent but can be reshaped, reshape and give warning
% if inconsistent and cannot can be reshaped, give error

% check the dimord and dimensions for each of the fields
fn = fieldnames(source);
for i=1:length(fn)
  element = source.(fn{i});

  if ischar(element) || isstruct(element)
    % the dimord only applies to cell-arrays or numeric arrays
    continue
  end

  if any(strcmp(fn{i}, {'inside', 'outside'}))
    % these don't need a dimord
    continue
  end

  % determine the dimensions of this data element
  if iscell(element)
    dim = numel(element);
    dim = [dim size(element{source.inside(1)})];
  else
    dim = size(element);
  end

  if isfield(source, [fn{i} 'dimord'])
    % check whether the specific dimord applies
    dimord = source.([fn{i} 'dimord']);

    dimtok = tokenize(dimord, '_');
    descr  = [];
    for j=1:length(dimtok)
      if strcmp(dimtok{j}, 'pos')
        descr = [descr size(source.pos,1)];
      elseif strcmp(dimtok{j}, '{pos}')
        descr = [descr size(source.pos,1)];
      else
        descr = [descr numel(source.(dimtok{j}))];
      end
    end

    if prod(dim)~=prod(descr)
      ft_error('the dimensions of the source data are not consistent with the dimord (%s)', fn{i})
    end

    if iscell(element)
      element = reshape(element, [descr(1) 1]);
      for j=1:numel(element)
        element{j} = reshape(element{j}, [descr(2:end) 1]);
      end
    else
      element = reshape(element, [descr 1]);
    end

    % put the reshaped data element back into the structure
    source.(fn{i}) = element;

  elseif isfield(source, 'dimord')
    % check whether the general dimord applies to this element
    dimord = source.dimord;

    dimtok = tokenize(dimord, '_');
    descr  = [];
    for j=1:length(dimtok)
      if strcmp(dimtok{j}, 'pos')
        descr = [descr size(source.pos,1)];
      elseif strcmp(dimtok{j}, '{pos}')
        descr = [descr size(source.pos,1)];
      else
        descr = [descr numel(source.(dimtok{j}))];
      end
    end

    if prod(dim)==prod(descr)
      % the dimensions of the source data are consistent with the dimord
      if iscell(element)
        element = reshape(element, [descr(1) 1]);
        for j=1:numel(element)
          element{j} = reshape(element{j}, [descr(2:end) 1]);
        end
      else
        element = reshape(element, [descr 1]);
      end

      % create a dimord for this data element
      source.([fn{i} 'dimord']) = dimord;
      % put the reshaped data element back into the structure
      source.(fn{i}) = element;
    end

  else
    % try to create a dimord on the fly
    if     ~hasfreq && ~hastime && prod(dim)==npos
      if iscell(element)
        dimord = '{pos}';
      else
        dimord = 'pos';
      end
      descr  = npos;
    elseif  hasfreq && ~hastime && prod(dim)==prod([npos nfreq])
      if iscell(element)
        dimord = '{pos}_freq';
      else
        dimord = 'pos_freq';
      end
      descr  = [npos nfreq];
    elseif  hasfreq &&  hastime && prod(dim)==prod([npos nfreq ntime])
      if iscell(element)
        dimord = '{pos}_freq_time';
      else
        dimord = 'pos_freq_time';
      end
      descr  = [npos nfreq ntime];
    elseif ~hasfreq &&  hastime && prod(dim)==prod([npos ntime])
      if iscell(element)
        dimord = '{pos}_time';
      else
        dimord = 'pos_time';
      end
      descr  = [npos ntime];
    elseif prod(dim)==npos
      % although the source data has time and frequency, this element might be pos only
      if iscell(element)
        dimord = '{pos}';
      else
        dimord = 'pos';
      end
      descr  = npos;
    else
      dimord = '';
      descr  = [];
    end

    if ~isempty(dimord)
      % the dimensions of the source data are consistent with the dimord
      if iscell(element)
        element = reshape(element, [descr(1) 1]);
        for j=1:numel(element)
          element{j} = reshape(element{j}, [descr(2:end) 1]);
        end
      else
        element = reshape(element, [descr 1]);
      end

      % create a dimord for this data element
      source.([fn{i} 'dimord']) = dimord;
      % put the reshaped data element back into the structure
      source.(fn{i}) = element;
    end

  end % if isfield dimord
end % for each of the fields

if isfield(source, 'dimord')
  % remove the general dimord field, there should be one for each data element
  source = rmfield(source, 'dimord');
end

%if isvolume
%  % ensure consistent dimensions of the volumetric data
%  % reshape each of the volumes that is found into a 3D array
%  param = parameterselection('all', data);
%  dim   = data.dim;
%  for i=1:length(param)
%    tmp  = getsubfield(data, param{i});
%    tmp  = reshape(tmp, dim);
%    data = setsubfield(data, param{i}, tmp);
%  end
%end

% if issource || isvolume,
%   % the following section is to make a dimord-consistent representation of
%   % volume and source data, taking trials, time and frequency into account
%   if isequal(hasdimord, 'yes') && (~isfield(data, 'dimord') || ~strcmp(data.dimord, sourcedimord))
%
%     % determine the size of the data
%     if isfield(data, 'dimord'),
%       dimtok = tokenize(data.dimord, '_');
%       if ~isempty(strmatch('time', dimtok)), Ntime = length(data.time); else Ntime = 1; end
%       if ~isempty(strmatch('freq', dimtok)), Nfreq = length(data.freq); else Nfreq = 1; end
%     else
%       Nfreq = 1;
%       Ntime = 1;
%     end
%
%     % convert old style source representation into new style
%     if isfield(data, 'avg') && isfield(data.avg, 'mom') && isfield(data, 'freq') && strcmp(sourcedimord, 'rpt_pos'),
%       % frequency domain source representation convert to single trial power
%       Npos   = size(data.pos,1);
%       Nrpt   = length(data.cumtapcnt);
%       tmpmom = zeros(Npos, size(data.avg.mom{data.inside(1)},2));
%       tmpmom(data.inside,:) = cat(1,data.avg.mom{data.inside});
%       tmppow = zeros(Npos, Nrpt);
%       tapcnt = [0;cumsum(data.cumtapcnt)];
%       for k = 1:Nrpt
%         Ntap = tapcnt(k+1)-tapcnt(k);
%         tmppow(data.inside,k) = sum(abs(tmpmom(data.inside,(tapcnt(k)+1):tapcnt(k+1))).^2,2)./Ntap;
%       end
%       data.pow = tmppow';
%       data     = rmfield(data, 'avg');
%       if strcmp(inside, 'logical'),
%         data     = fixinside(data, 'logical');
%         data.inside = repmat(data.inside(:)',[Nrpt 1]);
%       end
%     elseif isfield(data, 'avg') && isfield(data.avg, 'mom') && isfield(data, 'freq') && strcmp(sourcedimord, 'rpttap_pos'),
%       % frequency domain source representation convert to single taper fourier coefficients
%       Npos   = size(data.pos,1);
%       Nrpt   = sum(data.cumtapcnt);
%       data.fourierspctrm = complex(zeros(Nrpt, Npos), zeros(Nrpt, Npos));
%       data.fourierspctrm(:, data.inside) = transpose(cat(1, data.avg.mom{data.inside}));
%       data   = rmfield(data, 'avg');
%     elseif isfield(data, 'avg') && isfield(data.avg, 'mom') && isfield(data, 'time') && strcmp(sourcedimord, 'pos_time'),
%       Npos   = size(data.pos,1);
%       Nrpt   = 1;
%       tmpmom = zeros(Npos, size(data.avg.mom{data.inside(1)},2));
%       tmpmom(data.inside,:) = cat(1,data.avg.mom{data.inside});
%       data.mom = tmpmom;
%       if isfield(data.avg, 'noise'),
%         tmpnoise = data.avg.noise(:);
%         data.noise = tmpnoise(:,ones(1,size(tmpmom,2)));
%       end
%       data = rmfield(data, 'avg');
%       Ntime = length(data.time);
%     elseif isfield(data, 'trial') && isfield(data.trial(1), 'mom') && isfield(data, 'time') && strcmp(sourcedimord, 'rpt_pos_time'),
%       Npos   = size(data.pos,1);
%       Nrpt   = length(data.trial);
%       Ntime  = length(data.time);
%       tmpmom = zeros(Nrpt, Npos, Ntime);
%       for k = 1:Nrpt
%         tmpmom(k,data.inside,:) = cat(1,data.trial(k).mom{data.inside});
%       end
%       data     = rmfield(data, 'trial');
%       data.mom = tmpmom;
%     elseif isfield(data, 'trial') && isstruct(data.trial)
%       Nrpt = length(data.trial);
%     else
%       Nrpt = 1;
%     end
%
%     % start with an initial specification of the dimord and dim
%     if (~isfield(data, 'dim') || ~isfield(data, 'dimord'))
%       if issource
%         % at least it should have a Nx3 pos
%         data.dim    = size(data.pos, 1);
%         data.dimord = 'pos';
%       elseif isvolume
%         % at least it should have a 1x3 dim
%         data.dim    = data.dim;
%         data.dimord = 'dim1_dim2_dim3';
%       end
%     end
%
%     % add the additional dimensions
%     if Nfreq>1
%       data.dimord = [data.dimord '_freq'];
%       data.dim    = [data.dim     Nfreq];
%     end
%     if Ntime>1
%       data.dimord = [data.dimord '_time'];
%       data.dim    = [data.dim     Ntime];
%     end
%     if Nrpt>1 && strcmp(sourcedimord, 'rpt_pos'),
%       data.dimord = ['rpt_' data.dimord];
%       data.dim    = [Nrpt   data.dim ];
%     elseif Nrpt>1 && strcmp(sourcedimord, 'rpttap_pos'),
%       data.dimord = ['rpttap_' data.dimord];
%       data.dim    = [Nrpt   data.dim ];
%     end
%
%     % the nested trial structure is not compatible with dimord
%     if isfield(data, 'trial') && isstruct(data.trial)
%       param = fieldnames(data.trial);
%       for i=1:length(param)
%         if isa(data.trial(1).(param{i}), 'cell')
%           concat = cell(data.dim(1), prod(data.dim(2:end)));
%         else
%           concat = zeros(data.dim(1), prod(data.dim(2:end)));
%         end
%         for j=1:length(data.trial)
%           tmp = data.trial(j).(param{i});
%           concat(j,:) = tmp(:);
%         end % for each trial
%         data.trial = rmfield(data.trial, param{i});
%         data.(param{i}) = reshape(concat, data.dim);
%       end % for each param
%       data = rmfield(data, 'trial');
%     end
%   end
%
%   % ensure consistent dimensions of the source reconstructed data
%   % reshape each of the source reconstructed parameters
%   if issource && isfield(data, 'dim') && prod(data.dim)==size(data.pos,1)
%     % volumetric represented source structure
%     dim = [prod(data.dim) 1];
%   elseif issource && any(~cellfun('isempty',strfind(fieldnames(data), 'dimord')))
%     % sparsely represented source structure new style
%     dim = [size(data.pos,1) 1];
%   elseif isfield(data, 'dim')
%     dim = [data.dim 1];
%   elseif isfield(data, 'dimord')
%     %HACK
%     dimtok = tokenize(data.dimord, '_');
%     for i=1:length(dimtok)
%       if strcmp(dimtok(i), 'pos')
%         dim(1,i) = size(getsubfield(data,dimtok{i}),1);
%       elseif strcmp(dimtok(i), 'rpt')
%         dim(1,i) = nan;
%       else
%         dim(1,i) = length(getsubfield(data,dimtok{i}));
%       end
%     end
%     i = find(isnan(dim));
%     if ~isempty(i)
%       n = fieldnames(data);
%       for ii=1:length(n)
%         numels(1,ii) = numel(getfield(data,n{ii}));
%       end
%       nrpt = numels./prod(dim(setdiff(1:length(dim),i)));
%       nrpt = nrpt(nrpt==round(nrpt));
%       dim(i) = max(nrpt);
%     end
%     if numel(dim)==1, dim(1,2) = 1; end
%   end
%
% end


%% trisurfsmooth
% Below is a demonstration of the features of the |trisurfsmooth| function

%%
clear; close all; clc;

%% Syntax
% |[Vs]=trisurfsmooth(F,V,n,IND_V,par,opt);|

%% Description
% UNDOCUMENTED
%% Examples
%
%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% 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/>.