% std_ersp() - Compute ERSP and/or ITC transforms for ICA components
%              or data channels of a dataset. Save results into Matlab
%              float files. When these output files already exist, loads
%              the ERSP/ITC information from them unless the requested
%              flag specifies differently. If so, a query window
%              pops up.
%
% Function description:
%              The function returns the masked (as per the requested alpha)
%              mean ERSP or ITC for the selected dataset ICA components or
%              data channels in the requested frequency range and time window
%              (the two are dependent). Frequencies are equally log spaced.
%              Options specify component numbers, desired frequency range,
%              time window length, frequency resolution, significance level,
%              and wavelet cycles. See >> help newtimef and >> timef details
%
%              Two Matlab files are saved (for ERSP and ITC). These contain
%              the ERSP|ITC image, plus the transform parameters
%              used to compute them. Saves the computed dataset mean images
%              in dataset-name files with extensions '.icaersp' and '.icaitc'
%              for ICA components or '.datersp', '.datitc' for data channels.
%              If the ERSPs/ITCs were previously saved into these files,
%              and the same set of ERSP/ITC parameters are used, the values
%              are not recomputed, but the information is read from these
%              files. Vectors of frequencies and latencies for the ERSP/ITC
%              images are returned separately. Returned 'EEG.etc' fields
%              are modified with pointers to the output float files and some
%              information about them.
% Usage:
%              >> [X times logfreqs ] = std_ersp(EEG, 'key', 'val', ...);
% Inputs:
%   EEG          - an EEG dataset structure.
%
% Optional inputs:
%   'components' - [numeric vector] components in the EEG structure for which
%                  ERSP and ITC data will be computed {default|[]: all
%                  components if no 'channels' are specified (see below)}
%   'channels'   - [numeric vector or cell array of channel labels] channels
%                  in the EEG structure for which ERSP and ITC will be computed
%                  {default|[]: no channels}
%   'freqs'      - [minHz maxHz] the ERSP/ITC frequency range to compute
%                  and return. {default: 3 to EEG sampling rate divided by 3}
%   'timelimits' - [minms maxms] time window (in ms) to compute.
%                  {default: whole input epoch}.
%   'timewindow' - [minms maxms] time window (in ms) to plot.
%                  {default: all output latencies}
%   'cycles'     - [wavecycles (factor)]. If 0 -> DFT (constant window length
%                  across frequencies).
%                  If >0 -> the number of cycles in each analysis wavelet.
%                  If [wavecycles factor], wavelet cycles increase with
%                  frequency, beginning at wavecyles. (0 < factor < 1)
%                  factor = 0 -> fixed epoch length (DFT, as in FFT).
%                  factor = 1 -> no increase (standard wavelets)
%                  {default: [0]}
%   'padratio'   - (power of 2). Multiply the number of output frequencies
%                  by dividing their frequency spacing through 0-padding.
%                  Output frequency spacing is (low_freq/padratio).
%   'alpha'      - If in (0, 1), compute two-tailed permutation-based
%                  probability thresholds and use these to mask the output
%                  ERSP/ITC images {default: NaN}
%   'type'       - ['ersp'|'itc'] though both ERSP and ITC images are computed
%                  and saved to disk, only this transform is returned to the
%                  command line (see first output, X, below) {default: 'ersp'}
%   'savetrials' - ['on'|'off'] Save single-trial time-freq. decompositions in
%                  a file with extension '.dattimef' (channels) or '.icatimef'
%                  (components). {default: 'off'}
%   'powbase'    - [ncomps,nfreqs] optional input matrix giving baseline power
%                  spectra (not dB power, see >> help timef).
%                  For use in repeated calls to timef() using the same baseine
%                  {default|[] -> none; data windows centered before 0 latency}
%   'recompute'  - ['on'|'off'] 'on' forces recomputation of both ERSP and ITC.
%                  {default: 'off'}
%
% Other optional inputs:
%   This function will take any of the newtimef() optional inputs (for instance
%   to compute log-space frequencies)...
%
% Outputs:
%   X         - the masked log ERSP/ITC of the requested ICA components/channels
%               in the selected frequency and time range.
%   times     - vector of time points for which the ERSPs/ITCs were computed.
%   logfreqs  - vector of (equally log spaced) frequencies (in Hz) at which the
%               log ERSP/ITC was evaluated.
%
% Files written or modified:
%              [dataset_filename].icaersp   <-- saved component ERSPs
%              [dataset_filename].icaitc    <-- saved component ITCs
%  OR for channels
%              [dataset_filename].datersp   <-- saved channel ERSPs
%              [dataset_filename].datitc    <-- saved channel ITCs
% Example:
%            % Create mean ERSP and ITC images on disk for all comps from
%            % dataset EEG use three-cycle wavelets (at 3 Hz) to more than
%            % three-cycle wavelets at 50 Hz. Use probability masking at
%            % p < 0.01 with padratio 4. See >> timef details.
%            % Return the (equally log-freq spaced, probability-masked) ERSP.
%            >> [Xersp, times, logfreqs] = std_ersp(EEG, ...
%                       'type', 'ersp', 'freqs', [3 50], ...
%                                 'cycles', [3 0.5], 'alpha', 0.01);
%
% See also: timef(), std_itc(), std_erp(), std_spec(), std_topo(), std_preclust()
%
% Authors: Arnaud Delorme, Hilit Serby, SCCN, INC, UCSD, January, 2005-

% Copyright (C) Hilit Serby, SCCN, INC, UCSD, October 11, 2004, hilit@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 [X, times, freqs, parameters] = std_ersp(EEG, varargin)

if nargin < 1
    help std_ersp;
    return;
end;

options = {};
if length(varargin) > 1
    if ~isstr(varargin{1})
        if length(varargin) > 0, options = { options{:} 'components' varargin{1} }; end;
        if length(varargin) > 1, options = { options{:} 'freqs'      varargin{2} }; end;
        if length(varargin) > 2, options = { options{:} 'timewindow' varargin{3} }; end;
        if length(varargin) > 3, options = { options{:} 'cycles'     varargin{4} }; end;
        if length(varargin) > 4, options = { options{:} 'padratio'   varargin{5} }; end;
        if length(varargin) > 5, options = { options{:} 'alpha'      varargin{6} }; end;
        if length(varargin) > 6, options = { options{:} 'type'       varargin{7} }; end;
        if length(varargin) > 7, options = { options{:} 'powbase'    varargin{8} }; end;
    else
        options = varargin;
    end;
end;

[g timefargs] = finputcheck(options, { ...
                        'components'    'integer'     []      [];
                        'channels'      { 'cell' 'integer' }  { [] [] }     {};
                        'outputfile'    'string'      []      '';
                        'powbase'       'real'        []      [];
                        'trialindices' { 'integer' 'cell' } []         [];
                        'savetrials'    'string'      { 'on' 'off' }      'off';
                        'plot'          'string'      { 'on' 'off' }      'off';
                        'recompute'     'string'      { 'on' 'off' }      'off';
                        'getparams'     'string'      { 'on' 'off' }      'off';
                        'timewindow'    'real'        []      [];
                        'fileout'       'string'  []         '';
                        'timelimits'    'real'        []      [EEG(1).xmin EEG(1).xmax]*1000;
                        'cycles'        'real'        []      [3 .5];
                        'padratio'      'real'        []      1;
                        'freqs'         'real'        []      [0 EEG(1).srate/2];
                        'rmcomps'       'cell'        []      cell(1,length(EEG));
                        'interp'        'struct'      { }     struct([]);
                        'freqscale'     'string'      []      'log';
                        'alpha'         'real'        []      NaN;
                        'type'          'string'      { 'ersp' 'itc' 'both' 'ersp&itc' }  'both'}, 'std_ersp', 'ignore');
if isstr(g), error(g); end;
if isempty(g.trialindices), g.trialindices = cell(length(EEG)); end;
if ~iscell(g.trialindices), g.trialindices = { g.trialindices }; end;

% checking input parameters
% -------------------------
if isempty(g.components) & isempty(g.channels)
    if isempty(EEG(1).icaweights)
        error('EEG.icaweights not found');
    end
    g.components = 1:size(EEG(1).icaweights,1);
    disp('Computing ERSP with default values for all components of the dataset');
end

% select ICA components or data channels
% --------------------------------------
if isempty(g.fileout), g.fileout = fullfile(EEG(1).filepath, EEG(1).filename(1:end-4)); end;
if ~isempty(g.components)
    g.indices = g.components;
    prefix = 'comp';
    filenameersp   = [ g.fileout '.icaersp'  ];
    filenameitc    = [ g.fileout '.icaitc'   ];
    filenametrials = [ g.fileout '.icatimef' ];
    if ~isempty(g.channels)
        error('Cannot compute ERSP/ITC for components and channels at the same time');
    end;
elseif ~isempty(g.channels)
    if iscell(g.channels)
        if ~isempty(g.interp)
            g.indices = eeg_chaninds(g.interp, g.channels, 0);
        else
            g.indices = eeg_chaninds(EEG(1), g.channels, 0);
            for ind = 2:length(EEG)
                if ~isequal(eeg_chaninds(EEG(ind), g.channels, 0), g.indices)
                    error([ 'Channel information must be consistant when ' 10 'several datasets are merged for a specific design' ]);
                end;
            end;
        end;
    else
        g.indices = g.channels;
    end;
    prefix = 'chan';
    filenameersp   = [ g.fileout '.datersp'  ];
    filenameitc    = [ g.fileout '.datitc'   ];
    filenametrials = [ g.fileout '.dattimef' ];
end;

powbaseexist = 1; % used also later
if isempty(g.powbase) | isnan(g.powbase)
    powbaseexist = 0;
    g.powbase = NaN*ones(length(g.indices),1);  % default for timef()
end;
if size(g.powbase,1) ~= length(g.indices)
    error('powbase should be of size (ncomps,nfreqs)');
end

% Check if ERSP/ITC information found in datasets and if fits requested parameters
% ----------------------------------------------------------------------------
if exist( filenameersp ) & strcmpi(g.recompute, 'off')
    fprintf('Use existing file for ERSP: %s\n', filenameersp);
    return;
end;
%    tmpersp  = load( '-mat', filenameersp, 'parameters'); % AND IT SHOULD BE USED HERE TOO - ARNO
%	params   = struct(tmpersp.parameters{:});
%    if ~isequal(params.cycles, g.cycles)                   ...
%            | (g.padratio ~= params.padratio) ...
%            | ( (g.alpha~= params.alpha) & ~( isnan(g.alpha) & isnan(params.alpha)) )
%        % if not computed with the requested parameters, recompute ERSP/ITC
%        % i.e., continue
%    else
%        disp('File ERSP/ITC data already present, computed with the same parameters: no need to recompute...');
%        return; % no need to compute ERSP/ITC
%    end
%end;

% Compute ERSP parameters
% -----------------------
parameters = { 'cycles', g.cycles, 'padratio', g.padratio, ...
               'alpha', g.alpha, 'freqscale', g.freqscale, timefargs{:} };
defaultlowfreq = 3;
[time_range] = compute_ersp_times(g.cycles,  EEG(1).srate, ...
                                 [EEG(1).xmin EEG(1).xmax]*1000 , defaultlowfreq, g.padratio);
if time_range(1) < time_range(2) && g.freqs(1) == 0
     g.freqs(1) = defaultlowfreq; % for backward compatibility
end
parameters = { parameters{:} 'freqs' g.freqs };
if strcmpi(g.plot, 'off')
    parameters = { parameters{:} 'plotersp', 'off', 'plotitc', 'off', 'plotphase', 'off' };
end;
if powbaseexist & time_range(1) >= 0
    parameters{end+1} = 'baseboot';
    parameters{end+1} = 0;
    fprintf('No pre-0 baseline spectral estimates: Using whole epoch for timef() "baseboot"\n');
end

% return parameters
% -----------------
if strcmpi(g.getparams, 'on')
    X = []; times = []; freqs = [];
    if strcmpi(g.savetrials, 'on')
        parameters = { parameters{:} 'savetrials', g.savetrials };
    end;
    return;
end;

% No usable ERSP/ITC information available
% ---------------------------------
% tmpdata = [];
% for index = 1:length(EEG)
%     if isstr(EEG(index).data)
%         TMP = eeg_checkset( EEG(index), 'loaddata' );  % load EEG.data and EEG.icaact
%     else
%         TMP = EEG;
%     end
%     if ~isempty(g.components)
%         if isempty(TMP.icaact)                      % make icaact if necessary
%             TMP.icaact = (TMP.icaweights*TMP.icasphere)* ...
%                           reshape(TMP.data(TMP.icachansind,:,:), [ length(TMP.icachansind) size(TMP.data,2)*size(TMP.data,3) ]);
%         end;
%         tmpdata    = reshape(TMP.icaact, [ size(TMP.icaact,1) size(TMP.data,2) size(TMP.data,3) ]);
%         tmpdata    = tmpdata(g.indices, :,:);
%     else
%         if isempty(tmpdata)
%             tmpdata = TMP.data(g.indices,:,:);
%         else
%             tmpdata(:,:,end+1:end+size(TMP.data,3)) = TMP.data(g.indices,:,:);
%         end;
%     end;
% end;

options = {};
if ~isempty(g.rmcomps), options = { options{:} 'rmcomps' g.rmcomps }; end;
if ~isempty(g.interp),  options = { options{:} 'interp' g.interp }; end;
X       = [];
for dat = 1:length(EEG)
    if strcmpi(prefix, 'comp')
        tmpdata = eeg_getdatact(EEG(dat), 'component', [1:size(EEG(dat).icaweights,1)], 'trialindices', g.trialindices{dat} );
    else
        EEG(dat).data = eeg_getdatact(EEG(dat), 'channel', [1:EEG(dat).nbchan], 'rmcomps', g.rmcomps{dat}, 'trialindices', g.trialindices{dat});
        EEG(dat).trials = size(EEG(dat).data,3);
        EEG(dat).event  = [];
        EEG(dat).epoch  = [];
        if ~isempty(g.interp),
            TMPEEG = eeg_interp(EEG(dat), g.interp, 'spherical');
            tmpdata = TMPEEG.data;
        else
            tmpdata = EEG(dat).data;
        end;
    end;
    if isempty(X), X = tmpdata;
    else
        if size(X,1) ~= size(tmpdata,1), error('Datasets to be concatenated do not have the same number of channels'); end;
        if size(X,2) ~= size(tmpdata,2), error('Datasets to be concatenated do not have the same number of time points'); end;
        X(:,:,end+1:end+size(tmpdata,3)) = tmpdata; % concatenating trials
    end;
end;

% frame range
% -----------
pointrange1 = round(max((g.timelimits(1)/1000-EEG(1).xmin)*EEG(1).srate, 1));
pointrange2 = round(min(((g.timelimits(2)+1000/EEG(1).srate)/1000-EEG(1).xmin)*EEG(1).srate, EEG(1).pnts));
pointrange = [pointrange1:pointrange2];

% Compute ERSP & ITC
% ------------------
all_ersp   = [];
all_trials = [];
all_itc    = [];
for k = 1:length(g.indices)  % for each (specified) component
    if k>size(X,1), break; end; % happens for components
    if powbaseexist
        tmpparams = parameters;
        tmpparams{end+1} = 'powbase';
        tmpparams{end+1} = g.powbase(k,:);
    else
        tmpparams = parameters;
    end;

    % Run timef() to get ERSP
    % ------------------------
    timefdata  = reshape(X(k,pointrange,:), 1, length(pointrange)*size(X,3));
    if strcmpi(g.plot, 'on'), figure; end;
    [logersp,logitc,logbase,times,logfreqs,logeboot,logiboot,alltfX] ...
          = newtimef( timefdata, length(pointrange), g.timelimits, EEG(1).srate, tmpparams{2:end});
    %figure; newtimef( TMP.data(32,:), EEG.pnts, [EEG.xmin EEG.xmax]*1000, EEG.srate, cycles, 'freqs', freqs);
    %figure; newtimef( timefdata, length(pointrange), g.timelimits, EEG.srate, cycles, 'freqs', freqs);
    if strcmpi(g.plot, 'on'), return; end;

    all_ersp = setfield( all_ersp, [ prefix int2str(g.indices(k)) '_ersp'     ], single(logersp ));
    all_ersp = setfield( all_ersp, [ prefix int2str(g.indices(k)) '_erspbase' ], single(logbase ));
    all_ersp = setfield( all_ersp, [ prefix int2str(g.indices(k)) '_erspboot' ], single(logeboot));
    all_itc  = setfield( all_itc , [ prefix int2str(g.indices(k)) '_itc'      ], single(logitc  ));
    all_itc  = setfield( all_itc , [ prefix int2str(g.indices(k)) '_itcboot'  ], single(logiboot));

    if strcmpi(g.savetrials, 'on')
        all_trials = setfield( all_trials, [ prefix int2str(g.indices(k)) '_timef'     ], single( alltfX ));
    end;
end

% Save ERSP into file
% -------------------
all_ersp.freqs      = logfreqs;
all_ersp.times      = times;
all_ersp.datatype   = 'ERSP';
all_itc.freqs       = logfreqs;
all_itc.times       = times;
all_itc.parameters  = parameters;
all_itc.datatype    = 'ITC';
all_trials.freqs    = logfreqs;
all_trials.times    = times;
all_trials.parameters = { options{:} parameters{:} };
all_trials.datatype   = 'TIMEF';

if powbaseexist
    all_ersp.parameters = { parameters{:}, 'baseline', g.powbase };
else
    all_ersp.parameters = parameters;
end;
if ~isempty(g.channels)
    if ~isempty(g.interp)
        all_ersp.chanlabels   = { g.interp(g.indices).labels };
        all_itc.chanlabels    = { g.interp(g.indices).labels };
        all_trials.chanlabels = { g.interp(g.indices).labels };
    elseif ~isempty(EEG(1).chanlocs)
        tmpchanlocs = EEG(1).chanlocs;
        all_ersp.chanlabels   = { tmpchanlocs(g.indices).labels };
        all_itc.chanlabels    = { tmpchanlocs(g.indices).labels };
        all_trials.chanlabels = { tmpchanlocs(g.indices).labels };
    end;
end;

if strcmpi(g.type, 'both') | strcmpi(g.type, 'ersp') | strcmpi(g.type, 'ersp&itc')
    std_savedat( filenameersp, all_ersp);
end;
if strcmpi(g.type, 'both') | strcmpi(g.type, 'itc') | strcmpi(g.type, 'ersp&itc')
    std_savedat( filenameitc , all_itc );
end;
if strcmpi(g.savetrials, 'on')
    std_savedat( filenametrials , all_trials );
end;


function p=drex_invlogit(a)
%DREX subfunction
%Written by Issam El Naqa 2003-2005
%Extracted for generalized use 2005, AJH
%
% Copyright 2010, Joseph O. Deasy, on behalf of the DREES development team.
%
% This file is part of the Dose Response Explorer System (DREES).
%
% DREES development has been led by:  Issam El Naqa, Aditya Apte, Gita Suneja, and Joseph O. Deasy.
%
% DREES has been financially supported by the US National Institutes of Health under multiple grants.
%
% DREES is distributed under the terms of the Lesser GNU Public License.
%
%     This version of DREES 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.
%
% DREES 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 DREES.  If not, see <http://www.gnu.org/licenses/>.

p = 1 ./ (1 + exp(-a));

return


function x = proxTVSquare(x,lambda,alpha,varargin)

[n,m] = size(x);
lambda = alpha * lambda; % only the product matters

% apply proxTV horizontally
mMax = 2*floor((m+1)/2)-1; % round down to an odd number
[x(:,2:2:mMax),x(:,3:2:mMax)] = proxTV(x(:,2:2:mMax),x(:,3:2:mMax),lambda,varargin{:});

mMax = 2*floor(m/2); % round down to an even number
[x(:,1:2:mMax),x(:,2:2:mMax)] = proxTV(x(:,1:2:mMax),x(:,2:2:mMax),lambda,varargin{:});

% apply proxTV vertically
nMax = 2*floor((n+1)/2)-1; % round down to an odd number
[x(2:2:nMax,:),x(3:2:nMax,:)] = proxTV(x(2:2:nMax,:),x(3:2:nMax,:),lambda,varargin{:});

nMax = 2*floor(n/2); % round down to an even number
[x(1:2:nMax,:),x(2:2:nMax,:)] = proxTV(x(1:2:nMax,:),x(2:2:nMax,:),lambda,varargin{:});


function res = TTeMPS_op_laplace_to_TTeMPS_op( A )
    %TTeMPS_op_laplace_to_TTeMPS Convert to TT_op_laplace to TTeMPS_op format.
    %
    %   See also TTeMPS_to_TT, TTeMPS_op_to_TT, TTeMPS_op_laplace_to_TTeMPS_op.

    %   TTeMPS Toolbox.
    %   Michael Steinlechner, 2013-2016
    %   Questions and contact: michael.steinlechner@epfl.ch
    %   BSD 2-clause license, see LICENSE.txt

    C = cell(1, A.order);
    for i = 1:A.order
        % make a 4D tensor out of it again
        tmp = reshape( full(A.U{i}), [A.rank(i), A.rank(i+1), A.size_col(i), A.size_row(i)] );
        % inverse permute the indices
        C{i} = ipermute( tmp, [1 4 2 3] );
    end
    res = TTeMPS_op(C);
end


function test_ft_volumedownsample

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY ft_volumedownsample SPM

mri = [];
mri.anatomy = randn(181,217,181);
mri.dim = [181 217 181];
mri.transform = eye(4);
mri.unit = 'cm';
mri.coordsys = 'ctf';

cfg = [];
cfg.downsample = 2;
cfg.parameter = 'anatomy';
mriout = ft_volumedownsample(cfg, mri);


A=sprand(200,200000,0.05);

tic
AAt=mexCalcAAt(A);
t=toc;
fprintf('mex-file time: %fs\n',t);

tic
AAt2=A*A';
t=toc;
fprintf('matlab time: %fs\n',t);

sum((AAt(:)-AAt2(:)).^2)


function [trl] = read_fcdc_trl(fn)

% READ_FCDC_TRL reads trial definitions from a file
%
% Given a file which defines N trials, this function returns a Nx3
% matrix with the begin latency, end latency, and the latency offset
% of the first sample of each trial. The latencies are in seconds.
%
% [trl] = read_fcdc_trl(filename)
%
% An FCD trial definition file is formatted like
%   begin   end     offset
%   0.0000  1.0000  0.0000
%   3.0000  4.0000  0.0000
%   5.0000  5.5000  0.0000
%   ...
%
% The trial begin and end are given in seconds relative to the start
% of the recorded datafile. The offset is given in seconds and indicates
% the latency of the first sample, relative to the trial marker or
% trigger. E.g., given a trigger at 7000ms (relative to the recording
% begin), a trial of 1000ms with a pretrigger interval of 300ms would
% correspond to "6.700 7.700 -0.300".

% Copyright (C) 2003, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

fid = fopen_or_error(fn, 'rt');

trl = [];
while ~feof(fid)
  tmp = fscanf(fid, '%f %f %f', 3);
  if ~isempty(tmp)
    trl = [trl; tmp'];
  end
end

fclose(fid);


function c8_mag_test ( )

%*****************************************************************************80
%
%% C8_MAG_TEST tests C8_MAG.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 February 2015
%
%  Author:
%
%    John Burkardt
%
  seed = 123456678;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'C8_MAG_TEST\n' );
  fprintf ( 1, '  C8_MAG computes the magnitude of a C8.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, ...
    '       C1=C8_UNIFORM_01          R2=C8_MAG(C1)             R3=ABS(C1))\n' );
  fprintf ( 1, '     ---------------------     ---------------------     ---------------------\n' );
  fprintf ( 1, '\n' );

  for test = 1 : 10

    [ c1, seed ] = c8_uniform_01 ( seed );
    r2 = c8_mag ( c1 );
    r3 = abs ( c1 );

    fprintf ( 1, '  (%12f  %12f)  %12f  %12f\n', ...
      real ( c1 ), imag ( c1 ), r2, r3 );

  end

  return
end


function plot3(catalogObject, varargin)
    %CATALOG.PLOT3 Plot hypocenters in 3-D
    %   catalogObject.plot3()
    %
    %   Optional name/value pairs:
    %     'nsigma' - controls how zoomed-in the axes are (default
    %     5)

    % Glenn Thompson 2014/06/01
    if all(isnan(catalogObject.lat))
        warning('No hypocenter data to plot');
        return
    end
    p = inputParser;
    p.addParamValue('nsigma', '5', @isstr);
    p.parse(varargin{:});
    nsigma = p.Results.nsigma;

    % change region
    region = get_region(catalogObject, nsigma);

    % Compute Marker Size
    symsize = get_symsize(catalogObject);

    % 3D plot
    figure
    set(gcf,'Color', [1 1 1]);
    scatter3(catalogObject.lon, catalogObject.lat, catalogObject.depth, symsize);
    set(gca, 'ZDir', 'reverse');
    grid on;
    set(gca, 'XLim', [region(1) region(2)]);
    set(gca, 'YLim', [region(3) region(4)]);
    xlabel('Longitude');
    ylabel('Latitude');
    zlabel('Depth (km)');

end


%CALCOPTICALFLOWDF  DeepFlow optical flow algorithm implementation
%
%     flow = cv.calcOpticalFlowDF(I0, I1)
%
% ## Input
% * __I0__ First 8-bit single-channel grayscale input image.
% * __I1__ Second input image of the same size and type as `I0`.
%
% ## Output
% * __flow__ computed flow image that has the same size as `I0` and type
%   `single` (2-channels). Flow for `(x,y)` is stored in the third dimension.
%
% The class implements the DeepFlow optical flow algorithm described in
% [Weinzaepfel2013]. See also
% [DeepMatching](http://lear.inrialpes.fr/src/deepmatching/).
% Parameters - class fields - are:
%
% * __Alpha__ Smoothness assumption weight. default 1.0
% * __Delta__ Color constancy assumption weight. default 0.5
% * __Gamma__ Gradient constancy weight. default 5.0
% * __Sigma__ Gaussian smoothing parameter. default 0.6
% * __MinSize__ Minimal dimension of an image in the pyramid (next, smaller
%   images in the pyramid are generated until one of the dimensions reaches
%   this size). default 25
% * __DownscaleFactor__ Scaling factor in the image pyramid (must be <1).
%   default 0.95
% * __FixedPointIterations__ How many iterations on each level of the pyramid.
%   default 5
% * __SorIterations__ Iterations of Successive Over-Relaxation (solver).
%   default 25
% * __Omega__ Relaxation factor in SOR. default 1.6
%
% ## References
% [Weinzaepfel2013]:
% > Philippe Weinzaepfel, Jerome Revaud, Zaid Harchaoui, and Cordelia Schmid.
% > "Deepflow: Large displacement optical flow with deep matching".
% > In Computer Vision (ICCV), 2013 IEEE International Conference on,
% > pages 1385-1392. IEEE, 2013.
%
% See also: cv.calcOpticalFlowSF, cv.calcOpticalFlowFarneback
%


function [volOut,axisLabels]=changeAnatomyAxes(inVolume,axisTransform)
% function [volOut,axisLabels]=changeAnatomyAxes(inVolume,axisLabels)
% Rearrange the axes of a medical imaging brain volume.
% INPUT:
% inVolume:          3D input volume.
% axisTransform: This defines the way the axes will be re-arranged.
%              : It is a 3*1 array which must contain a permutation of the digits [1,2,3]
% Basically, we call 'permute' with this array (after doing some flips).

% Example:
% We have a volume y*x*z in size (so size(inVolume)=[y,x,z]
% The axes are y: axial, x: coronal, z: sagittal.
% In other words, if we take an image slice a=inVolume(:,:,fix(z/2));
% then 'a' is a sagittal view of the midline with the nose facing left, and dorsal pointing up.
% Now we want to rearrange the volume so that the same slice (:,:,fix(z/2)) will give us an axial view with the
% nose pointing up and the right ear on the right: y coronal, x sagittal, z axial
% So axisTransform is
% [2 3 1]
% In other words, the first axis in the original image becomes the 3rd axis in the target
% The second axis becomes the first and the third becomes the second.
% To flip the image so that left and right ears were reversed, we would make the second entry -ve: [2 -3 1]

% ARW 03.12.02

% Check number of input argumnents and size of inVolume

if (nargin~=2)
    error('This routine needs 2 input arguments');
end

volSize=size(inVolume);

axisTransform=axisTransform(:);

if (length(axisTransform)~=length(volSize))
    error('axisTransform matrix must be a vector with the same number of entries as there are dimensions in inVolume');
end

% Do flipdim operations
[flippedDims]=find(axisTransform<0);

for t=flippedDims
    flipdim(inVolume,abs(axisTransform(t)));
end

% Do the permutation
volOut=permute(inVolume,abs(axisTransform));


%% t_gifti_1
%

% Download from RDT
%{
 fullFolderName = fullfile(vistaRootPath,'local');
 rdt = RdtClient('vistasoft');

 rdt.crp('/vistadata/anatomy/anatomyNIFTI');
 leftMeshFile = rdt.readArtifact('leftMesh',...
    'type','mat',...
    'destinationFolder',fullFolderName);

 rdt.crp('/vistadata/gifti/BV_GIFTI/Base64');
 gFile = rdt.readArtifact('sujet01_Lwhite.surf',...
    'type','gii',...
    'destinationFolder',fullFolderName);

%}

%%
chdir(fullfile(vistaRootPath,'local'));

%% Converting  gifti to mrMesh (see above for the other direction)

mshFile = fullfile(vistaRootPath,'local','leftMesh.mat');
load(mshFile)
meshVisualize(msh);

% Load a GIFTI file
gFile = fullfile(vistaRootPath,'local','sujet01_Lwhite.surf.gii');
g = gifti(gFile);
% Blue shaded
% mrvNewGraphWin; plot(g);

% Seen with mrMesh - shading not yet right, but it comes up
msh = meshCreate;
msh.triangles = double(g.faces' - 1);
msh.vertices  = double(g.vertices');
% msh = meshColor(msh);

c = ones(3,size(msh.vertices,2))*120;
c(4,size(msh.vertices,2)) = 255;
msh.colors = c;
meshVisualize(msh);

% Can't smooth without the normals.  Perhaps we can create these using
% isonormals().  Also, we might be able to effectively smooth using the
% Matlab function reducepatch.  I don't know how to meshColor.
%
% msh2 = meshSmooth(msh);
% meshVisualize(msh);
% Also doesn't work just yet.
% foo = mrMeshCurvature(msh);

%% End


function [AC, nmi_value, error_cnt] = CalcMetrics(label, result)

result = bestMap(label, result);
error_cnt = sum(label ~= result);
AC = length(find(label == result))/length(label);

nmi_value = nmi(label, result);


function [out_vec] = ch_model_tgn(in_vec)
% ch_model_tgn.m - TGn channel model simulation (load external coeff's)
global numPkts  PER_snr  snr_idx  ch_type  num_taps ...
       H  H_idx_inc  H_idx_ini  H_idx  H_cnt  H_dline;

% PER graph settings (actual values are user-selected (GUI))
%%%%% numPkts = 200;
%%%%% PER_snr = 29:2:37;

% To select channel matrices
numCoherenceTimes = ceil(10*numPkts/442);      % num of coherence times to test
numSampPerCohere = numPkts/numCoherenceTimes;  % max value = 442 (num of ch. samples in one coherence time)

% Input parameters
Clk = in_vec(1);
Ntx = in_vec(2);
Nrx = in_vec(3);
Nltf = in_vec(4);

% Index for additive noise
%     - add noise after 8 legacy sym, 2 HT-LTF symbols (with 6 sample delay)
%     - done to simulate with perfect channel estimation...
nse_idx = 1; %%5*80*(8+Nltf) + 5*6;

% Channel inputs
in_len = length(in_vec(5:end))/4;
ch_in  = zeros(4, in_len);
ch_in(1,:) = in_vec(0*in_len+3+(1:in_len)).';
ch_in(2,:) = in_vec(1*in_len+3+(1:in_len)).';
ch_in(3,:) = in_vec(2*in_len+3+(1:in_len)).';
ch_in(4,:) = in_vec(3*in_len+3+(1:in_len)).';
ch_in = ch_in(1:Ntx,:);  % keep only used Tx ant. inputs

% Channel outputs
ch_out = zeros(4, in_len);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Channel Model (external coeff's)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Various channel models, widths
ChD_Width   = [   10     10     10     10     10     10     10     10     10     20     30     30     30     40     50     50     50     50];

% Select channel model
if (1)
    ch_width = ChD_Width;
end

% Initialize channel model
if (Clk==0)
    % Initialize PER test
    snr_idx = 1;

    % Load Channel coeff's
    load ..\..\tgn_ch_taps\tgn_chD_nlos(fluor)_2x2_short;
    %load ..\..\tgn_ch_taps\tgn_chD_nlos_15m_4x4;

    % Setup channel coeff's for PER test
    H_cohere_prd = ceil(size(H, 4)/100);  % ch. mat samples in one coherence time (100 simulated)
    H_idx_inc = round(H_cohere_prd / numSampPerCohere);

    % Setup indices for channel coeff's
    num_taps = size(H, 3);
    H_idx_ini = 100;   % initial index for channel matrices
    H_idx = H_idx_ini;
    H_cnt = 1;

    % Initialize channel delay line
    tot_dly = sum(ch_width)/10;
    H_dline = zeros(Ntx, tot_dly);
end

% Use fixed channel for each packet
%     - assume 38400 samples for each packet (with silence added)
if 1  %(FIXED_CHANNEL)
 % Get channel coeff's
 H_tap(1:Ntx,1:Nrx,:) = H(1:Ntx,1:Nrx,:,H_idx);
 %H_tap(:,:,:) = H(:,:,:,H_idx);
 % Increment index after every packet...
 H_idx = H_idx + H_idx_inc;
 if (H_idx > size(H, 4)) H_idx = H_idx_ini; end

 % Compute channel power...
 H_pow = 0;
 for m=1:num_taps
    for k = 1:(ch_width(m)/10)
        He = H_tap(:,:,m);
        H_pow = H_pow + sum(sum(He.*conj(He)))/Nrx;
    end
 end
end

% Process all input samples...
for i=1:in_len

    % Add new sample to delay line
    H_dline = [ch_in(:,i) H_dline(:,1:end-1)];

    % Apply channel filter
    H_dline_idx = 1;
    H_out = zeros(Nrx,1);
    for m=1:num_taps
        % Apply tap to inputs (considering tap width)
        H_samp = zeros(Ntx, 1);
        for k = 1:(ch_width(m)/10)
            % 10 ns (100 MHz) sampling
            H_samp = H_samp + H_dline(:,H_dline_idx);
            H_dline_idx = H_dline_idx + 1;
        end
        H_out = H_out + H_tap(:,:,m).'*H_samp;
    end

    % Store channel output
    ch_out(1:Nrx,i) = H_out(1:Nrx);
end

% Compute noise variance (time-domain)
nse_sigma = H_pow*(1/5);                % signal upsampled by 5
nse_sigma = sqrt(0.5*nse_sigma);

% Add AWGN to Rx streams
snr_val = PER_snr(snr_idx);
for i=1:Nrx
     % Generate additive noise
     nse_size = size(ch_out(i,nse_idx:end));
     nse_out = nse_sigma * (randn(nse_size) + j*randn(nse_size));
     nse_out = nse_out * 10^(-snr_val/20);
     % Add noise to channel output
     ch_out(i,nse_idx:end) = ch_out(i,nse_idx:end) + nse_out;
end

% Next SNR Value for PER Curve...
if (mod(Clk,numPkts)==(numPkts-1) && snr_idx<length(PER_snr))
    snr_idx = snr_idx+1;
end

% Return output
out_vec = reshape(ch_out.', 4*in_len, 1);


function [scanArray3M,mask3M] = perturbImageAndSeg(scanArray3M,mask3M,planC,...
         scanNum,perturbString,angle2DStdDeg,volScaleStdFraction,superPixVol)
% [scanArray3M,mask3M] = perturbImageAndSeg(scanArray3M,mask3M,planC,scanNum,...
%                        perturbString,angle2DStdDeg,volScaleStdFraction,superPixVol)
%
% perturbString is a string containing perturbation operations. It can be a
% combination of any letters RNTVC.
%
% APA, 2/28/2019
% AI , 3/22/2019 Added inputs angle2DStdDeg,volScaleStdFraction,superPixVol

% Noise
if ismember('N',perturbString)
    scanArray3M = perturbImageNoise(scanArray3M);
end

% Rotation
if ismember('R',perturbString)
    angl = normrnd(0,angle2DStdDeg);
    [scanArray3M,mask3M] = perturbImageRotation(scanArray3M,mask3M,angl);
end

% Volume adaptation
if ismember('V',perturbString)
    scale = normrnd(1,volScaleStdFraction);
    mask3M = perturbImageVolume(mask3M,scale);
end

% Contour randomization
if ismember('C',perturbString)
    mask3M = perturbImageContourBySuperpix(mask3M,scanArray3M,superPixVol,planC,scanNum);
end


function [f,h, whichSlice] = sagittalSlices(tv, ccfCoords, f)

if nargin<3
    f = figure;
    p = get(f, 'Position');
    set(f, 'Position',   [p(1) p(2)      1597         700]);
    set(f, 'Color', 'k');
    slicesExist = false;
else
    slicesExist = true;
end

slicePoints = 0.25:0.25:3.0; %mm
bregma = allenCCFbregma(); %voxels
sliceCCF = -slicePoints*1000+bregma(3)*10;

cc = ccfCoords;

r = randn(size(cc,1),2)*45;

[~,whichSlice] = min(abs(cc(:,3)-sliceCCF),[],2);

h = [];

apCoords = (0:size(tv,1)-1)*10;
dvCoords = (0:size(tv,2)-1)*10;

inclAP = apCoords>1000 & apCoords<11000;
inclDV = dvCoords<6000;

for s = 1:numel(sliceCCF)
    subtightplot(3,4,s);
    if ~slicesExist
        imagesc(apCoords(inclAP), dvCoords(inclDV), ...
            tv(inclAP,inclDV,round(sliceCCF(s)/10))');
        colormap gray
        axis image
        caxis([0 400]);
        axis off
    end

%     title(sprintf('ML = %.2f', slicePoints(s)));

    hold on;

    inclN = whichSlice==s & cc(:,3)>0;

    h(s) = scatter(cc(inclN,1)+r(inclN,1),cc(inclN,2)+r(inclN,2),4,'r','filled');
end


classdef TestCalcOpticalFlowDF
    %TestCalcOpticalFlowDF

    methods (Static)
        function test_1
            im1 = 255*uint8([...
                0 0 0 0 0 0 0 0 0 0;...
                0 0 0 0 0 0 0 0 0 0;...
                0 0 0 0 0 0 0 0 0 0;...
                0 0 0 1 1 1 0 0 0 0;...
                0 0 0 1 0 1 0 0 0 0;...
                0 0 0 1 1 1 0 0 0 0;...
                0 0 0 0 0 0 0 0 0 0;...
                0 0 0 0 0 0 0 0 0 0;...
                0 0 0 0 0 0 0 0 0 0;...
                0 0 0 0 0 0 0 0 0 0;...
            ]);
            im2 = circshift(im1, [0 1]);
            flow = cv.calcOpticalFlowDF(im1, im2);
            validateattributes(flow, {'single'}, ...
                {'3d', 'size',[size(im1,1) size(im1,2) 2]});
        end

        function test_2
            prevImg = cv.imread(fullfile(mexopencv.root(),'test','RubberWhale1.png'), ...
                'Grayscale',true, 'ReduceScale',2);
            nextImg = cv.imread(fullfile(mexopencv.root(),'test','RubberWhale2.png'), ...
                'Grayscale',true, 'ReduceScale',2);
            flow = cv.calcOpticalFlowDF(prevImg, nextImg);
            validateattributes(flow, {'single'}, ...
                {'3d', 'size',[size(prevImg,1) size(prevImg,2) 2]});
        end

        function test_error_argnum
            try
                cv.calcOpticalFlowDF();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


classdef SPX_Modulator < handle

    methods(Static)

        function [ outputSequence ] = modulate_bits_with_signals( inputSequence, s1, s0)
            %MODULATEBINARYSEQUENCE Modulates a sequence of bits to create output
            % The size of signal for each bit
            [N, L] = size(s1);
            % If s0 is not defined, we will assume s0 to be all zeros
            if ~exist('s0','var')
              s0=zeros(size(s1));
            end
            if ~iscolumn(s1)
                error('s1 must be a column vector.');
            end
            if ~iscolumn(s0)
                error('s0 must be a column vector.');
            end
            if ~isvector(inputSequence)
                error('inputSequence must be a vector.');
            end
            % Number of bits
            E = length(inputSequence);
            % Combine the two signals into a matrix
            s = [s0 s1];
            % The row number for each output
            r  = 1:N;
            outputSequence  = s(r, inputSequence+1);
            outputSequence = reshape(outputSequence, N*E,1);
        end

        function [ transmittedSequence ] = modulate_bits_with_gaussian_noise(...
            transmittedBits, N, sigma1, sigma0)
            %MODULATE_BITS_WITH_GAUSSIAN_NOISE Generates Gaussian noise samples with different
            %variances for the transmitted bits

            %   Detailed explanation goes here

            % Number of transmitted bits
            B = length(transmittedBits);
            % We create space for transmitted sequence
            transmittedSequence = zeros(B * N , 1);
            for i=1:B
                pos = (i-1)*N;
                bit = transmittedBits(i);
                if bit
                    transmittedSequence(pos + (1:N))  = sigma1 * randn(N,1);
                else
                    transmittedSequence(pos + (1:N))  = sigma0 * randn(N,1);
                end
            end

        end

        function [ outputSequence ] = modulate_mary_symbols_with_signals( inputSequence, signals )
            %MODULATE_MARY_SYMBOLS_WITH_SIGNALS Modulates a sequence of M-ary symbols to create
            %an output signal
            %
            % Input:
            %   inputSequence: Sequence of M-ary symbols.
            %       We assume that the symbols are in [1,M]
            %   signals: signals to be used for each symbol
            %       Every signal has length N[as a column vector]
            %       and there are M such signals.

            % The size of signal and number of signals
            [N, M] = size(signals);
            % Number of symbols
            E = length(inputSequence);
            % The modulation process
            % First generate signal for each symbol
            % column by column
            outputSequence  = signals(1:N, inputSequence);
            % Then reshape the output to a column vector
            outputSequence = reshape(outputSequence, N*E,1);
        end

    end

end


% Test file for ADCHEBFUN times

function pass = test_innerProduct

% Initialise pass vector
pass = zeros(3, 5);

% Tolerance for Taylor testing
tolOrder = 1e-2;
tolDiff = 1e-14;

% The function handle we're working with:
func = @innerProduct;

% Compare values
[err, lin] = adchebfun.valueTestingBinary(func);

% Confirm that the error returned is close to zero. Note that the error won't be
% exact zero, due to slightly different mechanisms used in
% CHEBFUN/INNERPRODUCT() and ADCHEBFUN/INNERPRODUCT() for computing the value of
% the inner products.
pass(1, :) = ( err < tolDiff );

% Taylor testing
[order1, order2, nDiff2] = adchebfun.taylorTestingBinary(func);

% We expect all elements of ORDER1 to be close to 1. Since depending on the
% combinations of variables (ADCHEBFUN, CHEBFUN and SCALAR), we should expect
% some of ORDER2 to be noise (for linear operations), in which case NDIFF2
% should have values close to machine epsilon. For the nonlinear operations,
% ORDER2 will be close having all elements value close to 2.

% Check whether we get the expected results for linear and nonlinear
% operations.
linearOpResults = ( ((max(abs(order1(:, 2:end))) - 1) < tolOrder) & ...
    (max(abs(nDiff2(:, 2:end))) < tolDiff) );

nonlinearOpResults = ( (max(abs(order1(:, 1) - 1)) < tolOrder) && ...
    (max(abs(order2(:, 1) - 2)) < tolOrder) );

% Concatenate results
pass(2, :) = [nonlinearOpResults, linearOpResults];

% Check whether we received correct linearity information.
pass(3, :) = ( lin == [0, 1, 1, 1, 1]);
end


function box = mergeBoxes3d(box1, box2)
%MERGEBOXES3D Merge 3D boxes, by computing their greatest extent.
%
%   BOX = mergeBoxes3d(BOX1, BOX2);
%
%   Example
%   box1 = [5 20 5 30 10 50];
%   box2 = [0 15 0 15 0 20];
%   mergeBoxes3d(box1, box2)
%   ans =
%       0 20 0 30 0 50
%
%
%   See also
%   boxes3d, drawBox3d, intersectBoxes3d
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2010-07-26,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.

% unify sizes of data
if size(box1,1) == 1
    box1 = repmat(box1, size(box2,1), 1);
elseif size(box2, 1) == 1
    box2 = repmat(box2, size(box1,1), 1);
elseif size(box1,1) ~= size(box2,1)
    error('Bad size for inputs');
end

% compute extreme coords
mini = min(box1(:,1:2:end), box2(:,1:2:end));
maxi = max(box1(:,2:2:end), box2(:,2:2:end));

% concatenate result into a new box structure
box = [mini(:,1) maxi(:,1) mini(:,2) maxi(:,2) mini(:,3) maxi(:,3)];


%SF_LAGMP Constant lagrange multiplier.
%
%   [ VBASE, NLDOF, XLDOF, SFUN ] = SF_LAGMP( I_EVAL, N_SDIM, N_VERT, I_DOF, XI, AINVJAC, VBASE )
%   Evaluates constant lagrange multiplier.
%
%       Input       Value/[Size]           Description
%       -----------------------------------------------------------------------------------
%       i_eval      scalar:  1             Evaluate function values
%                           >1             Evaluate values of derivatives
%       n_sdim      scalar: 1-3            Number of space dimensions
%       n_vert      scalar: 2-8            Number of vertices per cell
%       i_dof       scalar: 1-n_ldof       Local basis function to evaluate
%       xi          [n_sdim(+1)]           Local coordinates of evaluation point
%       aInvJac     [n,n_sdim(+1)*n_sdim]  Inverse of transformation Jacobian
%       vBase       [n]                    Preallocated output vector
%                                                                                .
%       Output      Value/[Size]           Description
%       -----------------------------------------------------------------------------------
%       vBase       [n]                    Evaluated function values
%       nLDof       [4]                    Number of local degrees of freedom on
%                                          vertices, edges, faces, and cell interiors
%       xLDof       [n_sdim,n_ldof]        Local coordinates of local dofs
%       sfun        string                 Function name of called shape function

% Copyright 2013-2022 Precise Simulation, Ltd.


function M = femMultiplyCell(varargin)
%+========================================================================+
%|                                                                        |
%|              OPENFEM - LIBRARY FOR FINITE ELEMENT METHOD               |
%|           openFem is part of the GYPSILAB toolbox for Matlab           |
%|                                                                        |
%| COPYRIGHT : Matthieu Aussal & Francois Alouges (c) 2017-2018.          |
%| PROPERTY  : Centre de Mathematiques Appliquees, Ecole polytechnique,   |
%| route de Saclay, 91128 Palaiseau, France. All rights reserved.         |
%| LICENCE   : This program is free software, distributed in the hope that|
%| it will be useful, but WITHOUT ANY WARRANTY. Natively, you can use,    |
%| redistribute and/or modify it under the terms of the GNU General Public|
%| License, as published by the Free Software Foundation (version 3 or    |
%| later,  http://www.gnu.org/licenses). For private use, dual licencing  |
%| is available, please contact us to activate a "pay for remove" option. |
%| CONTACT   : matthieu.aussal@polytechnique.edu                          |
%|             francois.alouges@polytechnique.edu                         |
%| WEBSITE   : www.cmap.polytechnique.fr/~aussal/gypsilab                 |
%|                                                                        |
%| Please acknowledge the gypsilab toolbox in programs or publications in |
%| which you use it.                                                      |
%|________________________________________________________________________|
%|   '&`   |                                                              |
%|    #    |   FILE       : femMultiplyCell.m                             |
%|    #    |   VERSION    : 0.40                                          |
%|   _#_   |   AUTHOR(S)  : Matthieu Aussal & François Alouges            |
%|  ( # )  |   CREATION   : 14.03.2017                                    |
%|  / 0 \  |   LAST MODIF : 14.03.2018                                    |
%| ( === ) |   SYNOPSIS   : Multiply finite elements cells                |
%|  `---'  |                                                              |
%+========================================================================+

if (nargin == 1)
    M = varargin{1};

elseif (nargin == 2)
    A = varargin{1};
    B = varargin{2};

    if iscell(A) && iscell(B)
        M = A{1} * B{1} + ...
            A{2} * B{2} + ...
            A{3} * B{3} ;

    elseif iscell(A) && ~iscell(B)
        M{1} = A{1} * B ;
        M{2} = A{2} * B ;
        M{3} = A{3} * B ;

    elseif ~iscell(A) && iscell(B)
        M{1} = A * B{1} ;
        M{2} = A * B{2} ;
        M{3} = A * B{3} ;

    elseif ~iscell(A) && ~iscell(B)
        M = A * B;

    else
        error('femMultiplyCell.m : unavailable case')
    end

elseif (nargin == 3)
    A = varargin{1};
    B = varargin{2};
    C = varargin{3};

    if iscell(A) && iscell(B) && iscell(C)
        M = A{1} * B{2} * C{3} - ...
            A{1} * B{3} * C{2} + ...
            A{2} * B{3} * C{1} - ...
            A{2} * B{1} * C{3} + ...
            A{3} * B{1} * C{2} - ...
            A{3} * B{2} * C{1} ;

    elseif iscell(A) && iscell(B) && ~iscell(C)
        M = ( A{1} * B{1} + ...
            A{2} * B{2} + ...
            A{3} * B{3} ) * C;

    elseif iscell(A) && ~iscell(B) && iscell(C)
        M = A{1} * B * C{1} + ...
            A{2} * B * C{2} + ...
            A{3} * B * C{3} ;

    elseif ~iscell(A) && iscell(B) && iscell(C)
        M = A * ( B{1} * C{1} + ...
            B{2} * C{2} + ...
            B{3} * C{3} );

    elseif ~iscell(A) && ~iscell(B) && iscell(C)
        M{1} = A * B * C{1};
        M{2} = A * B * C{2};
        M{3} = A * B * C{3};

    elseif ~iscell(A) && iscell(B) && ~iscell(C)
        M{1} = A * B{1} * C;
        M{2} = A * B{2} * C;
        M{3} = A * B{3} * C;

    elseif iscell(A) && ~iscell(B) && ~iscell(C)
        M{1} = A{1} * B * C;
        M{2} = A{2} * B * C;
        M{3} = A{3} * B * C;

    elseif ~iscell(A) && ~iscell(B) && ~iscell(C)
        M = A * B * C;
    else
        error('femMultiplyCell.m : unavailable case')
    end

else
    error('femMultiplyCell.m : unavailable case')
end
end


function [TrainData, TestData, TrainLabel, TestLabel, numX] = createData_CRA()
    ncFeature = 36;  % features of color
    ntFeature = 51;  % features of text

    % load source domain 1
    A = textread(strcat('data/img/11_color36.txt'));
    B = textread(strcat('data/img/11_texture51.txt'));
    n1 = size(A,1)/ncFeature;
    for i = 1:n1
        Cc(:,i) = A((ncFeature*(i-1)+1):ncFeature*i,1);
        D(:,i) = B((ntFeature*(i-1)+1):ntFeature*i,1);
        TrainY1(1,i) = 1;
    end
    A = textread(strcat('data/img/15_color36.txt'));
    B = textread(strcat('data/img/15_texture51.txt'));
    n2 = size(A,1)/ncFeature;
    for i = 1:n2
        Cc(:,i+n1) = A((ncFeature*(i-1)+1):ncFeature*i,1);
        D(:,i+n1) = B((ntFeature*(i-1)+1):ntFeature*i,1);
        TrainY1(1,i+n1) = -1;
    end
    TrainX1 = [Cc;D];
    clear Cc;
    clear D;
    % load source domain 2
    A = textread(strcat('data/img/12_color36.txt'));
    B = textread(strcat('data/img/12_texture51.txt'));
    n1 = size(A,1)/ncFeature;
    for i = 1:n1
        Cc(:,i) = A((ncFeature*(i-1)+1):ncFeature*i,1);
        D(:,i) = B((ntFeature*(i-1)+1):ntFeature*i,1);
        TrainY2(1,i) = 1;
    end
    A = textread(strcat('data/img/16_color36.txt'));
    B = textread(strcat('data/img/16_texture51.txt'));
    n2 = size(A,1)/ncFeature;
    for i = 1:n2
        Cc(:,i+n1) = A((ncFeature*(i-1)+1):ncFeature*i,1);
        D(:,i+n1) = B((ntFeature*(i-1)+1):ntFeature*i,1);
        TrainY2(1,i+n1) = -1;
    end
    TrainX2 = [Cc;D];
    clear Cc;
    clear D;
    % load source domain 3
    A = textread(strcat('data/img/13_color36.txt'));
    B = textread(strcat('data/img/13_texture51.txt'));
    n1 = size(A,1)/ncFeature;
    for i = 1:n1
        Cc(:,i) = A((ncFeature*(i-1)+1):ncFeature*i,1);
        D(:,i) = B((ntFeature*(i-1)+1):ntFeature*i,1);
        TrainY3(1,i) = 1;
    end
    A = textread(strcat('data/img/17_color36.txt'));
    B = textread(strcat('data/img/17_texture51.txt'));
    n2 = size(A,1)/ncFeature;
    for i = 1:n2
        Cc(:,i+n1) = A((ncFeature*(i-1)+1):ncFeature*i,1);
        D(:,i+n1) = B((ntFeature*(i-1)+1):ntFeature*i,1);
        TrainY3(1,i+n1) = -1;
    end
    TrainX3 = [Cc;D];
    clear Cc;
    clear D;
    % load target domain
    A = textread(strcat('data/img/14_color36.txt'));
    B = textread(strcat('data/img/14_texture51.txt'));
    n1 = size(A,1)/ncFeature;
    for i = 1:n1
        Cc(:,i) = A((ncFeature*(i-1)+1):ncFeature*i,1);
        D(:,i) = B((ntFeature*(i-1)+1):ntFeature*i,1);
        TestY(1,i) = 1;
    end
    A = textread(strcat('data/img/18_color36.txt'));
    B = textread(strcat('data/img/18_texture51.txt'));
    n2 = size(A,1)/ncFeature;
    for i = 1:n2
        Cc(:,i+n1) = A((ncFeature*(i-1)+1):ncFeature*i,1);
        D(:,i+n1) = B((ntFeature*(i-1)+1):ntFeature*i,1);
        TestY(1,i+n1) = -1;
    end
    TestX = [Cc;D];

    clear A B Cc D;

    %% normalization
    column = size(TrainX1,2);
    mode_TrainX = sqrt(sum(TrainX1.*TrainX1,1));
    for i = 1 : column
        TrainX1(:,i) = TrainX1(:,i)/mode_TrainX(1,i);
    end
    column = size(TrainX2,2);
    mode_TrainX = sqrt(sum(TrainX2.*TrainX2,1));
    for i = 1 : column
        TrainX2(:,i) = TrainX2(:,i)/mode_TrainX(1,i);
    end
    column = size(TrainX3,2);
    mode_TrainX = sqrt(sum(TrainX3.*TrainX3,1));
    for i = 1 : column
        TrainX3(:,i) = TrainX3(:,i)/mode_TrainX(1,i);
    end
    TrainData{1,1} = TrainX1;
    TrainLabel{1,1} = TrainY1;
    TrainData{1,2} = TrainX2;
    TrainLabel{1,2} = TrainY2;
    TrainData{1,3} = TrainX3;
    TrainLabel{1,3} = TrainY3;

    column = size(TestX,2);
    mode_TestX = sqrt(sum(TestX.*TestX,1));
    for i = 1 : column
        TestX(:,i) = TestX(:,i)/mode_TestX(1,i);
    end
    TestData{1,1} = TestX;
    TestLabel{1,1} = TestY;
    save inputData.mat TrainData TrainLabel TestData TestLabel
end


%finds best source and distance to the best source
% if distance is negative, the best source cannot be found (for example, because the propagation was stopped before it reached this point)
% Danil Kirsanov, 09/2007

function [source_id, distance] = geodesic_best_source(algorithm, destination)

global geodesic_library;

if nargin == 2
    d = geodesic_convert_surface_points({destination});

    tmp = 1;
    [source_id, tmp1, distance] = calllib(geodesic_library, 'distance_and_source', algorithm.id, d, tmp);
    source_id = source_id + 1;
else                                    %return distances and sources for all vertices
    tmp = libpointer('doublePtrPtr');
%     tmp = libpointer('int32PtrPtr');
     tmp1 = libpointer('longPtrPtr');
%  tmp1 = libpointer('doublePtr');

    [num_vertices, d, s] = calllib(geodesic_library, 'distance_and_source_for_all_vertices', algorithm.id, tmp, tmp1);

    setdatatype(d, 'doublePtr', num_vertices);
    distance = d.Value;
    setdatatype(s, 'longPtr', num_vertices);
    source_id = s.Value + 1;
end


function test2 (nmat)
%TEST2 test for BTF
% Requires CSparse and UFget
% Example:
%   test2
% See also btf, maxtrans, strongcomp, dmperm, UFget,
%   test1, test2, test3, test4, test5.

% Copyright 2007, Timothy A. Davis, University of Florida

index = UFget ;
f = find (index.nrows == index.ncols) ;

% too much time:
skip = [1514 1297 1876 1301] ;
f = setdiff (f, skip) ;

[ignore i] = sort (index.nnz (f)) ;
f = f (i) ;

if (nargin < 1)
    nmat = 1000 ;
end
nmat = min (nmat, length (f)) ;
f = f (1:nmat) ;

T0 = zeros (nmat,1) ;
T1 = zeros (nmat,1) ;
Anz = zeros (nmat,1) ;
figure (1) ;
clf
MN = zeros (nmat, 2) ;
Nzdiag = zeros (nmat,1) ;

% warmup
p = maxtrans (sparse (1)) ;             %#ok
p = btf (sparse (1)) ;                  %#ok
p = cs_dmperm (sparse (1)) ;            %#ok
a = cs_transpose (sparse (1)) ;         %#ok

h = waitbar (0, 'BTF test 2 of 6') ;

try
    for k = 1:nmat

        Prob = UFget (f (k), index) ;
        A = Prob.A ;

        waitbar (k/nmat, h) ;

        Nzdiag (k) = nnz (diag (A)) ;

        [m n] = size (A) ;
        Anz (k) = nnz (A) ;
        MN (k,:) = [m n] ;

        tic
        [p,q,r] = btf (A) ;
        t0 = toc ;
        s0 = sum (q > 0) ;
        T0 (k) = max (1e-9, t0) ;

        tic
        [p2,q2,r2] = cs_dmperm (A) ;
        t1 = toc ;
        s1 = sum (dmperm (A) > 0) ;
        T1 (k) = max (1e-9, t1) ;

        fprintf ('%4d btf %10.6f cs_dmperm %10.6f', f(k), t0, t1) ;
        if (t1 ~= 0)
            fprintf (' rel: %8.4f', t0 / t1) ;
        end
        fprintf ('\n') ;

        if (s0 ~= s1)
            error ('!') ;
        end

        C = A (p, abs (q)) ;
        subplot (1,2,1) ;
        cspy (C) ;
        z = find (q < 0) ;
        zd = nnz (diag (C (z,z))) ;
        if (zd > 0)
            error ('?') ;
        end

        minnz = Anz (1) ;
        maxnz = nnz (A) ;

        subplot (1,2,2) ;
        loglog (Anz (1:k), T0 (1:k) ./ T1 (1:k), ...
            'o', [minnz maxnz], [1 1], 'r-') ;
        drawnow

        clear C A Prob
    end

catch
    % out-of-memory is OK, other errors are not
    disp (lasterr) ;
    if (isempty (strfind (lasterr, 'Out of memory')))
        error (lasterr) ;                                                   %#ok
    else
        fprintf ('test terminated early, but otherwise OK\n') ;
    end
end

close (h) ;


%compute velang_head
function [data,units]=compute_velanghead(trx,n)
larvae=trx.exp2flies{n};
numlarvae=numel(larvae);
velanghead=cell(1,numlarvae);
for i=1:numlarvae
    larva=larvae(i);
    velanghead{1,i}=bsxfun(@atan2,trx(larva).dyhead_mm,trx(larva).dxhead_mm);
end

units=parseunits('rad');
data=velanghead;


%
% SCRIPT TO TEST THE KINEMATICS OF THE 3RRR robot
%
% Copyright (C) 2012, by Arturo Gil Aparicio
%
% This file is part of ARTE (A Robotics Toolbox for Education).
%
% ARTE is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% ARTE 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with ARTE.  If not, see <http://www.gnu.org/licenses/>.

close all

%load the robot
%the robot is represented (interiorly) by three planar 2dof arms
robot=load_robot('example','3RRR');

adjust_view(robot)

%init T
T=eye(4);
%Represent a final point in space that will be achieved by the end effector
%P=[xA, yA]=[1.5 1.5]
T(1,4)=1.2;
T(2,4)=1.0;
%orientation
phi=pi/3;
T(1,1)=cos(phi)
T(2,1)=sin(phi)

%find 8 solutions for the INVERSE KINEMATIC in position
q=inversekinematic(robot, T)

%plot every solution
drawrobot3d(robot, q(:,1)), pause(2);
drawrobot3d(robot, q(:,2)), pause(2);
drawrobot3d(robot, q(:,3)), pause(2);
drawrobot3d(robot, q(:,4)), pause(2);
drawrobot3d(robot, q(:,5)), pause(2);
drawrobot3d(robot, q(:,6)), pause(2);
drawrobot3d(robot, q(:,7)), pause(2);
drawrobot3d(robot, q(:,8)), pause(2);

%Make a line in space with a variation in the angle phi
x=linspace(1,1.4,50);
y=linspace(1.1,1.15,50);
th=linspace(0,pi/3,50);
Q=[];
for i=1:length(x),
    T(1,4)=x(i);
    T(2,4)=y(i);
    %orientation

    T(1,1)=cos(th(i));
    T(2,1)=sin(th(i))

    q=inversekinematic(robot, T);

    drawrobot3d(robot, q(:,1), 1) %noclear activated
    drawrobot3d(robot, q(:,1)) %noclear deactivated
    pause(0.1)
end

%TEST NOW the directkinematic function
T(1,4)=1.0;
T(2,4)=1.0;
%orientation
phi=pi/3;
T(1,1)=cos(phi)
T(2,1)=sin(phi)

%find 8 solutions for the INVERSE KINEMATIC in position
q=inversekinematic(robot, T)

%now, for the first solution
T=directkinematic(robot, [q(1,1) q(3,1) q(5,1)])
%caution: there may exist less than 8 possible solutions
for i=1:8,
    drawrobot3d(robot, q(:,i))
    % 1 and 3 correspond to the joint variables of the robot
    T=directkinematic(robot, [q(1,i) q(3,i) q(5,i)])
    pause(2);
    close all
end


function [mResult, fMls, fMc, fMu, fSigma, mDatPredBest, vPredBest] = plot_McEMR(mCatalog, fBinning)
% Same as calc_McCdfnormal with plotting the fitting steps and the final result
%
% [mResult, fMls, fMc, fMu, fSigma, mDatPredBest, vPredBest] = plot_McEMR(mCatalog, fBinning);
% -----------------------------------------------------------------------------------------------------
%
% Incoming variables:
% mCatalog   : EQ catalog
% fBinning   : Binning interval, usually 0.1
%
% Outgoing variables:
% mResult     : Solution matrix including
%               vProbability: maximum likelihood score
%               vMc         : Mc values
%               vX_res      : mu (of normal CDF), sigma (of normal CDF), residuum, exitflag
%               vNmaxBest   : Number of events in lowest magnitude bin considered complete
%               vABValue    : a and b-value
% fMls       : likelihood score --> best Mc
% fMc        : Best estimated magnitude of completeness
% mDatPredBest   : Matrix of non-cumulative FMD [Prediction, magnitudes, original distribution]
% vPredBest      : Matrix of non-cumulative FMD below Mc [magnitude, prediction, uncertainty of prediction]
%
% J. Woessner: jochen.woessner@sed.ethz.ch
% updated: 29.09.04

% Initialize
vProbability = [];
vMc = [];
vABValue =[];
mFitRes = [];
vX_res = [];
vNCumTmp = [];
mDataPred = [];
vPredBest = [];
vDeltaBest = [];
vX_res = [];
vNmaxBest = [];
mResult=[];
mDatPredBest = [];

% Determine exact time period
fPeriod1 = max(mCatalog.Date) - min(mCatalog.Date);

% Determine max. and min. magnitude
fMaxMag = ceil(10 * max(mCatalog.Magnitude)) / 10;

% Set starting value for Mc loop and LSQ fitting procedure
fMcTry= calc_Mc(mCatalog, McMethods.MaxCurvature);
fSmu = abs(fMcTry/2);
fSSigma = abs(fMcTry/4);
if (fSmu > 1)
    fSmu = fMcTry/10;
    fSSigma = fMcTry/20;
end
fMcBound = fMcTry;

% Calculate FMD for original catalog
[vFMDorg, vNonCFMDorg, fmdbins] = calc_FMD(mCatalog.Magnitude);
% convert answer back to this file's expectations...
vFMDorg = [fmdbins'; vFMDorg'] % as rows
vNonCFMDorg = [fmdbins'; vNonCFMDorg'];

fMinMag = min(vNonCFMDorg(1,:));

%% Shift to positive values
% if fMinMag ~= 0
%     fMcBound = fMcTry-fMinMag;
% end
% Loop over Mc-values
for fMc = fMcBound-0.4:0.1:fMcBound+0.8
    fMc = round(fMc, -1);
    vFMD = vFMDorg;
    vNonCFMD = vNonCFMDorg;
    vNonCFMD = fliplr(vNonCFMD);
    % Select magnitudes to calculate b- anda-value
    vSel = mCatalog.Magnitude > fMc-fBinning/2;
    if sum(vSel) >= 20
        [ fBValue, fStdDev, fAValue] =  calc_bmemag(mCatalog.Magnitude(vSel), fBinning);
        % Normalize to time period
        vFMD(2,:) = vFMD(2,:)./fPeriod1; % ceil taken out
        vNonCFMD(2,:) = vNonCFMD(2,:)./fPeriod1; % ceil removed
        % Compute quantity of earthquakes by power law
        fMaxMagFMD = max(vNonCFMD(1,:));
        fMinMagFMD = min(vNonCFMD(1,:));
        vMstep = [fMinMagFMD:0.1:fMaxMagFMD];
        vNCum = 10.^(fAValue-fBValue.*vMstep); % Cumulative number

        % Compute non-cumulative numbers vN
        fNCumTmp = 10^(fAValue-fBValue*(fMaxMagFMD+0.1));
        vNCumTmp  = [vNCum fNCumTmp ];
        vN = abs(diff(vNCumTmp));

        % Normalize vN
        vN = vN./fPeriod1;
        % Data selection
        % mData = Non-cumulative FMD values from GR-law and original data
        mData = [vN' vNonCFMD'];
        vSel = (mData(:,2) >= fMc);
        mDataTest = mData(~vSel,:);
        mDataTmp = mData.subset(vSel);
%         % Check for zeros in observed data
        vSelCheck = (mDataTest(:,3) == 0);
        mDataTest = mDataTest(~vSelCheck,:);
        % Choices of normalization
        fNmax = mDataTmp(1,3); % Frequency of events in Mc bin
        %fNmax = max(mDataTest(:,3));  % Use maximum frequency of events in bins below Mc
        %fNmax = mDataTest(length(mDataTest(:,1)),3); % Use frequency of events at bin Mc-0.1 -> best fit
        if (~isempty(isempty(fNmax)) &&  ~isnan(fNmax) & fNmax ~= 0 & length(mDataTest(:,1)) > 4)
            mDataTest(:,3) = mDataTest(:,3)/fNmax; % Normalize datavalues for fitting with CDF
            % Move to M=0 to fit with lsq-algorithm
            fMinMagTmp = min(mDataTest(:,2));
            mDataTest(:,2) = mDataTest(:,2)-fMinMagTmp;
            % Curve fitting: Non cumulative part below Mc
            options = optimset;
            %options = optimset('Display','off','Tolfun',1e-7,'TolX',0.0001,'MaxFunEvals', 100000,'MaxIter',10000);
            options = optimset('Display','off','Tolfun',1e-5,'TolX',0.001,'MaxFunEvals', 1000,'MaxIter',1000);
            [vX, resnorm, resid, exitflag, output, lambda, jacobian]=lsqcurvefit(@calc_normalCDF,[fSmu  fSSigma], mDataTest(:,2), mDataTest(:,3),[],[],options);
            mDataTest(:,1) = normcdf(mDataTest(:,2), vX(1), vX(2))*fNmax;
            if (length(mDataTest(:,2)) > length(vX(1,:)))
                %% Confidence interval determination
                % vPred : Predicted values of lognormal function
                % vPred+-delta : 95% confidence level of true values
                [vPred,delta] = nlpredci(@calc_normalCDF,mDataTest(:,2),vX, resid, jacobian);
            else
                vPred = NaN;
                delta = NaN;
            end % END: This section is due for errors produced with datasets less long than amount of parameters in vX
            % Results of fitting procedure
            mFitRes = [mFitRes; vX resnorm exitflag];
            % Move back to original magnitudes
            mDataTest(:,2) = mDataTest(:,2)+fMinMagTmp;
            % Set data together
            mDataTest(:,3) = mDataTest(:,3)*fNmax;
            mDataPred = [mDataTest; mDataTmp];
            % Denormalize to calculate probabilities
            mDataPred(:,1) = round(mDataPred(:,1).*fPeriod1);
            mDataPred(:,3) = mDataPred(:,3).*fPeriod1;
            vProb_ = calc_log10poisspdf2(mDataPred(:,3), mDataPred(:,1)); % Non-cumulative

            % Sum the probabilities
            fProbability = (-1) * sum(vProb_);
            vProbability = [vProbability; fProbability];
            % Move magnitude back
            mDataPred(:,2) = mDataPred(:,2)+fMinMag;
            vMc = [vMc; fMc];
            vABValue = [vABValue; fAValue fBValue];

            % Keep values
            vDeltaBest = [vDeltaBest; delta];
            vX_res = [vX_res; vX resnorm exitflag];
            vNmaxBest = [vNmaxBest; fNmax];

            % Keep best fitting model
            if (fProbability == min(vProbability))
                vDeltaBest = delta;
                vPredBest = [mDataTest(:,2) vPred*fNmax*fPeriod1 delta*fNmax*fPeriod1]; % Gives back uncertainty
                %fMc+fMinMag : Test procedure
                mDatPredBest = [mDataPred];
           end
        else
            %disp('Not enough data');
            % Setting values
            fProbability = NaN;
            fMc = NaN;
            vX(1) = NaN;
            vX(2) = NaN;
            resnorm = NaN;
            exitflag = NaN;
            delta = NaN;
            vPred = [NaN NaN NaN];
            fNmax = NaN;
            fAValue = NaN;
            fBValue = NaN;
            vProbability = [vProbability; fProbability];
            vMc = [vMc; fMc];
            vX_res = [vX_res; vX resnorm exitflag];
%             vDeltaBest = [vDeltaBest; NaN];
%             vPredBest = [vPredBest; NaN NaN NaN];
            vNmaxBest = [vNmaxBest; fNmax];
            vABValue = [vABValue; fAValue fBValue];
        end
    end

    % Clear variables
    vNCumTmp = [];
    mModelDat = [];
    vNCum = [];
    vSel = [];
    mDataTest = [];
    mDataPred = [];
end % END of FOR fMc
% Result matrix
mResult = [mResult; vProbability vMc vX_res vNmaxBest vABValue];

% Find best estimate, excluding the case of mResult all NAN
if  ~isempty(min(mResult))
    if ~isnan(min(mResult(:,1)))
        vSel = find(min(mResult(:,1)) == mResult(:,1));
        fMc = min(mResult(vSel,2));
        fMls = min(mResult(vSel,1));
        fMu = min(mResult(vSel,3));
        fSigma = min(mResult(vSel,4));
        fAvalue = min(mResult(vSel,8));
        fBvalue = min(mResult(vSel,9));
    else
        fMc = NaN;
        fMls = NaN;
        fMu = NaN;
        fSigma = NaN;
        fAvalue = NaN;
        fBvalue = NaN;
    end
else
    fMc = NaN;
    fMls = NaN;
    fMu = NaN;
    fSigma = NaN;
    fAvalue = NaN;
    fBvalue = NaN;
end

try % Try catch block used as mDatPreBest not always calculated
    % Reconstruct vector of magnitudes from model for Period 1
    vMag = [];
    mModelFMD = [round(mDatPredBest(:,1)) mDatPredBest(:,2)];
    vSel = (mModelFMD(:,1) ~= 0); % Remove bins with zero frequency of zero events
    mData = mModelFMD(vSel,:);
    for nCnt=1:length(mData(:,1))
        fM = repmat(mData(nCnt,2),mData(nCnt,1),1);
        vMag = [vMag; fM];
    end
    % Calculate KS-Test
    [bH,fPval,fKsstat] = kstest2(roundn(mCatalog.Magnitude,-1),roundn(vMag,-1),0.05,0)
catch
    bH = NaN;
    fPval = NaN;
    fKsstat = NaN;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Plot result

% Plot best fitting CDF vs. magnitude
figure_w_normalized_uicontrolunits('tag','best_cdfit','Name','CDF fit','Units','normalized','Nextplot','add',...
                    'Numbertitle','off','visible','on');
p1=plot(mDatPredBest(:,2), mDatPredBest(:,3),'Marker','d','MarkerEdgeColor',[0 0 0],'MarkerFaceColor',[0.4 0.4 0.4],'Markersize',8,'Linewidth',2,'Linestyle','none');
set(gca,'NextPlot','add');
p2=plot(mDatPredBest(:,2),mDatPredBest(:,1),'Marker','o','MarkerEdgeColor',[0.25 0.25 0.25],'MarkerFaceColor',[0.75 0.75 0.75],'Markersize',8,'Linewidth',2,'Linestyle','none');
%sTitlestr = ['mu = ' num2str(fMu) ', sigma = ' num2str(fSigma)];
%title(sTitlestr)
p3=plot(vPredBest(:,1),vPredBest(:,2),'-','Color',[0.2 0.2 0.2],'Linewidth',2);
p4=plot(vPredBest(:,1),vPredBest(:,2)+vPredBest(:,3),'--','Color',[0.2 0.2 0.2],'Linewidth',2);
plot(vPredBest(:,1),vPredBest(:,2)-vPredBest(:,3),'--','Color',[0.2 0.2 0.2],'Linewidth',2);
xlabel('Magnitude','FontSize',14,'FontWeight','bold');
ylabel('Number of events','FontSize',14,'FontWeight','bold');
xlim = ([min(mDatPredBest(:,2)) max(mDatPredBest(:,2))]);
ylim = ([0 max(mDatPredBest(:))]);
hl1=legend([p1,p2,p3,p4],'Noncum. FMD','Noncum. model FMD ','Model','Model uncertainty');
set(hl1,'FontWeight','bold','FontSize',12')
set(gca,'visible','on','FontSize',12,'FontWeight','bold','LineWidth',2,'Box','on');
set(gca,'NextPlot','replace');

% Plot Non-/Cumulative distribution, original and predicted
figure_w_normalized_uicontrolunits('tag','ncumdist','Name','Best model','Units','normalized','Nextplot','add',...
                    'Numbertitle','off','visible','on');
p1 = semilogy(vNonCFMDorg(1,:)', vNonCFMDorg(2,:)', 'Marker','d','MarkerEdgeColor',[0 0 0],'MarkerFaceColor',[0.4 0.4 0.4],'Markersize',8,'Linewidth',2,'Linestyle','none');
set(gca,'NextPlot','add');
p2 = semilogy(vFMDorg(1,:)', vFMDorg(2,:)', 'Marker','^','MarkerEdgeColor',[0 0 0],'MarkerFaceColor',[0.75 0.75 0.75],'Markersize',8,'Linewidth',2,'Linestyle','none');
%p2=semilogy(vCFMD(1,:)', vNBest.*fPeriod1, '*',
p3=semilogy(mDatPredBest(:,2),mDatPredBest(:,1),'Marker','o','MarkerEdgeColor',[0.25 0.25 0.25],'MarkerFaceColor',[0.75 0.75 0.75],'Markersize',8,'Linewidth',2,'Linestyle','none');
%fBvalue = mResult(vSel,9)
%fAValue = mResult(vSel,8)
vPoly = [-1*fBvalue fAvalue]
vMagnitudes = [0:0.01:max(mDatPredBest(:,2))];
fBFunc = 10.^(polyval(vPoly, vMagnitudes));
p4 = semilogy(vMagnitudes, fBFunc,'Linewidth',3,'Linestyle','--','Color',[0.4 0.4 0.4])
xlim = ([min(mDatPredBest(:,2)) max(mDatPredBest(:,2))]);
ylim = ([0 100000]);
%sTitlestr = ['Mc = ' num2str(fMc) ' using Normal CDF fitting'];
%title(sTitlestr)
sText1 = ['KS-Test: H = ' num2str(bH)];
sText2 = ['Mc(EMR) = ' num2str(fMc)];
hT1 = text(max(vFMDorg(1,:))-1, max(vFMDorg(2,:))*0.6,sText1);
hT2 = text(max(vFMDorg(1,:))-1, max(vFMDorg(2,:))*0.4,sText2);
set(hT1,'FontSize',12,'FontWeight','bold');
set(hT2,'FontSize',12,'FontWeight','bold');
xlabel('Magnitude','FontSize',14,'FontWeight','bold');
ylabel('Number of events','FontSize',14,'FontWeight','bold');
hl1=legend([p1 p2 p3 p4],'Noncum. FMD','Cum. FMD','Noncum. model FMD','Cum. model FMD');
set(hl1,'FontWeight','bold','FontSize',12')
set(gca,'visible','on','FontSize',12,'FontWeight','bold','LineWidth',2,'Box','on');

%%%% Plotting the likelihood scores
figure
%vSel2 = (vMc >= 0.6 & vMc<= 2);
%vMc = vMc(vSel2);
%vProbability = vProbability(vSel2);
plot(vMc, vProbability,'Marker','s','MarkerFaceColor',[0.5 0.5 0.5],'MarkerEdgeColor',[0 0 0],'Markersize',10','Linewidth',2,'Color',[0 0 0],'visible','on');%sTitlestr = ['mu = ' num2str(fMu) ', sigma = ' num2str(fSigma)];
hl2=legend('MLE');
set(hl2,'FontWeight','bold','FontSize',12');
xlim = ([min(mDatPredBest(:,2)) max(mDatPredBest(:,2))]);
set(gca,'visible','on','FontSize',12,'FontWeight','bold','LineWidth',2,'Box','on');
xlabel('Magnitude','FontSize',14,'FontWeight','bold');
ylabel('Likelihood','FontSize',14,'FontWeight','bold');


g=-50;
Q=1;
f=10e3;

[x, Fs] = wavread('tea_16bit_48kHz_short.wav');

[b a]=get_high_shelving_filter(g,Q,f,Fs);

y=filter(b,a,x);
sound(y,Fs);


classdef FLEA < ALGORITHM
% <multi/many> <real> <large/none>
% Fast sampling based evolutionary algorithm

%------------------------------- Reference --------------------------------
% L. Li, C. He, R. Cheng, H. Li, L. Pan, and Y. Jin, A fast sampling based
% evolutionary algorithm for million-dimensional multiobjective
% optimization, Swarm and Evolutionary Computation, 2022, 75: 101181.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

% This function is written by Cheng He & Lianghao Li

    methods
        function main(Algorithm,Problem)
            %% Parameter setting
            Population = Problem.Initialization();
            RN         = ceil(sqrt(Problem.N));	% Number of reference solutions

            %% Optimization
            while Algorithm.NotTerminated(Population)
                FrontNo          = NDSort(Population.objs,Population.cons,inf);
                [Ref,Population] = RefSelection(Problem,Population,RN,(Problem.FE/Problem.maxFE)^2);	% APD_Based_Selection
                [id_obj,id_dec]  = Neighborhood_Association(Population,Ref);
                cm               = 0.1*floor(10*(Problem.FE/Problem.maxFE));	% Ratio of convergence population
                dirV_obj         = Direction_Calculation(Problem,Population,Ref,id_obj,FrontNo);
                dirV_dec         = Direction_Calculation(Problem,Population,Ref,id_dec,FrontNo);
                Offspring        = Reproduction(Problem,Ref,cm,dirV_obj,dirV_dec);
                [Population,~,~] = EnvironmentalSelection([Population,Offspring],Problem.N);
            end
        end
    end
end

function [Ref,Population] = RefSelection(Problem,Population,RN,theta)
% The environmental selection of RVEA
    [V,~] = UniformPoint(RN,Problem.M);
    V(1:RN,:) = V.*repmat(max(Population.objs,[],1)-min(Population.objs,[],1)+eps,size(V,1),1);
    PopObj = Population.objs;
    [N,M]  = size(PopObj);
    NV     = size(V,1);
    PopObj = PopObj - repmat(min(PopObj,[],1),N,1);
    cosine = 1 - pdist2(V,V,'cosine');
    cosine(logical(eye(length(cosine)))) = 0;
    gamma  = min(acos(cosine),[],2);

    %% Associate each solution to a reference vector
    Angle  = acos(1-pdist2(PopObj,V,'cosine'));
    Next   = zeros(1,NV);
    for i  = 1 : NV
        APD = (1+M*theta*Angle(:,i)/gamma(i)).*sqrt(sum(PopObj.^2,2));
        [~,Next(i)] = min(APD);
        Angle(Next(i),:) = inf;
    end
    % Population for next generation
    Ref    = Population(Next);
    [~,order1] = sort(Ref.objs);
    Ref    = Ref(order1(:,1));
end

function [OCid,DCid] = Neighborhood_Association(Population,Ref)
    % Neighborhood in objective space
    RefObj   = Ref.objs; PopObj = Population.objs;
    Distance_Obj   = pdist2(RefObj,PopObj,'chebychev');
    [~,OCid] = min(Distance_Obj);
    % Neighborhood in decision space
    RefDec = Ref.decs; PopDec = Population.decs;
    Distance_Dec = pdist2(RefDec,PopDec,'chebychev');
    [~,DCid] = min(Distance_Dec);
end

function dirV = Direction_Calculation(Problem,Population,Ref,id,FrontNo)
    %Direction of convergence
    RefDec   = Ref.decs;
    RN = length(Ref);
    dirV = zeros(size(RefDec));
    for i = 1:RN
        Neighbor = Population(id==i);
        F_Neighbor = FrontNo(id==i);
        if ~isempty(Neighbor) && min(F_Neighbor)>1
            dirV(i,:) = mean(Neighbor(F_Neighbor==min(F_Neighbor)).decs,1)-RefDec(i,:);
        elseif rand>0.5
            dirV(i,:)  = (RefDec(i,:)-Problem.lower)./Problem.D;
        else
            dirV(i,:)  = (Problem.upper-RefDec(i,:))./Problem.D;
        end
    end
end

function Offspring = Reproduction(Problem,Ref,cm,dirV_obj,dirV_dec)
    RefDec   = Ref.decs;
    RN = length(Ref);
    CN = ceil(cm*0.5*Problem.N/RN); %Size of convergence population
    DN = Problem.N-CN*RN*2; %Size of diversity population
    OffDec = zeros(CN*RN*2+DN,Problem.D);
    for i = 1:RN
        mu = repmat(RefDec(i,:),CN,1);
        %% Convergence offsprings
        OffDec(1+(i-1)*CN:i*CN,:) = mu+repmat(randn(1,CN)',1,Problem.D).*repmat(dirV_obj(i,:),CN,1);
        OffDec(CN*RN+1+(i-1)*CN:CN*RN+i*CN,:) = mu+repmat(randn(1,CN)',1,Problem.D).*repmat(dirV_dec(i,:),CN,1);
    end
    %% Diversity offsprings
    x_1 = randi(RN,1,DN);x_2 = randi(RN,1,DN);
    dirV  = Ref(x_1).decs-Ref(x_2).decs;
    OffDec(Problem.N-DN+1:end,:) = Ref(x_1).decs + randn(1,DN)'.*dirV;
    %% Evaluation
    Offspring = Problem.Evaluation(OffDec);
end

function [Population,FrontNo,CrowdDis] = EnvironmentalSelection(Population,N)
% The environmental selection of NSGA-II
    %% Non-dominated sorting
    [FrontNo,MaxFNo] = NDSort(Population.objs,Population.cons,N);
    Next = FrontNo < MaxFNo;

    %% Calculate the crowding distance of each solution
    CrowdDis = CrowdingDistance(Population.objs,FrontNo);

    %% Select the solutions in the last front based on their crowding distances
    Last     = find(FrontNo==MaxFNo);
    [~,Rank] = sort(CrowdDis(Last),'descend');
    Next(Last(Rank(1:N-sum(Next)))) = true;

    %% Population for next generation
    Population = Population(Next);
    FrontNo    = FrontNo(Next);
    CrowdDis   = CrowdDis(Next);
end


function gf=gradloglikGaP(x, varargin)
% f=loglikGaP(x, varargin)
% complete log likellihood of the GaP model
% Vxt = varargin{1};      %data
% sigpsf = varargin{2};  %std deviation of the PSF gaussian approx
% alpha = varargin{3}; %parameters of the Gamma prior on the blinking
% beta = varargin{4}; %parameters of the Gamma prior on the blinking
% peval = varargin{5}; %parameters
% x(1:end-2*peval.ncomp) is Hkt

Vxt = varargin{1};      %data
sigpsf = varargin{2};  %std deviation of the PSF gaussian approx
alpha = varargin{3}; %parameters of the Gamma prior on the blinking
beta = varargin{4}; %parameters of the Gamma prior on the blinking
peval = varargin{5}; %parameters

% % % Hkt_linear=x(1:end-peval.ncomp*2); % intensities
% % % cx=x(end-peval.ncomp*2+1:end-peval.ncomp); %x-coordinates of the centers
% % % cy=x(end-peval.ncomp+1:end); % y-coordinates of the centers
% % %
Hkt_linear=x; % intensities
cx=varargin{6};
cy=varargin{7};
% % %

sigpsf_vec=repmat(sigpsf,peval.ncomp,1); %all psfs same sigma
cxy_vec=[cx'+.5, cy'+.5];
a_vec=1./(sigpsf_vec*2*pi); % all normalised to 1

Hkt=reshape(Hkt_linear, peval.ncomp, peval.nt);
% generate PSFs from given parameters:
Wxkpix=gauss2dmultislice([peval.nx, peval.ny, peval.ncomp], cxy_vec, sigpsf_vec, a_vec);
Wxkpix=normalizePSF(Wxkpix); %normalize PSFs to 1
Wxk=reshape(Wxkpix,peval.nx*peval.ny, peval.ncomp);
% add the background component (just for muttiplication - in the gradient it should not matter):
[Wxkbg,Hktbg]=addbg(Wxk, Hkt, peval.bg);
P=Wxkbg*Hktbg; %current approximation

xxvc = lineargrad([peval.nx, peval.ny, peval.ncomp], cx, 'xx'); %linera grasdient shifted by cx
yyvc = lineargrad([peval.nx, peval.ny, peval.ncomp], cy, 'yy');

% dW/dcx:
Wxtcx=1/sigpsf^2*xxvc.*Wxk;
% dW/dcy:
Wxtcy=1/sigpsf^2*yyvc.*Wxk;

% d(log(L))/dHkt:
% % % gfHkt=(alpha-1)*1./Hkt - 1/beta + Wxk'*(Vxt./P-eye(peval.nx*peval.ny,peval.nt));
% % % gfHkt= Wxk'*(Vxt./P-eye(peval.nx*peval.ny,peval.nt));
gfHkt= Wxk'*(Vxt./P)-1; %without background
% d(log(L))/dcx:
gfcx=diag(Wxtcx'*(Vxt./P)*Hkt');
% d(log(L))/dcy:
gfcy=diag(Wxtcy'*(Vxt./P)*Hkt');

% % % gf = [reshape(gfHkt',1,peval.nt*peval.ncomp), gfcx', gfcy'];
% gf = [reshape(gfHkt(1:peval.ncomp, :),1,peval.nt*peval.ncomp)];
gf = [reshape(gfHkt,1,peval.nt*peval.ncomp)];

end
function Wnorm=normalizePSF(W)
sw=size(W);
Wr=reshape(W, sw(1)*sw(2),sw(3));
q=squeeze(sum(Wr,1));
Wrnorm=Wr./repmat(q,sw(1)*sw(2),1);
Wnorm=reshape(Wrnorm,sw(1), sw(2), sw(3));
end
function xxvc = lineargrad(sizevec, cx, dir)
switch dir
    case 'xx'
        xxp=double(xx(sizevec, 'true')); %linear function - pixels
    case 'yy'
        xxp=double(yy(sizevec, 'true')); %linear function - pixels
    otherwise
        error('Wrong dir')
end

xxv=reshape(xxp,sizevec(1)*sizevec(2),sizevec(3)); %linear function - vector
xxvc=xxv-repmat(cx,sizevec(1)*sizevec(2),1);
% xxp=double(xx([peval.nx, peval.ny, peval.ncomp], 'true')); %linear function - pixels
%yyp=double(yy([peval.nx, peval.ny, peval.ncomp], 'true'));
% xxv=reshape(xxp,peval.nx*peval.ny,peval.ncomp); %linear function - vector
%yyv=reshape(yyp,peval.nx*peval.ny,peval.ncomp);
% xxvc=xxv-repmat(cx,peval.ncomp,1);
%yyvc=yyv-repmat(cy,peval.ncomp,1);
end


function [res,FLAG,RELRES,ITER,RESVEC,LSVEC] = cgNUSPIRiT(kData, x0, NUFFTOP, GOP, nIter, lambda)

% Implementation of image-domain SPIRiT reconstruction from arbitrary
% k-space. The function is based on Jeff Fessler's nufft code and LSQR
%
% Inputs:
%       kData   - k-space data matrix it is 3D corresponding to [readout,interleaves,coils]
%       x0      - Initial estimate of the coil images
%       NUFFTOP - nufft operator (see @NUFFT class)
%       GOP     - SPIRiT Operator (See @SPIRiT)
%       nIter   - number of LSQR iterations
%       lambda  - ratio between data consistency and SPIRiT consistency (1 is recommended)
%
% Outputs:
%       res - reconstructed coil images
%       FLAG,RELRES,ITER,RESVEC,LSVEC - See LSQR documentation
%
% See demo_nuSPIRiT for a demo on how to use this function.
%
% (c) Michael Lustig 2006, modified 2010

N = prod(size(x0));
imSize = size(x0);
dataSize = [size(kData)];

b = [kData(:) ; zeros(prod(imSize),1)];
[res,FLAG,RELRES,ITER,RESVEC,LSVEC] = lsqr(@(x,tflag)afun(x,NUFFTOP,GOP,dataSize, imSize,lambda,tflag), b, [], nIter,speye(N,N),speye(N,N), x0(:));

res = reshape(res,imSize);

function [y, tflag] = afun(x,NUFFTOP,GOP,dataSize,imSize,lambda,tflag)

if strcmp(tflag,'transp')
   x1 = reshape(x(1:prod(dataSize)),dataSize);
   x2 = reshape(x(prod(dataSize)+1:end),imSize);
   y = NUFFTOP'.*x1 + lambda*(GOP'*x2);
   y = y(:);
else

    x = reshape(x,imSize);
    y1 = NUFFTOP.*x;
    y2 = GOP*x;
    y = [y1(:); lambda*y2(:)];
end


function Goal_Idx = Select_Goal_Point(State,Params,Trajectory)

th = State(3);

if strcmp(Params.Sim.Direction,'reverse')
    Current_Direction = -[-sin(th); cos(th)];
    Dir = 2;
else
    Current_Direction = [-sin(th); cos(th)];
    Dir = 1;
end

Npts = Params.Traj.Npts;
Idx = 1:Npts;

%Determine the relative position vector for all points in Trajectory
Rel_Pos = zeros(2,Npts);
for i=1:Npts
    Rel_Pos(1,i) = Trajectory.States{Dir,i}(1) - State(1); %Relative X position
    Rel_Pos(2,i) = Trajectory.States{Dir,i}(2) - State(2); %Relative Y position
end

%[Index,Distance,Dot_Product]
Data = zeros(Npts,3);

Data(:,1) = Idx';
Data(:,2) = sqrt(Rel_Pos(1,:).^2 + Rel_Pos(2,:).^2);
Data(:,3) = Dot(Current_Direction,Rel_Pos)./Data(:,2)';   %==Cos(heading)

Wrong_Way = Data(:,3) < cos(Params.Ctl.Max_Target_Angle);
Too_Close = Data(:,2) < Params.Ctl.Minimum_Goal_Distance;
End_of_Road = Data(:,1) > (Params.Traj.Npts - Params.Traj.End_Buffer);

N_remove = sum(Wrong_Way | Too_Close | End_of_Road);

if N_remove < Npts   %Then at least one valid point remains
    Data(Wrong_Way | Too_Close | End_of_Road,:) = [];   %Remove invalid points
    Data_Sorted = sortrows(Data,2);
    %Select the closest valid goal point:
    Goal_Idx = Data_Sorted(1,1);
else
    N_backwards = sum(Wrong_Way);
    if N_backwards < Npts   %Then we can just pick a point that is too close
        %Data(Wrong_Way,:) = [];   %Remove invalid points
        %Data_Sorted = sortrows(Data,2);
        %Select the closest valid goal point:
        %Goal_Idx = Data_Sorted(1,1);
        Goal_Idx = -1;   %Delimiter to show that the road is ending
    else  %No valid points. Give up and select the closest
        %Data_Sorted = sortrows(Data,2);
        %Select the closest valid goal point:
        Goal_Idx = -1;   %Delimiter to show that the road is ended
    end
end

end


% trial using t-test

range_fish = 8:11;
numFish = length(range_fish);
TF_fishrange = cell(1,numFish);
% also save clusID of matching pairs???
Pairs_AllClusAllFish = []; % each row: fish#1, clusID1, fish#2, clusID2

for i_fishnum = 1:numFish,
    % choose reference fish
    i_fish_ref = range_fish(i_fishnum);
    U_ref = unique(FC{i_fish_ref}.gIX);
    numClus_ref = length(U_ref);
    TF = zeros(numClus_ref,numFish-1);

    % cycle through clusters in reference fish
    for i_ref_clus = 1:numClus_ref,
        refclusID = U_ref(i_ref_clus);
        IX_ref = find(FC{i_fish_ref}.gIX == refclusID);
        Ref_xyz = FC{i_fish_ref}.xyz_norm(IX_ref,:);

        % for current cluster, compare with closest cluster in each other fish
        for i_testnum = 1:numFish,
            i_fish_test = range_fish(i_testnum);
            if i_fish_test ~= i_fish_ref,
                U = unique(FC{i_fish_test}.gIX);
                numClus = length(U);

                % find testclusID that is closest to current ref-clus in anat-space
                refcoord = mean(Ref.xyz_n,1);
                testcoords = zeros(numClus,3);
                Dist = zeros(numClus,1);
                for i = 1:numClus,
                    IX = find(FC{i_fish_test}.gIX==U(i));
                    testcoords(i,:) = mean(FC{i_fish_test}.xyz_norm(IX,:),1);
                    Dist(i) = pdist([refcoord;testcoords(i,:)]);
                end
                [~,ix] = min(Dist);
                testclusID = U(ix);

                % perform t-test between this pair of clusters
                IX = find(FC{i_fish_test}.gIX==testclusID);
                Test_xyz = FC{i_fish_test}.xyz_norm(IX,:);
                [h,p] = ttest2(Ref_xyz,Test_xyz,'Vartype','unequal');
                if max(h) == 0,
                    % clusters are the same, collect
                    TF(i_ref_clus,i_testnum) = 1;
                    if i_fish_ref<i_fish_test,
                        Pairs_AllClusAllFish = [Pairs_AllClusAllFish; ...
                            [i_fish_ref, refclusID, i_fish_test, testclusID]];
                    end
                else
                    TF(i_ref_clus,i_testnum) = 1-sum(h)/3;
                end
            else % don't compare within same fish
                TF(i_ref_clus,i_testnum) = NaN;
            end
        end
    end
    TF_fishrange{i_fishnum} = TF;
end


function node_num = grid_t3_node_num ( nelemx, nelemy )

%*****************************************************************************80
%
%% GRID_T3_NODE_NUM counts the nodes in a grid of T3 elements.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 February 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NELEMX, NELEMY, the number of elements along the
%    X and Y directions.  The number of elements generated will be
%    NELEMX * NELEMY.
%
%    Output, integer NODE_NUM, the number of nodes in the grid.
%
  node_num = ( nelemx + 1 ) * ( nelemy + 1 );

  return
end