function ress = times(a,bb)
% performs only interpolation nufft

% for n=1:size(bb,3)
% b = bb(:,:,n);
% if a.adjoint
% 	b = b(:).*a.w(:);
% 	res = nufft_adj(b, a.st)/sqrt(prod(a.imSize));;
% 	res = reshape(res, a.imSize(1), a.imSize(2));
% 	res = fft2c(res);
% else
% 	b = reshape(b,a.imSize(1),a.imSize(2));
% 	b = ifft2c(b);
% 	res = (nufft(b, a.st)/sqrt(prod(a.imSize))).*a.w(:);
% 	res = reshape(res,a.dataSize(1),a.dataSize(2));
% end
% ress(:,:,n) = res;
% end
%

ress = mtimes(a,bb);


function P = pos(A)

P = A .* double( A > 0 );


% Test file for bndfun/restrict.m

function pass = test_restrict(pref)

% Get preferences.
if (nargin < 1)
    pref = chebfunpref();
end

% Set the domain
dom = [-2 7];

%%
% Check behavior for empty inputs.
f = bndfun();
f = restrict(f, [-0.5 0.5]);
pass(1) = isempty(f);

%%
% Check behaviour for non-subinterval inputs.
f = bndfun(@(x) sin(x), struct('domain', dom), pref);
g = restrict(f, dom);
pass(2) = isequal(f, g);

try
    g = restrict(f, [dom(1) - 1, dom(2) + 1]); %#ok<NASGU>
    pass(3) = 0;
catch ME
    pass(3) = strcmp(ME.identifier, 'CHEBFUN:BNDFUN:restrict:badInterval');
end

try
    g = restrict(f, [-Inf, 1]); %#ok<NASGU>
    pass(4) = 0;
catch ME
    pass(4) = strcmp(ME.identifier, 'CHEBFUN:BNDFUN:restrict:badInterval');
end

try
    g = restrict(f, [-1 -0.25 0.3 0.1 1]); %#ok<NASGU>
    pass(5) = 0;
catch ME
    pass(5) = strcmp(ME.identifier, 'CHEBFUN:BNDFUN:restrict:badInterval');
end

%%
% Check whether restriction actually results in a BNDFUN on the correct domain.
g = restrict(f,[2, 3]);
pass(6) = all(g.domain == [2, 3]);

%%
% Spot-check a few functions
pass(7) = test_spotcheck_restrict(@(x) exp(x) - 1, dom, [-2 4], [], pref);
pass(8) = test_spotcheck_restrict(@(x) 1./(1 + x.^2), dom, [-0.7 0.9], [], ...
    pref);
pass(9) = test_spotcheck_restrict(@(x) cos(1e3*x), dom, [0.1 0.5], [], pref);
pass(10) = test_spotcheck_restrict(@(t) sinh(t*exp(2*pi*1i/6)), dom, ...
    [-0.4 1], [], pref);

%%
% Check multiple subinterval restriction.
f = bndfun(@(x) sin(x) + sin(x.^2), struct('domain', dom), pref);
g = restrict(f, [-1.7 2.3 6.8]);
h1 = restrict(f, [-1.7 2.3]);
h2 = restrict(f, [2.3 6.8]);
x = linspace(-1, 1, 100).';
err1 = norm(feval(g{1} - h1, x), inf);
err2 = norm(feval(g{2} - h2, x+4), inf);
tol = 1e3*eps;

pass(11) = err1 < tol && err2 < tol;

%%
% Check whether restriction actually results in a BNDFUN on the correct domain.
g = restrict(f,[2, 3, 5]);
pass(12) = all(g{1}.domain == [2, 3] & g{2}.domain == [3,5]);

%%
% Check operation for array-valued functions.
pass(13) = test_spotcheck_restrict(@(x) [sin(x) cos(x) exp(x)], dom, ...
    [-1 -0.7], [], pref);

f = bndfun(@(x) [sin(x) cos(x)], struct('domain', dom), pref);
g = restrict(f, [-0.6 0.1 1]);
h1 = restrict(f, [-0.6 0.1]);
h2 = restrict(f, [0.1 1]);
x = linspace(-.5, 0, 100).';
err1 = norm(feval(g{1} - h1, x), inf);
err2 = norm(feval(g{2} - h2, x+.7), inf);
tol = 10*eps;
pass(14) = err1 < tol && err2 < tol;

%% Test on singular function:

pow = -0.5;
op = @(x) (x - dom(1)).^pow.*sin(x);
pref.blowup = true;
data.exponents = [pow 0];
pass(15) = test_spotcheck_restrict(op, dom, [-1 -0.7], data, pref);

end

% Spot-check restriction of a given function to a given subinterval.
function result = test_spotcheck_restrict(fun_op, dom, subint, data, pref)
% Perform restriction.
data.domain = dom;
f = bndfun(fun_op, data, pref);
g = restrict(f, subint);

a = subint(1);
b = subint(2);

% Sample on a grid of 100 points and check for accuracy.
x = linspace(a, b, 100).';
y_exact = fun_op(x);
y_approx = feval(g, x);

result = norm(y_exact - y_approx, Inf) <...
         8e4*max(get(f, 'vscale')*eps);

end


function [theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters)
%GRADIENTDESCENTMULTI Performs gradient descent to learn theta
%   theta = GRADIENTDESCENTMULTI(x, y, theta, alpha, num_iters) updates theta by
%   taking num_iters gradient steps with learning rate alpha
    [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters);
end


%% Copyright (C) 2014, 2016 Colin B. Macdonald
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy 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 software 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 software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defop  Method   @@symfun mldivide {(@var{f}, @var{g})}
%% @defopx Operator @@symfun {@var{f} \ @var{g}} {}
%% Backslash division of symbolic functions.
%%
%% Simple example:
%% @example
%% @group
%% syms f(x)
%% g(x) = sin(x);
%% @end group
%%
%% @group
%% h = f \ g
%%   @result{} h(x) = (symfun)
%%       sin(x)
%%       ──────
%%        f(x)
%% @end group
%% @end example
%%
%% @seealso{@@sym/mldivide}
%% @end defop

function h = mldivide(f, g)
  [vars, s1, s2] = helper_symfun_binops(f, g);
  h = symfun(s1 \ s2, vars);
end

%!test
%! syms x
%! f(x) = x^2;
%! assert( isa(f\f, 'symfun'))
%! assert( isa(f\x, 'symfun'))


classdef CopeakLoss < dagnn.Loss
    properties
        eps = 10^-5;
        NumInputs = [];
        c = [];
        x = [];
    end

    methods
        function outputs = forward(obj, inputs, params)
            if length(inputs) == 2
                obj.NumInputs = [length(inputs{1}) length(inputs{2})];
                obj.c = cat(1, gpuArray.ones(obj.NumInputs(1), 1), -gpuArray.ones(obj.NumInputs(2), 1));
                obj.x = cat(1, inputs{1}, inputs{2});
                a = -obj.c.*obj.x ;
                b = max(0, a) ;
                t = b + log(exp(-b) + exp(a-b)) ;
                outputs{1} = mean(t(1:obj.NumInputs(1))) + mean(t(obj.NumInputs(1)+1:end));
                NumData = length(inputs{1}) + length(inputs{2});
            else
                obj.NumInputs = length(inputs{1});
                obj.c = gpuArray.ones(obj.NumInputs(1), 1);
                obj.x = inputs{1};
                a = -obj.c.*obj.x ;
                b = max(0, a) ;
                t = b + log(exp(-b) + exp(a-b)) ;
                outputs{1} = mean(t);
                NumData = length(inputs{1});
            end
            n = obj.numAveraged;
            m = n + NumData;
            obj.average = (n * obj.average + double(gather(outputs{1} * NumData))) / m ;
            obj.numAveraged = m;
        end

        function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
            y = - derOutputs{1} .* obj.c ./ (1 + exp(obj.c.*obj.x)) ;
            derInputs{1} = y(1:obj.NumInputs(1)) / obj.NumInputs(1);
            if length(inputs) == 2
                derInputs{2} = y(obj.NumInputs(1)+1:end) / obj.NumInputs(2);
            end
            derParams = {};
        end

        function reset(obj)
            obj.average = 0 ;
            obj.numAveraged = 0 ;
        end
        function obj = CopeakLoss(varargin)
            obj.load(varargin) ;
        end
    end
end


function [Results, OPTIONS, HeadModel] = bst_wmne(HeadModel,OPTIONS)
% BST_WMNE: Compute the whitened and weighted minimum-norm operator (wMNE imaging kernel)
%
% USAGE:  [Results,OPTIONS] = bst_wmne(HeadModel, OPTIONS) : Compute mininum operator
%                   OPTIONS = bst_wmne()                   : Return default options
%
% DESCRIPTION:
%     This program computes the whitened and weighted minimum-norm operator,
%     (the wMNE imaging kernel), which is used to compute whitened
%     and weighted minimum-norm estimates (MNE).
%         (e.g., J=wMNEoperator*B; where B is the unwhitened data).
%     It can also compute the whitened and noise-normalized dynamic
%     statistical parametric mapping (dSPM) inverse operator, and/or the
%     whitened standardized low resolution brain electromagnetic tomography
%     (sLORETA) inverse operator, which are used to compute whitened source
%     activity dSPM and sLORETA maps.
%         (e.g., S_dSPM=dSPMoperator*B; where B is the unwhitened data).
%         (e.g., S_sLORETA=sLORETAoperator*B; where B is the unwhitened data).
%
%     The function was written with the goal of providing some of the same
%     functionality of the MNE software written by Matti Hamalainen, but no
%     guarantees are made that it performs all computations in the same
%     exact way. It also provides some functionalities not available in the
%     MNE software.
%
% INPUTS:
%    - HeadModel: Array of Brainstorm head model structures
%         |- Gain       : Forward field matrix for all the channels (unconstrained source orientations)
%         |- GridOrient : Dipole orientation matrix
%         |- area       : Vector with the areas (or possibly volumes) associated with the vertices of the source space.
%    - OPTIONS: structure
%         |- NoiseCov      : NoiseCov is the noise covariance matrix.
%         |- ChannelTypes  : Type of each channel (for each row of the Leadfield and the NoiseCov matrix)
%         |- InverseMethod : {'wmne', 'dspm', 'sloreta'}
%         |- SourceOrient  : String or a cell array of strings specifying the type of orientation constraints for each HeadModel (default: 'fixed')
%         |- SNR        : Signal-to noise ratio defined as in MNE (default: 3).
%         |- diagnoise  : Flag to discard off-diagonal elements of NoiseCov (assuming heteroscedastic uncorrelated noise) (default: 0)
%         |- loose      : Value that weights the source variances of the dipole components defining the tangent space of the cortical surfaces (default: []).
%         |- depth      : Flag to do depth weighting (default: 1).
%         |- weightexp  : Order of the depth weighting. {0=no, 1=full normalization, default=0.8}
%         |- weightlimit: Maximal amount depth weighting (default: 10).
%         |- magreg     : Amount of regularization of the magnetometer noise covariance matrix
%         |- gradreg    : Amount of regularization of the gradiometer noise covariance matrix.
%         |- eegreg     : Amount of regularization of the EEG noise covariance matrix.
%         |- ecogreg    : Amount of regularization of the ECOG noise covariance matrix.
%         |- seegreg    : Amount of regularization of the SEEG noise covariance matrix.
%         |- fMRI       : Vector of fMRI values are the source points.
%         |- fMRIthresh : fMRI threshold. The source variances of source points with OPTIONS.fMRI smaller
%         |               than fMRIthresh will be multiplied by OPTIONS.fMRIoff.
%         |- fMRIoff    : Weight assigned to non-active source points according to fMRI and fMRIthresh.
%
% OUTPUTS:
%    - Results : structure with the wMNE inverse operator and possibly the dSPM
%                and/or sLORETA inverse operators, and other information:

% NOTES:
%     - More leadfield matrices can be used: the solution will combine all
%       leadfield matrices appropriately.
%
%     - This leadfield structure allows to combine surface and volume
%       source spaces with and without dipole orientation constraints,and
%       with and without area or volumetric current density computations.
%       If using a single sphere headmodel, the silent radial
%       component could be eliminated using the SVD (e.g., use
%       bst_remove_silent.m).
%
%     - NoisCov: This should be computed from the pre-stimulus period for
%       averaged ERF data (e.g., using MNE), or from an empty room recording
%       for unaveraged spontaneous or induced data.
%
%     - Orientation constrains for dipoles (.SourceOrient field)
%         - "fixed"     : Dipoles constrained to point normal to cortical surfaces
%         - "free"      : No constraints, dipoles point in x,y,z directions
%         - "loose"     : Source variances of dipole components pointing tangentially to the cortical surfaces are multipled by OPTIONS.loose
%         - "truncated" : An SVD of the gain matrix for each source point is
%                         used to remove the dipole component with least variance, which for
%                         the Single Sphere Head Model, corresponds to the radialsilent component).
%       => For dealing with multiple source spaces with different types of orientation constraints use for example,
%          OPTION.SourceOrient{1}='fixed';
%          OPTION.SourceOrient{2}='free';
%          This has to correspond with the HeadModel Structure
%
%     - The output HeadModel param is used here in return to save LOTS of memory in the bst_wmne function,
%       event if it seems to be absolutely useless. Having a parameter in both input and output have the
%       effect in Matlab of passing them "by referece". So please, do NOT remove it from the function description
%
%     - sLORETA: Output values are multiplied by 1e12 for display in Brainstorm (time series and cortical maps).

% @=============================================================================
% 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.
% =============================================================================@
%
% Copyright (C) 2010 - Rey Rene Ramirez
%
% Authors:  Rey Rene Ramirez, Ph.D.   e-mail: rrramirez at mcw.edu
%           Francois Tadel, 2010-2013

%% ===== DEFINE DEFAULT OPTIONS =====
Def_OPTIONS.NoiseCov      = [];
Def_OPTIONS.InverseMethod = 'wmne';
Def_OPTIONS.ChannelTypes  = {};
Def_OPTIONS.SNR           = 3;
Def_OPTIONS.diagnoise     = 0;
%Def_OPTIONS.SourceOrient= {'free'};
Def_OPTIONS.SourceOrient= {'fixed'};
Def_OPTIONS.loose       = 0.2;
Def_OPTIONS.depth       = 1;
Def_OPTIONS.weightexp   = 0.5;
Def_OPTIONS.weightlimit = 10;
Def_OPTIONS.regnoise    = 1;
Def_OPTIONS.magreg      = .1;
Def_OPTIONS.gradreg     = .1;
Def_OPTIONS.eegreg      = .1;
Def_OPTIONS.ecogreg     = .1;
Def_OPTIONS.seegreg     = .1;
Def_OPTIONS.fMRI        = [];
Def_OPTIONS.fMRIthresh  = [];
Def_OPTIONS.fMRIoff     = 0.1;
Def_OPTIONS.pca         = 1;
% Return the default options
if (nargin == 0)
    Results = Def_OPTIONS;
    return
end
% Make the default for all the leadfields
numL = size(HeadModel,2);
Def_OPTIONS.SourceOrient = repmat(Def_OPTIONS.SourceOrient, [1 numL]);
% Copy default options to OPTIONS structure (do not replace defined values)
OPTIONS = struct_copy_fields(OPTIONS, Def_OPTIONS, 0);

%% ===== CHECK FOR INVALID VALUES =====
% Detect if the input noise covariance matrix is or should be diagonal
C_noise = OPTIONS.NoiseCov;
variances = diag(C_noise);
if isequal(C_noise, diag(variances))
    OPTIONS.diagnoise = 1;
    disp('wMNE> Detected diagonal noise covariance: setting diagnoise to 1');
end
% If OPTIONS.diagnoise is 1, then OPTIONS.pca=0
if OPTIONS.diagnoise
    OPTIONS.pca=0;
    disp('wMNE> If using diagonal noise covariance, PCA option should be off. Setting PCA option off.')
end
if isempty(OPTIONS.NoiseCov)
    error('You need to input the noise covariance in the NoiseCov field of OPTIONS.')
end
if (numL ~= length(OPTIONS.SourceOrient))
    error('The number of elements in the HeadModel structure should equal the length of the cell array OPTIONS.SourceOrient.')
end
if ~isempty(OPTIONS.loose) && (OPTIONS.loose>=1 || OPTIONS.loose<=0)
    error('loose value should be smaller than 1 and bigger than 0, or empty for no loose orientations.')
end
if OPTIONS.weightexp>1 || OPTIONS.weightexp<0
    error('weightexp should be a scalar between 0 and 1')
end
if OPTIONS.magreg>1 || OPTIONS.magreg<0
    error('magreg should be a scalar between 0 and 1')
end
if OPTIONS.eegreg>1 || OPTIONS.eegreg<0
    error('eegreg should be a scalar between 0 and 1')
end
if OPTIONS.ecogreg>1 || OPTIONS.ecogreg<0
    error('ecogreg should be a scalar between 0 and 1')
end
if OPTIONS.seegreg>1 || OPTIONS.seegreg<0
    error('seegreg should be a scalar between 0 and 1')
end

%% ===== NOISE COVARIANCE RANK =====
% Get indices of MEG and EEG channels
iMeg  = find(strncmpi(OPTIONS.ChannelTypes,'MEG',3));
iEeg  = find(strncmpi(OPTIONS.ChannelTypes,'EEG',3));
iEcog = find(strncmpi(OPTIONS.ChannelTypes,'ECOG',3));
iSeeg = find(strncmpi(OPTIONS.ChannelTypes,'SEEG',3));
% Diagonal noisecov
if OPTIONS.diagnoise
    C_noise = diag(variances);
    rnkC_noise_meg = length(iMeg);
    rnkC_noise_eeg = length(iEeg);
    rnkC_noise_ecog = length(iEcog);
    rnkC_noise_seeg = length(iSeeg);
    disp('wMNE> Setting off diagonal elements of the noise covariance to zero.');
    disp(['wMNE> Rank of noise covariance is ' num2str(size(C_noise,1))]);
% Full noisecov
else
    % Estimate noise covariance matrix rank separately for sensor types
    if ~isempty(iMeg)
        rnkC_noise_meg = rank(single(C_noise(iMeg,iMeg))); % Rey added this. Separate rank of MEG. 3/23/11
        disp(['wMNE> Rank of MEG part of noise covariance is ' num2str(rnkC_noise_meg)]);
    end
    if ~isempty(iEeg)
        rnkC_noise_eeg = rank(single(C_noise(iEeg,iEeg))); % Rey added this. Separate rank of EEG. 3/23/11
        disp(['wMNE> Rank of EEG part of noise covariance is ' num2str(rnkC_noise_eeg)]);
    end
    if ~isempty(iEcog)
        rnkC_noise_ecog = rank(single(C_noise(iEcog,iEcog)));  % FT added 21-Feb-13
        disp(['wMNE> Rank of ECOG part of noise covariance is ' num2str(rnkC_noise_ecog)]);
    end
    if ~isempty(iSeeg)
        rnkC_noise_seeg = rank(single(C_noise(iSeeg,iSeeg)));  % FT added 21-Feb-13
        disp(['wMNE> Rank of SEEG part of noise covariance is ' num2str(rnkC_noise_seeg)]);
    end
    % Sets off-diagonal terms to zero. Rey added this. 3/23/11
    C_noise_new = 0 * C_noise;
    if ~isempty(iMeg)
        C_noise_new(iMeg,iMeg) = C_noise(iMeg,iMeg);
    end
    if ~isempty(iEeg)
        C_noise_new(iEeg,iEeg) = C_noise(iEeg,iEeg);
    end
    if ~isempty(iEcog)
        C_noise_new(iEcog,iEcog) = C_noise(iEcog,iEcog);
    end
    if ~isempty(iSeeg)
        C_noise_new(iSeeg,iSeeg) = C_noise(iSeeg,iSeeg);
    end
    C_noise = C_noise_new;
end

%% ===== REGULARIZE NOISE COVARIANCE MATRIX =====
% Only if option is selected
if OPTIONS.regnoise
    listTypes = unique(OPTIONS.ChannelTypes);
    % Loop on all the required data types (MEG MAG, MEG GRAD, EEG)
    for iType = 1:length(listTypes)
        % Get channel indices
        iChan = find(strcmpi(OPTIONS.ChannelTypes, listTypes{iType}));
        % Regularize noise covariance matrix
        switch listTypes{iType}
            case 'MEG GRAD', reg = OPTIONS.gradreg;
            case 'MEG MAG',  reg = OPTIONS.magreg;
            case 'MEG',      reg = OPTIONS.gradreg;
            case 'EEG',      reg = OPTIONS.eegreg;
            case 'ECOG',     reg = OPTIONS.ecogreg;
            case 'SEEG',     reg = OPTIONS.seegreg;
        end
        C_noise(iChan,iChan) = C_noise(iChan,iChan) + (reg * mean(variances(iChan)) * eye(length(iChan)));
    end
end

% FT added 06-Nov-2014
% Make sure the noise covariance matrix is strictly symmetrical
% (the previous operations may cause rounding errors that make the matrix not exactly symmetrical)
if ~isequal(C_noise, C_noise')
    C_noise = tril(C_noise) + (tril(C_noise)' - diag(diag(C_noise)));
end

%% ===== WHITENING OPERATOR =====
% Rey added all of this, 3/23/11
% Modified FT 21-Feb-2013
% Whitening of each modality separately (MEG,EEG,ECOG,SEEG), which assumes
% zero covariance between them (i.e., a block diagonal noise covariance). This
% was recommended by Matti as EEG does not measure all the signals from the same
% environmental noise sources as MEG.
nChan = size(C_noise,2);
W = zeros(0, nChan);
if ~isempty(iMeg)
    W_meg = CalculateWhitener('MEG', C_noise, iMeg, rnkC_noise_meg, OPTIONS.pca);
    W_tmp = zeros(size(W_meg,1), nChan);
    W_tmp(:,iMeg) = W_meg;
    W = [W; W_tmp];
end
if ~isempty(iEeg)
    W_eeg = CalculateWhitener('EEG', C_noise, iEeg, rnkC_noise_eeg, OPTIONS.pca);
    W_tmp = zeros(size(W_eeg,1), nChan);
    W_tmp(:,iEeg) = W_eeg;
    W = [W; W_tmp];
end
if ~isempty(iEcog)
    W_ecog = CalculateWhitener('ECOG', C_noise, iEcog, rnkC_noise_ecog, OPTIONS.pca);
    W_tmp = zeros(size(W_ecog,1), nChan);
    W_tmp(:,iEcog) = W_ecog;
    W = [W; W_tmp];
end
if ~isempty(iSeeg)
    W_seeg = CalculateWhitener('SEEG', C_noise, iSeeg, rnkC_noise_seeg, OPTIONS.pca);
    W_tmp = zeros(size(W_seeg,1), nChan);
    W_tmp(:,iSeeg) = W_seeg;
    W = [W; W_tmp];
end
% Check for whitener integrity
if any(isnan(W(:))) || any(isinf(W(:)))
    error('Invalid noise covariance matrix.')
end
% Display rank of the whitener
rnkC_noise = size(W,1);
display(['wMNE> Total rank is ' num2str(rnkC_noise) '.'])

%% ===== PROCESSING LEAD FIELD MATRICES, WEIGHTS, AREAS & ORIENTATIONS =====
% Initializing.
spl = zeros(numL,1);
numdipcomp = spl;
for k = 1:numL
    sL = size(HeadModel(k).Gain, 2);
    switch OPTIONS.SourceOrient{k}
        case 'fixed',      numdipcomp(k)=1;
        case 'free',       numdipcomp(k)=3;
        case 'loose',      numdipcomp(k)=3;
        case 'truncated',  numdipcomp(k)=2;
    end
    spl(k) = (sL / 3) * numdipcomp(k); % This is a vector with the total number of dipole components per source space.
end
sspl = sum(spl); % This is the total number of dipole components across all source spaces.
L = zeros(rnkC_noise,sspl);
w = ones(sspl,1);
if isfield(HeadModel, 'area')
    areas = w;
else
    areas = [];
end
itangential = [];
start = 0;
Q_Cortex = cell(1,numL);
for k = 1:numL
    start = start + 1;
    endd = start + spl(k) - 1;
    Lk = HeadModel(k).Gain;
    HeadModel(k).Gain = [];
    %% ===== COMPUTE POWER =====
    szL = size(Lk);
    if OPTIONS.depth
        % display(['wMNE> Computing power of gain matrices at each source point for source space ' num2str(k) '.'])
        % Computing power
        wk = squeeze(sum(sum((reshape(Lk,[szL(1) 3 szL(2)/3])) .^2,1),2));
        wk = repmat(wk',[numdipcomp(k) 1]);
        wk = reshape(wk,[spl(k) 1]);
        w(start:endd) = wk;
        clear wk
    end
    switch OPTIONS.SourceOrient{k}
        case 'fixed'
            display('wMNE> Appying fixed dipole orientations.')
            Lk = bst_gain_orient(Lk,HeadModel(k).GridOrient);
        case 'free'
            display('wMNE> Using free dipole orientations. No constraints.')
        case 'loose'
            display('wMNE> Transforming lead field matrix to cortical coordinate system.')
            [Lk, Q_Cortex{k}] = bst_xyz2lf(Lk, HeadModel(k).GridOrient');
            % Getting indices for tangential dipoles.
            itangentialtmp = start:endd;
            itangentialtmp(1:3:end) = [];
            itangential = [itangential itangentialtmp];  %#ok<AGROW>
        case 'truncated'
            display('wMNE> Truncating the dipole component pointing in the direction with least variance (i.e., silent component for single sphere head model.')
            [Lk, Q_Cortex{k}] = bst_remove_silent(Lk);
    end
    %% ===== WHITEN LEAD FIELD MATRIX =====
    % Whiten lead field.
    % display(['wMNE> Whitening lead field matrix for source space ' num2str(k) '.'])
    Lk = W * Lk;
    if isfield(HeadModel(k),'area') && ~isempty(HeadModel(k).area)
        areav = HeadModel(k).area;
        areav = repmat(areav', [numdipcomp(k) 1]);
        areav = reshape(areav, [spl(k) 1]);
        areas(start:endd) = areav;
    end
    L(:,start:endd) = Lk;
    start = endd;
end
% Computing reciprocal of power.
w = 1 ./ w;
% Clear memory
clear Lk endd start itangentialtmp sL szL

%% ===== APPLY AREAS =====
if ~isempty(areas)
    display('wMNE> Applying areas to compute current source density.')
    areas = areas.^2;
    w = w .* areas;
end
clear areas

%% ===== APPLY DEPTH WEIGHTHING =====
if OPTIONS.depth
    % ===== APPLY WEIGHT LIMIT =====
    % Applying weight limit.
    % display('wMNE> Applying weight limit.')
    weightlimit2 = OPTIONS.weightlimit .^ 2;
    %limit=min(w(w>min(w)*weightlimit2));  % This is the Matti way.
    limit = min(w) * weightlimit2;  % This is the Rey way (robust to possible weight discontinuity).
    w(w>limit) = limit;

    % ===== APPLY WEIGHT EXPONENT =====
    % Applying weight exponent.
    % display('wMNE> Applying weight exponent.')
    w = w .^ OPTIONS.weightexp;
    clear limit weightlimit2
end

%% ===== APPLY LOOSE ORIENTATIONS =====
if ~isempty(itangential)
    display(['wMNE> Applying loose dipole orientations. Loose value of ' num2str(OPTIONS.loose) '.'])
    w(itangential) = w(itangential) * (OPTIONS.loose);
end

%% ===== APPLY fMRI PRIORS =====
% Apply fMRI Priors
if ~isempty(OPTIONS.fMRI)
    display('wMNE> Applying fMRI priors.')
    ifmri = (OPTIONS.fMRI < OPTIONS.fMRIthresh);
    w(ifmri) = w(ifmri) * OPTIONS.fMRIoff;
end

%% ===== ADJUSTING SOURCE COVARIANCE MATRIX =====
% Adjusting Source Covariance matrix to make trace of L*C_J*L' equal to number of sensors.
% display('wMNE> Adjusting source covariance matrix.')
C_J = speye(sspl, sspl);
C_J = spdiags(w, 0, C_J);
trclcl = trace(L * C_J * L');
C_J = C_J * (rnkC_noise / trclcl);
Rc = chol(C_J, 'lower');
LW = L * Rc;
clear C_J trclcl sspl itangential rnkC_noise

%% ===== SINGULAR VALUE DECOMPOSITION =====
% Set regularization parameter based on SNR
lambda2 = OPTIONS.SNR ^ (-2);
% Compute SVD.
% display('wMNE> Computing SVD of whitened and weighted lead field matrix.')
[U,S,V] = svd(LW,'econ');
s = diag(S);
ss = s ./ (s.^2 + lambda2);
display(sprintf('wMNE> Effective Max and Mean SNR: %.2f and %.2f', s(1)^2/lambda2, mean(s.^2)/lambda2));
clear LW lambda2 s

%% ===== WHITENED MNE IMAGING KERNEL =====
% Compute whitened MNE operator.
Kernel = Rc * V * diag(ss) * U';
clear Rc V ss U

%% ===== NORMALIZATIONS =====
start = 0;
for k = 1:numL
    start = start + 1;
    endd = start + spl(k) - 1;

    % ===== dSPM OPERATOR =====
    if strcmpi(OPTIONS.InverseMethod, 'dspm')
        dspmdiag = sum(Kernel(start:endd,:) .^2, 2);
        if (numdipcomp(k) == 1)
            dspmdiag = sqrt(dspmdiag);
        elseif (numdipcomp(k)==3 || numdipcomp(k)==2)
            dspmdiag = reshape(dspmdiag, [numdipcomp(k), spl(k)/numdipcomp(k)]);
            dspmdiag = sqrt(sum(dspmdiag)); % Taking trace and sqrt.
            dspmdiag = repmat(dspmdiag, [numdipcomp(k), 1]);
            dspmdiag = reshape(dspmdiag, [spl(k), 1]);
        end
        Kernel(start:endd,:) = bst_bsxfun(@rdivide, Kernel(start:endd,:), dspmdiag);

    % ===== sLORETA OPERATOR =====
    elseif strcmpi(OPTIONS.InverseMethod, 'sloreta')
        if (numdipcomp(k) == 1)
            sloretadiag = sqrt(sum(Kernel(start:endd,:) .* L(:,start:endd)', 2));
            Kernel(start:endd,:) = bst_bsxfun(@rdivide, Kernel(start:endd,:), sloretadiag);
        elseif (numdipcomp(k)==3 || numdipcomp(k)==2)
            for spoint = start:numdipcomp(k):endd
                R = Kernel(spoint:spoint+numdipcomp(k)-1,:) * L(:,spoint:spoint+numdipcomp(k)-1);
                SIR = sqrtm(pinv(R));
                Kernel(spoint:spoint+numdipcomp(k)-1,:) = SIR * Kernel(spoint:spoint+numdipcomp(k)-1,:);
            end
        end
    end

    % ===== LOOSE ORIENTATION: RE-ORIENT COMPONENTS =====
    % WARNING: Changing the orientations of the dipoles from MNE to Brainstorm
    % => Make "Unconstrained" and "loose"/"truncated" models directly comparable
    if ~isempty(Q_Cortex{k})
        % Creating a block diagonal matrix
        N = endd - start + 1;
        Nout = N / numdipcomp(k) * 3;
        iRow = reshape(repmat(reshape(1:Nout,3,[]), numdipcomp(k), 1), 1, []);
        iCol = reshape(repmat(1:N,3,1), 1, []);
        Q_Cortex{k} = sparse(iRow, iCol, Q_Cortex{k}(:));
        % Applying orientations
        Kernel(start:endd,:) = Q_Cortex{k} * Kernel(start:endd,:);
    end

    start=endd;
end
disp(' ');

%% ===== ASSIGN IMAGING KERNEL =====
% Multiply inverse operator and whitening matrix, so no need to whiten data.
Kernel = Kernel * W;
% Return results structure
Results.ImagingKernel = Kernel;
Results.ImageGridAmp  = [];
Results.Whitener      = W;
if (length(numdipcomp) > 1)
    Results.nComponents = 0;
else
    Results.nComponents = numdipcomp;
end

end

%% ==============================================================================
%  ===== HELPER FUNCTIONS =======================================================
%  ==============================================================================
function W = CalculateWhitener(Modality, C_noise, iChannel, rnkC_noise, isPca)
    [V,D] = eig(C_noise(iChannel,iChannel));
    % In some case, eig returns complex values
    if ~isreal(D)
        error('Complex values in the eigvalues...');
    end
    D = diag(D);
    [D,I] = sort(D,'descend');
    V = V(:,I);
    % No PCA case.
    if ~isPca
        display(['wMNE> Not doing PCA for ' Modality '.'])
        D = 1 ./ D;
        W = diag(sqrt(D)) * V';
    % Rey's approach. MNE has been changed to implement this.
    else
        display(['wMNE> Setting small ' Modality ' eigenvalues to zero.'])
        D = 1 ./ D;
        D(rnkC_noise+1:end) = 0;
        W = diag(sqrt(D)) * V';
        W = W(1:rnkC_noise,:); % This line will reduce the actual number of variables in data and leadfield to the true rank. This was not done in the original MNE C code.
    end
end


function [CSF, seg]=mtv_mrQ_Seg_kmeans_simple(T1,BM,M0,mmPerVox,CSFVal)
% function [CSF, seg]=mtv_mrQ_Seg_kmeans_simple(T1,BM,M0)
%
% Clips brain to ventricles area, then segments using k-means with three
% clusters.
%
% This function uses FSL to segment into three tissues. It takes the CSF
% tissue and restricts it by the T1 values. The CSF is also restricted to
% be in the center of the brain in a box of approximately 60mm x 80mm x
% 40mm. Assuming that the brain is in AC-PC space, this is where the
% ventricles should be.
% Assumption:
%       CSFVal: R1 for water at body temperature (in 1/sec).
%                  Default is 0.35.
%
% ~INPUTS~
%       T1: VFA T1.
%       BM: Brain Mask.
%       M0: VFA M0.
%       CSFVal: Threshold on the R1 value of CSF (default=0.35s-1)
%
% ~OUTPUTS~
%       CSF: Refined mask of ventricules (box in the center + smooth)
%       seg: brain clustering (GM=1;DeepGray=2;WM=3;CSF=4)
%
% Adapted from:
% (C) Mezer lab, the Hebrew University of Jerusalem, Israel
%   2015
%
%

%% I. Loading and definitions
if ~exist('CSFVal','var')
    CSFVal=1/0.35; % R1 (in 1/sec) of water at body temp  (minimum value)
end
R1=1./T1;
BM = BM & ~isinf(R1);
%% II. Perform k-means in a "while" loop

    fprintf('\n Performing segmentation for CSF file ...              \n');

seg=zeros(size(R1));

mask= R1>CSFVal & BM;
notdone=0;

while notdone==0

    [IDX,C] =kmeans(R1(mask),3);
    seg(mask)=IDX;

    notdone=1;

    % Check we don't get a strange cluster that is very small in size.
    %(if so, this might be just noise)
    if  length(find(IDX==1))/length(IDX)<0.05
        mask=mask & seg~=1;
        notdone=0;
    end

    if  length(find(IDX==2))/length(IDX)<0.05
        mask=mask & seg~=2;
        notdone=0;
    end

    if  length(find(IDX==3))/length(IDX)<0.05
        mask=mask & seg~=3;
        notdone=0;
    end
end

% check if the clusters' means are too similar
if abs(1-C(1)/C(2))<0.1  &&  abs(1-C(1)/C(3))<0.1
    [IDX,C] =kmeans(R1(mask),1);
elseif abs(1-C(1)/C(2))<0.1
    [IDX,C] =kmeans(R1(mask),2);
elseif abs(1-C(1)/C(3))<0.1
    [IDX,C] =kmeans(R1(mask),2);
elseif abs(1-C(2)/C(3))<0.1
    [IDX,C] =kmeans(R1(mask),2);
end

%% III. Create segmentation file of the clipped brain
seg=zeros(size(R1));
seg(mask)=IDX;

% The tissue with the highest value is white matter (WM), the tissue with
% the lowest value is gray matter (GM), and the tissue with the
% intermediate value is the deep nuclei and the tissue between the WM and
% the GM.
%
% In some segmentations the lowest value is is air, intermediate is
% GM, and highest is WM.
%
% Either way, the order is maintained and we get a segmentation of GM, WM
% and CSF.

[val,idx]=sort(C);
GMclass=1;DEEPclass=2;WMclass=3; CSFclass=4;

seg(seg==idx(1))=4; seg(seg==idx(2))=5;seg(seg==idx(3))=6;
seg(seg==4)=GMclass; seg(seg==5)=DEEPclass; seg(seg==6)=WMclass;

CSF= R1<CSFVal & BM;
seg(CSF)=CSFclass; % any region that is mostly water.

% Clip mask size
boxsize = [30 40 20];
sz=size(CSF); szH=round(sz./2);
XX=boxsize(1)./round(mmPerVox(1));
YY=boxsize(2)./round(mmPerVox(2));
ZZ=boxsize(3)./round(mmPerVox(3));

CSF(szH(1)+XX:end,:,:)=0;
CSF(1:szH(1)-XX,:,:)=0;

CSF(:,1:szH(2)-YY,:)=0;
CSF(:,szH(2)+YY:end,:,:)=0;
if numel(szH)>2
    CSF(:,:,1:max(1,szH(3)-ZZ))=0;
    CSF(:,:,min(end,szH(3)+ZZ):end)=0;
end
%% IV. Smoothe in space
[CSF1] = ordfilt3D(CSF,6);
CSF1=CSF &  CSF1;

CSF2= CSF1 & R1<0.25 & R1>0.2 & M0<prctile(M0(BM),99);

%% V. Some issues

if length(find(CSF2))<200
           fprintf(['\n Warning: We could find only ' num2str(length(find(CSF2))) ' csf voxels. This makes the CSF WF estimation noisy. Consider reducing the CSF T1 threshold.              \n']);
end

% Larger ventricles region.
% This mask is good for cases when CSF ventricles are hard to identify.
% It may reduce the accuracy.
CSF= CSF & R1<0.25 & R1>0.2 & M0<prctile(M0(BM),99);


function [ MINSCORE, MINTRANS] = compRoomMatchScore( HYPS, VALID_TRANS_GNDS )
%COMPROOMMATCHSCORE Summary of this function goes here
%   Detailed explanation goes here
HYP_COMP = getHypInfo(HYPS);
MINSCORE = zeros(length(HYPS), length(VALID_TRANS_GNDS));
MINTRANS = zeros(length(HYPS), length(VALID_TRANS_GNDS));
for j = 1:length(VALID_TRANS_GNDS)
%     fprintf('GND: %d/%d\n', j, length(VALID_TRANS_GNDS));
    fprintf('>>%d', j);
    tCOST = roomAlignmentMex(HYP_COMP, VALID_TRANS_GNDS(j).SAMPLE_COMP, 3, 0);
    [B,I] = min( tCOST, [], 2);
    MINSCORE(:,j) = B;
    MINTRANS(:,j) = I;
end

end


function liga(pattern)
%*************************************************
%DATE: 13/8/2007 (created); 	13/8/2007 (modified)
%FUNCTION:
%INPUTS:
%OUTPUTS:
%muwn.gu@gmail.com
%*************************************************

global layerMatrix;

segLengthArray = extractPattern (pattern);

for segIndex = 1: size(segLengthArray, 2)

	segFrom = round ( 96 * segLengthArray(segIndex).from);
	if (segFrom == 0)
		segFrom = 1;
	end
	segEnd	= round ( 96 * segLengthArray(segIndex).end);

	for pointIndex = segFrom:segEnd 			% horzontal sweep

		prIndex = find(layerMatrix(:,pointIndex) == 9); % find the photo resister sublines in current pointIndex
		layerMatrix (prIndex, pointIndex) = 0;

	end
end

function [segLengthArray] = extractPattern(pattern)
%*************************************************
%DATE: 11/8/2007 (created); 	11/8/2007 (modified)
%FUNCTION:	extract segment number and length array from pattern
%INPUTS:	pattern string
%OUTPUTS:	segLengthArray
%*************************************************
%'  -- -- -'
%'1234567890
segIndex = 1;
patternLength = length (pattern);

if (pattern(1, 1) == ' ')
segLengthArray(1).from = 0;
end

for charIndex =  1:patternLength - 1

	if (pattern(1, charIndex) == '-') & (pattern(1, charIndex+1) == ' ')
		segLengthArray(segIndex).from = (charIndex)/(patternLength);
	end

	if (pattern(1, charIndex) == ' ') & (pattern(1, charIndex+1) == '-')
		segLengthArray(segIndex).end = (charIndex)/(patternLength);
		segIndex =  segIndex + 1;
	end
end

	if (pattern(1, patternLength) == ' ')
		segLengthArray(segIndex).end = 1;
	end


% Summarise EEG events
% axs Jun 2018
function [ev_count] = event_code_count(EEG)

evt = struct2table(EEG.event);
evtype = evt.type;

n_ev = numel(evtype);

ev2 = zeros(n_ev,1);

str_flag = 0;
for i = 1:n_ev

    ev_here = evt.type{i};

    ev_num = str2double(ev_here);

    if isnan(ev_num)
        if strcmp(ev_here,'boundary') == 1
            ev_num = -99;
        else
            ev_num = 0;
            str_flag = 1;
        end
    end

    ev2(i) = ev_num;
end

% Now parse and display
n_ev_types = unique(ev2);

ev_count = zeros(numel(n_ev_types),2);
ev_count(1:end,1) = n_ev_types;

for i = 1:numel(n_ev_types)
    indx_here = find(ev2 == n_ev_types(i));
    count_here = numel(indx_here);
    ev_count(i,2) = count_here;
end

disp('Your event code counts are:')
disp(ev_count)

if str_flag == 1
    disp('Event codes of unknown strings were taken as 0s');
end


function show3DLD(X, adj, color, varargin)

% function show3DLD(X, adj, color, varargin)
%
% This file is created by Tianfan Xue (tfxue@mit.edu).

para.showNumber = false;
para.showAxis = true;
para.fontsize = 20;
para = propval(varargin, para);

if (nargin == 2) || isempty(color)
    color = [1,0,0];
end

X1 = X(1,:); X2 = X(2,:); X3 = X(3,:);
plot3(X1,X2,X3,'.','Color',color,'MarkerSize',10);
hold on;
line(X1(adj)', X2(adj)', X3(adj)', 'Color', color,'LineWidth',3);
if para.showNumber
    for i=1:size(X,2)
        text(X1(i),X2(i),X3(i),sprintf('%d',i),'FontSize',para.fontsize);
    end
end
if para.showAxis
    xlabel('x');
    ylabel('y');
    zlabel('z');
end
axis equal

end


function [eigvector, eigvalue, bSuccess] = OLPP(W, options, data)
% OLPP: Orthogonal Locality Preserving Projections
%
%       [eigvector, eigvalue, bSuccess] = OLPP(W, options, data)
%
%             Input:
%               data       - Data matrix. Each row vector of fea is a data point.
%               W       - Affinity matrix. You can either call "constructW"
%                         to construct the W, or construct it by yourself.
%               options - Struct value in Matlab. The fields in options
%                         that can be set:
%
%                         Please see OLGE.m for other options.
%
%             Output:
%               eigvector - Each column is an embedding function, for a new
%                           data point (row vector) x,  y = x*eigvector
%                           will be the embedding result of x.
%               eigvalue  - The sorted eigvalue of OLPP eigen-problem.
%
%               bSuccess  - 0 or 1. Indicates whether the OLPP calcuation
%                           is successful. (OLPP needs matrix inverse,
%                           which will lead to eigen-decompose a
%                           non-symmetrical matrix. The caculation precsion
%                           of malab sometimes will cause imaginary numbers
%                           in eigenvectors. It seems that the caculation
%                           precsion of matlab is a little bit random, you
%                           can try again if not successful. More robust
%                           and efficient algorithms are welcome!)
%
%                         Please see OLGE.m for other options.
%
%
%
%
%    Examples:
%
%       fea = rand(50,70);
%       options = [];
%       options.Metric = 'Euclidean';
%       options.NeighborMode = 'KNN';
%       options.k = 5;
%       options.WeightMode = 'HeatKernel';
%       options.t = 1;
%       W = constructW(fea,options);
%       options.PCARatio = 0.99
%       options.ReducedDim = 5;
%       bSuccess = 0
%       while ~bSuccess
%           [eigvector, eigvalue, bSuccess] = OLPP(W, options, fea);
%       end
%       Y = fea*eigvector;
%
%       fea = rand(50,70);
%       gnd = [ones(10,1);ones(15,1)*2;ones(10,1)*3;ones(15,1)*4];
%       options = [];
%       options.Metric = 'Euclidean';
%       options.NeighborMode = 'Supervised';
%       options.gnd = gnd;
%       options.bLDA = 1;
%       W = constructW(fea,options);
%       options.PCARatio = 1;
%       options.ReducedDim = 5;
%       while ~bSuccess
%           [eigvector, eigvalue, bSuccess] = OLPP(W, options, fea);
%       end
%       Y = fea*eigvector;
%
%
%
% See also constructW, LPP, LGE, OLGE.
%
%Reference:
%
%   Deng Cai and Xiaofei He, "Orthogonal Locality Preserving Indexing"
%   The 28th Annual International ACM SIGIR Conference (SIGIR'2005),
%   Salvador, Brazil, Aug. 2005.
%
%   Deng Cai, Xiaofei He, Jiawei Han and Hong-Jiang Zhang, "Orthogonal
%   Laplacianfaces for Face Recognition". IEEE Transactions on Image
%   Processing, vol. 15, no. 11, pp. 3608-3614, November, 2006.
%
%    Written by Deng Cai (dengcai2 AT cs.uiuc.edu), August/2004, Feb/2006,
%                                                   Mar/2007, May/2007

if (~exist('options','var'))
   options = [];
end

[nSmp] = size(data,1);
if size(W,1) ~= nSmp
    error('W and data mismatch!');
end

D = full(sum(W,2));

if isfield(options,'Regu') && options.Regu
    options.ReguAlpha = options.ReguAlpha*sum(D)/length(D);
end

D = sparse(1:nSmp,1:nSmp,D,nSmp,nSmp);

%==========================
% If data is too large, the following centering codes can be commented
%==========================
if isfield(options,'keepMean') && options.keepMean
else
    if issparse(data)
        data = full(data);
    end
    sampleMean = mean(data);
    data = (data - repmat(sampleMean,nSmp,1));
end
%==========================

[eigvector, eigvalue, bSuccess] = OLGE(W, D, options, data);

eigIdx = find(eigvalue < 1e-3);
eigvalue (eigIdx) = [];
eigvector(:,eigIdx) = [];


function info = xif_read_header(filename)
% function for reading header of XIF HDllab/ATL ultrasound ( .xif )
% volume file
%
% info = xif_read_header(filename);
%
% examples:
% 1,  info=xif_read_header()
% 2,  info=xif_read_header('volume.xif');

if(exist('filename','var')==0)
    [filename, pathname] = uigetfile('*.xif', 'Read xif-file');
    filename = [pathname filename];
end

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

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

% Store file name of volume
info.Filename=filename;

%Run through the XML header, reading in scanlines, samples etc.
s = [];
while (size(strfind(s, '#SOH')) == 0)
    s = fgets(fid);
    if (strfind(s, 'echoNumLines'))
       % <dataItem
       %   name="echoNumLines"
       %   type="INT"
       %   value="105"/>
        s = fgets(fid);
        s = fgets(fid);
        info.Scanlines = str2num(cell2mat(regexp(s, '(\d+)', 'match')));
    end
    if (strfind(s, 'echoNumDisplaySamples'))
        s = fgets(fid);
        s = fgets(fid);
        info.Samples = str2num(cell2mat(regexp(s, '(\d+)', 'match')));
    end
    if (strfind(s, 'numFrames'))
        s = fgets(fid);
        s = fgets(fid);
        info.Frames = str2num(cell2mat(regexp(s, '(\d+)', 'match')));
    end
    if (strfind(s, 'frameRate'))
        s = fgets(fid);
        s = fgets(fid);
        info.Framerate = str2num(cell2mat(regexp(s, '(\d+)', 'match')));
    end
    if (strfind(s, 'echoScan_linearWidth'))
        s = fgets(fid);
        s = fgets(fid);
        %Different regexp, as we need to match a decimal number.
        info.Width = str2num(cell2mat(regexp(s, '(\d+\.\d+)', 'match')));
    end
    if (strfind(s, 'echoDepth_twodDepth'))
        s = fgets(fid);
        s = fgets(fid);
        %Same as above.
        info.Height = str2num(cell2mat(regexp(s, '(\d+\.\d+)', 'match')));
    end
end
info.Dimensions=[info.Samples, info.Scanlines, info.Frames];
info.PixelDimensions=[0 0 0];
fclose(fid);


function x = subsasgn( x, S, y )

%   Disciplined convex/geometric programming information for SUBSASGN:
%      Subscripting can be used to change values of elements or slices
%      of CVX variables in the same manner as with numeric arrays. All
%      conventions are preserved, including the colon ':' and 'end'
%      notation, as well as the ability to "expand" a CVX variable by
%      assigning a value to a location outside of its current dimensions
%      (e.g., X(end+1)=0).
%
%      One notable exception is this: if the right-hand side is a CVX
%      expression, then the left-hand side must be as well. So, for
%      example, the following will fail:
%         variable x;
%         y = ones(3,1);
%         y(2) = x;
%      This is because MATLAB does not know how to automatically promote
%      'y' to a CVX variable so that it can accept 'x' as an element. If
%     you want
%      to accomplish something like this, you must manually convert y into a
%      CVX variable first, as follows:
%         variable x;
%         y = cvx(ones(3,1));
%         y(2) = x;

%
% Test subscripts
%

szx = size( x );
szy = size( y );
nlx = prod( szx );
try
    temp = reshape( 1 : nlx, szx );
    ndx_x = builtin( 'subsasgn', temp, S, zeros( szy ) );
catch errmsg
    throw( errmsg );
end
szx_n = size( ndx_x );
if length( szx_n ) ~= length( szx ),
   szx_n(end+1:length(szx)) = 1;
   szx(end+1:length(szx_n)) = 1;
end

%
% Assign data
%

bx = cvx_basis( x );
if any( szx_n < szx ),
    bx = bx( :, ndx_x );
else
    if any( szx_n > szx ),
        bx( :, end + 1 ) = 0;
        ndx_x( ndx_x == 0 ) = size( bx, 2 );
        bx = bx( :, ndx_x );
        temp = reshape( 1 : prod( szx_n ), szx_n );
    end
    ndx_x = builtin( 'subsref', temp, S );
    ndx_x = ndx_x( : );
    nlz = length( ndx_x );
    by = cvx_basis( y );
    nx = size( bx, 1 );
    [ ny, my ] = size( by );
    if nx < ny,
        if issparse( by ) && ~issparse( bx ), bx = sparse( bx ); end
        bx( ny, : ) = 0;
    elseif nx > ny,
        if issparse( bx ) && ~issparse( by ), by = sparse( by ); end
        by( nx, : ) = 0;
    end
    if my < nlz,
        by = by( :, ones( 1, nlz ) );
    end
    bx( :, ndx_x ) = by;
end

%
% Create the new object
%

x = cvx( szx_n, bx );

% 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 [image,index]=find_color(image,map,tr,colors)
%[IMAGE,IND]=FIND_COLOR(A,MAP,THRESHOLD,COLOR VECTOR)
%Finds a color of an Image A and returns IMAGE, the
%original image with the pixels with the specified color set
%to zero, and IND, an index to the pixels that are were
%equal to the selected color.
%
%MAP is the input if the image is indexed, if the image is not indexed
%enter empty brackerts ( [] ), TR is the threshold tolerance for the
%color range, COLOR VECTOR is an additional argument that takes
%in the hard-coded values for the color, use empty brackects ( [] )
%if you wish to select the color from the origimal image using the mouse.
%
%Composite image, EXAMPLE:
%x=imread('football.jpg');
%subplot(2,1,1);imshow(x);
%title('Before');
%[image,ind]=find_color(x,[],90,[27 80 111]);
%subplot(2,1,2);imshow(image);
%title('After')
%figure
% y=imread('saturn.tif');
% image(328,438,:)=0;
% i= ~(im2bw(image,0.01));
% c=immultiply(y,i);
% c(:,:,2)=c;
% c(:,:,3)=c(:,:,2);
% y(:,:,2)=y;
% y(:,:,3)=y(:,:,1);
% C=imadd(image,c);
% imshow(C)

%by is

I=make_rgb(image,map);

if isempty(colors)
disp('Right click on the color you want off the image with the mouse:') ;

colors=impixel(I);
close
end

[i j]=size(colors);

disp('Wait....');

if i>1,
    colors=colors(1,:);
end
[image,index]= getcolor(I,colors,tr);

disp('Done')

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

function [image,index]=getcolor(I,color,tr)

[i j k]=size(I);
R=color(1,1);
G=color(1,2);
B=color(1,3);
I=double(I);

mask=( abs(I(:,:,1)-R) <tr ) & ( abs(I(:,:,2)-G) <tr ) &( abs(I(:,:,3)-B) <tr );

I(:,:,1)=I(:,:,1).*(~mask);
I(:,:,2)=I(:,:,2).*(~mask);
I(:,:,3)=I(:,:,3).*(~mask);

image=uint8(I);
index=find(mask==1);

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

function I=make_rgb(image,map)

[i j k]=size(image);

if (~isempty(map)),
    I=ind2rgb(image,map);
    I=im2uint8(I);

elseif (isempty(k)),
    I(:,:,2)=I;
    I(:,:,3)=I(:,:,1);

else
I=image;
end


function [dat, mrk] = proc_resample(dat, target_fs, varargin)
%PROC_RESAMPLE - resample the EEG data to a target sampling frequency
%
%Synposis:
% [dat, mrk] = proc_resample(dat, target_fs, <mrk, N>)
%
%Arguments:
%     dat - Structure with fields x and fs. This fields
%     will be overwritten
%     target_fs - the target sampling frequency
%
%     optional (given with keywords or as opt.xxx):
%     mrk - Structure with field time. It will be updated.
%     N - remove the first and last N samples from the resampled data to
%     avoid edge effects (default is 0)
%
%Returns:
%     dat: updated data structure
%     mrk: updated marker structure
%
%Description:
% Resamples the field dat.x such that is has the desired sampling frequency.
% dat.t and mrk (if given) will be updated as well.

% Sven Daehne, 06-2011

props= {'N'     0     '!INT[1]'
        'mrk'   []    'STRUCT'};

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

misc_checkType(dat, 'STRUCT(x fs)');
dat = misc_history(dat);

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

N = opt.N;                  % # samples
Nt = N/target_fs*1000;      % corresponding time in ms
mrk = opt.mrk;

p = round(target_fs*1000);
q = round(dat.fs*1000);

if ndims(dat.x)==3
  nTrials = size(dat.x,3);
  for n= 1:nTrials,
    X(:,:,n) = resample(dat.x(:,:,n), p, q);
  end
else
  X = resample(dat.x, p, q);
end
dat.x = X;
dat.fs = target_fs;
n_samples = size(dat.x,1);
if isfield(dat, 't'),
  t = linspace(dat.t(1), dat.t(end), n_samples);
  dat.t = t; % time in ms
end

% remove the first and the last N samples to avoid edge effects
dat.x = dat.x((N+1):end-N, :, :);
if isfield(dat, 't')
    dat.t = dat.t((N+1):end-N);
end

% Adjust marker if necessary
if N>0 && ~isempty(mrk)
    mrk.time = mrk.time-Nt;
    % Remove markers that refer to data that was cut-off the beginning or
    % end
    rem_idx = [find(mrk.time<=0) find(mrk.time>length(dat.x)/dat.fs*1000)];
    mrk = mrk_selectEvents(mrk,'not',rem_idx);
end


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

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

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

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

%% detect edge and visualize results

path = './data/input/';
files = dir([path, '*.jpg']);
Imgnum = size(files, 1);
result_path = './data/edge_tone/';
mkdir(result_path);
for i=1:Imgnum
    I = imread(strcat(path, files(i,1).name));
    if size(I, 3) < 3
        I = repmat(I, [1,1,3]);
    end
    %%
    E=edgesDetect(I,model);
    imwrite(1-E, strcat(result_path, files(i,1).name(1:end-4),'_edge.jpg'));
    %%
    I=rgb2gray(I);
    nhoodSize = [11, 11];
    smoothValue=0.5*diff(getrangefromclass(I)).^2;
    I=imguidedfilter(I,I,'NeighborhoodSize', nhoodSize, 'DegreeOfSmoothing',smoothValue);
    imwrite(I,strcat(result_path,files(i,1).name(1:end-4),'_gf.jpg'));
end


function [state,options,Aineq,bineq,Aeq,beq] = ...
    psocheckinitialpopulation(state,Aineq,bineq,Aeq,beq,LB,UB,nonlcon,...
    options)
% Checks initial population with respect to linear constraints. Requires
% optimization toolbox.

if exist('linprog','file') ~= 2
    msg = sprintf('Could not find a required function in Optimization ') ;
    msg = sprintf('%s Toolbox. Ignoring (non)linear constraints ',msg) ;
    msg = sprintf('%s for initial population distribution and',msg) ;
    warning('pso:linearconstraints:missingtoolbox',...
        '%s setting constraint behavior to ''soft''.',msg)
    options.ConstrBoundary = 'soft' ;
    return
end

% Some robustness for older versions of optimset
% vv = ver ;
% vernos = {vv.Version} ;
% if str2double(vernos{strcmpi({vv.Name},'MATLAB')}) < 7.7
%     state.LinprogOptions = optimset('Simplex','off',...
%         'LargeScale','off',...
%         'Display','off') ;
% else
    state.LinprogOptions = optimset('Simplex','off',...
        'LargeScale','off',...
        'Algorithm','active-set',...
        'Display','off') ;
% end

state.OutOfBounds = false(options.PopulationSize,1) ;

hw = waitbar(0,'Finding feasible initial positions...') ;
for i = 1:size(state.Population,1)
    if strcmpi(options.LinearConstr.type,'linearconstraints')
        if (~isempty([Aineq,bineq]) && any(Aineq*state.Population(i,:)' - bineq > options.TolCon)) ...
                || (~isempty([Aeq,beq]) && any(abs(Aeq*state.Population(i,:)' - beq) > ...
                options.TolCon))
            % Reposition the ith particle if it is outside of linear
            % constraint boundaries
            [newpoint,unused,exitflag] = ...
                linprog([],Aineq,bineq,Aeq,beq,LB,UB,...
                state.Population(i,:),...
                state.LinprogOptions) ;
            clear unused
            if exitflag == -2
                error('Problem is infeasible due to constraints')
            else
                state.Population(i,:) = reshape(newpoint,1,[]) ;
            end % if exitflag
        end
    elseif strcmpi(options.LinearConstr.type,'nonlinearconstraints')
        [c,ceq] = nonlcon(state.Population(i,:)) ;
        lineq = false ;
        if ~isempty(Aineq)
            lineq = Aineq*state.Population(i,:)' - bineq > ...
                    options.TolCon ;
        end

        % Check constraint boundary type
        if i==1 && ~isempty(ceq) && strcmpi(options.ConstrBoundary,'soft')
            msg = '''Soft'' boundaries don''t work with nonlinear' ;
            msg = sprintf('%s equality constraints.',msg) ;
            warning('pso:initpop:nonlcon',...
                '%s Changing options.ConstrBoundary to ''absorb''.',...
                msg)
            options.ConstrBoundary = 'absorb' ;
        end

        if isempty(ceq) && isempty(Aeq)
            % Keep trying random points within PopInitRange until we
            % find one that satisfies the nonlinear constraints.
            % This method is faster, but it depends on the user setting
            % appropriate values for PopInitRange. It doesn't work with
            % equality constraints, linear or nonlinear. If LB and UB
            % exist, PopInitRange should already have been set to match
            % them.
            while any(c > options.TolCon) || any(lineq)
                state.Population(i,:) = options.PopInitRange(1,:) + ...
                    rand(1,size(options.PopInitRange,2)) .* ...
                    (options.PopInitRange(2,:) - ...
                    options.PopInitRange(1,:)) ;
                c = nonlcon(state.Population(i,:)) ;
                if ~isempty(Aineq)
                    lineq = Aineq*state.Population(i,:)' - bineq > ...
                        options.TolCon ;
                end
            end % while any
        elseif any(c > options.TolCon) || any(abs(ceq) > options.TolCon)
%         if any(c > options.TolCon) || any(abs(ceq) > options.TolCon)
            % Random point rejection is much faster, and produces
            % a more uniform distribution of points within the bounded
            % region. However, using fmincon to find acceptable points will
            % allow simultaneous compliance with linear and boundary
            % constraints, as well as dealing well with nonlinear equality
            % constraints. Appropriate setting of PopInitRange will prevent
            % the initial points from accumulating near the boundaries.
            [newpoint,unused,exitflag] = ...
                fmincon(@void,state.Population(i,:),...
                Aineq,bineq,Aeq,beq,LB,UB,nonlcon,state.LinprogOptions) ;
            clear unused
            if exitflag == -2
                error('Problem is infeasible due to nonlinear constraints')
            else
                state.Population(i,:) = reshape(newpoint,1,[]) ;
            end % if exitflag
        end % if isempty
    end % if strcmpi
    waitbar(i/options.PopulationSize,hw)
end % for i
if ishandle(hw), close(hw), end


classdef printingVigdergauzMicroStructures < handle

    properties (Access = private)
        mesh
        outputName
        pdim
        postprocess
    end

    methods (Access = public)

        function init(obj)
            obj.ouputName = 'VigergauzMicroStructure';
        end

        function obj = printingVigdergauzMicroStructures()
            settings = Settings('VigergauzLevelSetInput');

            settings.superEllipseRatio = tan(pi/6);%tan(pi/5);
            settings.volumeMicro = 0.8;

            translator = SettingsTranslator();
            translator.translate(settings);
            fileName = translator.fileName;
            settingsTopOpt = SettingsTopOptProblem(fileName);
            topOpt = TopOpt_Problem(settingsTopOpt);

            dV = topOpt.designVariable;

        end

    end

    methods (Access = private)

        function createPostProcess(obj)
            dB = obj.createPostProcessDataBase();
            dB.printers = obj.printers;
            postCase = 'NumericalHomogenizer';
            obj.postProcess = Postprocess(postCase,dB);
        end

        function dB = createPostProcessDataBase(obj)
            dI.mesh            = obj.mesh;
            dI.outName         = obj.outputName;
            dI.pdim            = obj.pdim;
            dI.ptype           = 'MICRO';
            ps = PostProcessDataBaseCreator(dI);
            dB = ps.getValue();
        end

    end

end


function Rt = cameraAngleAxis2Rt(vec)

Rt = AngleAxisToRotationMatrix(vec(1:3));
Rt(1:3,4) = vec(4:6);


%--- help for ts/expanding ---
%
%  Applies a function to an expanding window of the time series
%
%  ::
%
%     h = expanding(db,func);
%     h = expanding(db,func,varargin);
%
%  Args:
%
%     db (ts object): time series object to get data
%
%     func: function that will apply to the expanding window of the time
%       series. The function is recursively applied to the data 1:t for
%       t=1,2,3,...,T, where T is the number of observations
%
%     varargin: additional arguments to func
%
%


function test_suite = test_trimeshSurfaceArea
%TEST_TRIMESHSURFACEAREA  Test case for the file trimeshSurfaceArea
%
%   Test case for the file trimeshSurfaceArea

%   Example
%   test_trimeshSurfaceArea
%
%   See also
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-10-17,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

test_suite = functiontests(localfunctions);

function test_Octahedron(testCase) %#ok<*DEFNU>

[v, e, f] = createOctahedron(); %#ok<ASGLU>
area = trimeshSurfaceArea(v, f);

a = sqrt(2);
exp = 2 * sqrt(3) * a * a;

testCase.assertEqual(exp, area, 'AbsTol', .1);


function [GS, pp, info] = slgmm(X, varargin)
%SLGMM Learns Gaussian Mixture model from samples
%
% $ Syntax $
%   - GS = slgmm(X, ...)
%   - [GS, pp] = slgmm(X, ...)
%   - [GS, pp, info] = slgmm(X, ...)
%
% $ Arguments $
%   - GS:       The Gaussian model struct with mixture weights
%   - pp:       the posteriori of samples to component models
%   - info:     the information of learning process
%   - X:        the sample matrix
%
% $ Description $
%   - GS = slgmm(X, ...) learns Gaussian mixture model from samples
%     in matrix X. The following properties can be specified:
%     \*
%     \t    Table. Properties of Learning Gausssian Mixture Model
%     \h    name         &      description                      \\
%          'method'      & The method using for GMM learning. Currently,
%                          there are only one method available: 'EM',
%                          default = 'EM'.
%          'K'           & The number of initial components in the mixture
%                          model (default = 3)                     \\
%          'update'      & The way of updating (default = 'pass'):
%                          1. 'pass'     Pass-wise update;
%                          2. 'comp'     Component-wise update     \\
%          'cyclecn'     & The ratio of components to be updated in each
%                          cycle for 'comp' update scheme. default = 1.
%          'maxiter'     & The maximum number of iterations
%                          (default = 100) \\
%          'tol'         & The maximum tolerance of posteriori error when
%                          the iteration terminates, (default = 1e-6) \\
%          'verbose'     & whether to display information while iteration,
%                          default = true                              \\
%          'annthres'    & The threshold of annealing in FJ algorithm,
%                          default = 0 (unit = average mixture weight) \\
%          'weights'     & The weights of the samples, default = [],
%                          indicating non-weighted. Weights should be given
%                          by a 1 x n row vector. \\
%          'varform'     & The form of variance: 'univar'|'diagvar'|'covar',
%                          default = 'covar';          \\
%          'sharevar'    & Whether the variance is shared by all models,
%                          default = false;            \\
%          'invparams'   & The parameters for computing inverse of variance
%                          default = {}                \\
%
% $ Remarks $
%   - In current version, the component-wise update scheme is only
%     supported when sharevar is false.
%
% $ History $
%   - Created by Dahua Lin, on Aug 28, 2006
%

%% parse and verify input arguments

if ~isnumeric(X) || ndims(X) ~= 2
    error('sltoolbox:invalidarg', ...
        'X should be a 2D numeric matrix');
end

opts.method = 'EM';
opts.K = 3;
opts.update = 'pass';
opts.cyclecn = 1;
opts.maxiter = 100;
opts.tol = 1e-6;
opts.verbose = true;
opts.annthres = 0;
opts.weights = [];
opts.varform = 'covar';
opts.sharevar = false;
opts.invparams = {};
opts = slparseprops(opts, varargin{:});

n = size(X, 2);

%% initialization by random clustering

if opts.K > n
    error('sltoolbox:sizoverflow', ...
        'The K is larger than the number of samples');
end

init_centerinds = randsample(n, opts.K);
init_centers = X(:, init_centerinds);
initc = slclassify_eucnn(init_centers, X);

%% perform learning based on FMM

estfunctor = {@gmm_estfunc, opts.varform, opts.sharevar, opts.invparams};
evalfunctor = {@gmm_evalfunc};

[GS, cw, pp, info] = slfmm(X, n, estfunctor, evalfunctor, ...
    'method', opts.method, ...
    'update', opts.update, ...
    'cyclecn', opts.cyclecn, ...
    'iter', {'maxiter', opts.maxiter}, ...
    'tol', opts.tol, ...
    'verbose', opts.verbose, ...
    'initc', initc, ...
    'annthres', opts.annthres, ...
    'weights', opts.weights, ...
    'estmode', 'innermul', ...
    'condpmode', 'log', ...
    'manifunc', @gmm_manifunc);

%% post actions

GS.mixweights = cw;

%% Core slot functions

function GS = gmm_estfunc(GS, X, n, W, selinds, varform, sharevar, invparams)

slignorevars(n);

if isempty(selinds)
    GS = slgaussest(X, 'weights', W, ...
        'varform', varform, 'sharevar', sharevar, ...
        'compinv', true, 'invparams', invparams);
else
    if sharevar
        error('sltoolbox:rterror', ...
            'The selective updating scheme is only supported when sharevar is false');
    end

    Wsel = W(selinds, :);
    GSu = slgaussest(X, 'weights', Wsel, ...
        'varform', varform, 'sharevar', sharevar, ...
        'compinv', true, 'invparams', invparams);

    nu = length(selinds);
    switch varform
        case 'univar'
            for idx = 1 : nu
                iu = selinds(idx);
                GS.means(:, iu) = GSu.means(:,idx);
                GS.vars(iu) = GSu.vars(idx);
                GS.invvars(iu) = GSu.invvars(idx);
            end
        case 'diagvar'
            for idx = 1 : nu
                iu = selinds(idx);
                GS.means(:, iu) = GSu.means(:, idx);
                GS.vars(:, iu) = GSu.vars(:, idx);
                GS.invvars(:, iu) = GSu.invvars(:, idx);
            end
        case 'covar'
            for idx = 1 : nu
                iu = selinds(idx);
                GS.means(:, iu) = GSu.means(:, idx);
                GS.covs(:,:, iu) = GSu.covs(:,:, idx);
                GS.invcovs(:,:, iu) = GSu.invcovs(:,:, idx);
            end
    end

end

function condp = gmm_evalfunc(GS, X, n)

slignorevars(n);
condp = slgausspdf(GS, X, 'output', 'log');

function GS = gmm_manifunc(GS0, op, varargin)

switch op
    case 'select'

        selinds = varargin{1};

        tyi = slgausstype(GS0);

        GS.dim = GS0.dim;
        GS.nmodels = length(selinds);
        GS.means = GS0.means(:, selinds);

        switch tyi.varform
            case {'univar', 'diagvar'}
                if tyi.sharevar
                    GS.vars = GS0.vars;
                    GS.invvars = GS0.invvars;
                else
                    GS.vars = GS0.vars(:, selinds);
                    GS.invvars = GS0.invvars(:, selinds);
                end
            case 'covar'
                if tyi.sharevar
                    GS.covs = GS0.covs;
                    GS.invcovs = GS0.invcovs;
                else
                    GS.covs = GS0.covs(:,:,selinds);
                    GS.invcovs = GS0.invcovs(:,:,selinds);
                end
        end

    otherwise
        error('sltoolbox:invalidarg', ...
            'Unsupported manipulation option for GMM: %s', op);
end


function [intra, inter, Qnodes, Fnodes, Onode] = mk_hhmm_topo_F1(D, all_Q_to_Qs, Ops)
% MK_HHMM_TOPO Make Hierarchical HMM topology assuming level 1 can finish
% function [intra, inter, Qnodes, Fnodes, Onode] = mk_hhmm_topo(D, all_Q_to_Qs, Ops, F1)
%
% D is the depth of the hierarchy
% If all_Q_to_Qs = 1, level i connects to all levels below, else just to i+1 [0]
% Ops are the Q parents of the observed node [Qnodes(end)]
% If F1=1, level 1 can finish (restart), else there is no F1->Q1 arc [0]

Qnodes = 1:D;

if nargin < 2, all_Q_to_Qs = 1; end
if nargin < 3, Ops = Qnodes(D); end
if nargin < 4, F1 = 0; end

if F1
  Fnodes = 2*D:-1:D+1; % must number from bottom to top
  Onode = 2*D+1;
  ss = 2*D+1;
else
  Fnodes = (2*D)-1:-1:D+1;
  Onode = 2*D;
  ss = 2*D;
end

intra = zeros(ss);
intra(Ops, Onode) = 1;
for d=1:D-1
  if all_Q_to_Qs
    intra(Qnodes(d), Qnodes(d+1:end)) = 1;
  else
    intra(Qnodes(d), Qnodes(d+1)) = 1;
  end
end
for d=D:-1:3
  intra(Fnodes(d), Fnodes(d-1)) = 1;
end
if F1
  intra(Fnodes(2), Fnodes(1)) = 1;
end
if all_Q_to_Qs
  for d=1:D
    intra(Qnodes(d), Fnodes(d:end)) = 1;
  end
else
  for d=1:D
    if d < D
      intra(Qnodes(d), Fnodes([d d+1])) = 1;
    else
      intra(Qnodes(d), Fnodes(d)) = 1;
    end
  end
end

inter = zeros(ss);
for d=1:D
  inter(Qnodes(d), Qnodes(d)) = 1;
end
for d=1:D
  if d==1
    inter(Fnodes(d), Qnodes(d)) = 1;
  else
    inter(Fnodes(d), Qnodes([d-1 d])) = 1;
  end
end


function MASKSTATS = canlab_maskstats(msks,imgs,varargin)
% Produces comparison of pattern mask and images
% e.g., look at NPS pattern expression in set of beta images
%
% :Usage:
% ::
%
%    MASKSTATS = canlab_maskstats(maskfiles,imgfiles,[options])

% :Inputs:
%
%   **maskfiles:**
%      string or cellstring of mask filenames or fmri_data object

%   **imgfiles:**
%      string or cellstring of image filenames or fmri_data object
%
% :Optional Inputs:
%
%   **ts:**
%        timeseries treatment: each string in imgfiles is assumed to be
%        a 4D file. Data will be returned with one column per time series and
%        one volume per row. If not all timeseries are same length, all will
%        be NaN-padded to the length of the longest timeseries.
%
%        Note: does not work with imgfiles input as fmri_data object
%
%   **dir2cell:**
%        will sort stats into cells based on directory containing the imgfile
%        they belong to such that each cell contains one directory's worth of
%        stats which is a vector with a value for each imgfile.
%        :Examples:
%        ::
%
%             # Input: a list of single trial betas for a set of subjects
%             b = filenames('sub*/*heat_trials*.img');
%             ms = canlab_maskstats('nps',b,'dot_product','dir2cell');
%
%        Output: includes the set of cells that are input to a mediation
%        analysis.
%
%   **keepzeros:**
%        don't remove zeros from imgfiles before taking measurements
%
%   **keepzerosmask:**
%        don't remove zeros from maskfiles before taking measurements
%
%   **single:**
%        leave data as single (DEFAULT: convert to double)
%
%   **trinarize:**
%        trinarize maskfile (set values larger than 0 to 1 and values less than
%        zero to -1)
%
%   **noreshape:**
%        don't attempt to reshape results according to imgfiles array
%
%   **nobin:**
%        don't binarize mask before extracting mean or std
%
% :Note: ts, dir2cell, and noreshape are mutually exclusive options
%
% **Built-In Masks**
% The following strings can be given as the maskfile argument to
% call up built-in mask files:
%
%   **nps:**
%        weights_NSF_grouppred_cvpcr.img
%
%   **nps_thresh:**
%        weights_NSF_grouppred_cvpcr_FDR05.img
%
%   **nps_thresh_smooth:**
%        weights_NSF_grouppred_cvpcr_FDR05_smoothed_fwhm05.img
%
% :Measure Options:
%
%   **all:**
%        add: mean, dot_product, centered_dot_product,
%             cosine_similarity, and correlation
%
%   **mean:** (DEFAULT)
%      apply binarized mask to images and return means
%      mean(img .* abs(bin(mask)))
%
%   **std:**
%        apply binarized mask to images and return standard deviations
%        std(img .* abs(bin(mask)))
%
%   **dot_product:**
%        dot(mask, img)
%
%   **cosine_similarity:**
%        dot(mask, img) / (norm(mask) * norm(img))
%
%   **correlation:**
%        corr(mask, img)
%
%   **centered_dot_product:**
%        dot(mask-mean(mask), img-mean(img))
%
%
% :Details:
%   - imgfiles are spatially resampled to maskfiles
%   - voxels with zeros in maskfile are removed
%   - in-mask voxels with zeros in imgfiles will generate warnings
%
% ..
%    AUTHOR: Luka Ruzic 2013
% ..

OP = {}; % struct to contain desired "operations" (e.g., dot product, mean, etc)
%% parse arguments
ALLOPS = false; % adds all implemented operations
DO_TRINARIZE = false; % signed binarize option
DO_ZERO2NAN_DATA = true; % treat zeros as non-data in data input
DO_ZERO2NAN_MASK = true; % treat zeros as non-data in mask input
DO_RESHAPE = true; % attempt to reshape output data according to shape of input data
DO_BIN = true; % binarize mask
DO_TS = false; % timeseries mode
DO_CELLS = false; % cell array output mode

i=1;
while i<=numel(varargin)
    if ischar(varargin{i})
        switch varargin{i}
            case {'binmean' 'mean' 'norm' ...
                  'dot_product' 'centered_dot_product' 'cosine_similarity' 'correlation'}
                OP{end+1} = varargin{i}; %#ok
            case 'all'
                ALLOPS = true;
            case 'keepzeros'
                DO_ZERO2NAN_DATA = false;
            case 'keepzerosmask'
                DO_ZERO2NAN_MASK = false;
            case 'trinarize'
                DO_TRINARIZE = true;
            case 'nobin'
                DO_BIN = false;
            case 'noreshape'
                DO_RESHAPE = false;
                DO_CELLS = false;
                DO_TS = false;
            case 'ts'
                DO_RESHAPE = true;
                DO_TS = true;
                DO_CELLS = false;
            case 'dir2cell'
                DO_RESHAPE = true;
                DO_CELLS = true;
                DO_TS = false;
            otherwise
                error('Unrecognized argument %s',varargin{i})
        end
    elseif iscellstr(varargin{i})
        for j=1:numel(varargin{i})
            switch varargin{i}{j}
                case {'binmean' 'mean' 'std' 'nonbinmean' 'nonbinstd' 'norm' ...
                        'dot_product' 'centered_dot_product' 'cosine_similarity' 'correlation'}
                    OP{end+1} = varargin{i}{j}; %#ok
                case 'all'
                    ALLOPS = true;
                otherwise
                    error('Unrecognized argument %s',varargin{i}{j})
            end
        end
    else
        disp(varargin{i})
        error('Above argument unrecognized')
    end
    i=i+1;
end

if ALLOPS, OP = [OP 'mean' 'std' 'dot_product' 'centered_dot_product' 'cosine_similarity' 'correlation']; end

if isempty(OP), OP = {'mean'}; end

%% error checking
if isempty(msks), error('Must provide one or more maskfiles'); end
if ischar(msks), msks = cellstr(msks); end
if ~iscellstr(msks) && ~isa(msks,'fmri_data'), error('maskfiles must be a string, cell array of strings, or fmri_data object');end

if isempty(imgs), error('Must provide one or more imgfiles'); end
if ischar(imgs), imgs = cellstr(imgs); end
if ~iscellstr(imgs) && ~isa(imgs,'fmri_data'), error('imgfiles must be string, cell array of strings, or fmri_data object'); end

MASKSTATS(numel(msks)) = struct; % initializing

%% prepare mask files
if ~isa(msks,'fmri_data')
    for m = 1:numel(msks)
        switch msks{m}
            case 'nps'
                msks{m} = which('weights_NSF_grouppred_cvpcr.img');
            case 'nps_thresh'
                msks{m} = which('weights_NSF_grouppred_cvpcr_FDR05.img');
            case 'nps_thresh_smooth'
                msks{m} = which('weights_NSF_grouppred_cvpcr_FDR05_smoothed_fwhm05.img');
            otherwise
                if ~exist(msks{m},'file')
                    error('No such file: %s',msks{m})
                end
        end
    end
end

%% prepare data
% fprintf('LOADING IMAGE FILES\n')
if isa(imgs,'fmri_data')
    imgdata = imgs;
    imgdata = imgdata.replace_empty;
    if DO_TS
        warning('''ts'' mode is incompatible with fmri_data input: turning off'); %#ok
        DO_TS = false;
    end
    imgfiles = cellstr(imgdata.fullpath);
else
    imgfiles = imgs;
    evalc('imgdata = fmri_data(imgfiles);');
end

imgdata.dat = double(imgdata.dat); % convert singles to doubles
if DO_ZERO2NAN_DATA, imgdata.dat(imgdata.dat==0) = NaN; end  % remove zeros if desired

if DO_TS
    for i = 1:numel(imgfiles)
        ni = nifti(imgfiles{i});
        tsdim(i) = ni.dat.dim(4); %#ok
    end
end

if DO_CELLS
%     [ignore1 ignore2 x] = unique(regexprep(imgfiles,'/[^/]*$','')); %#ok
    [ignore1 ignore2 x] = unique(regexprep(cellstr(imgdata.fullpath),'/[^/]*$','')); %#ok
    reshaperows = histc(x,1:max(x));
end

%% produce comparison
if isa(msks,'fmri_data')
    allmaskdata = msks;
    allmaskdata = allmaskdata.replace_empty;
    nmasks = size(allmaskdata.dat,2);
else
    nmasks = numel(msks);
end
for m = 1:nmasks
    clear imgdat maskdat imgdatcent maskdatcent imgdatnorm maskdatnorm

    % save filenames
    % imgs (modify cell array according to mode)
    if DO_CELLS
        for i = 1:numel(reshaperows)
            st = sum(reshaperows(1:i-1))+1;
            MASKSTATS(m).imgfiles{i} = imgfiles(st:st+reshaperows(i)-1);
        end
    elseif DO_TS
        MASKSTATS(m).imgfiles = imgfiles';
    else
        MASKSTATS(m).imgfiles = imgfiles;
    end

    % load and prep mask data

    if isa(msks,'fmri_data')
        maskdata = allmaskdata;
        maskdata.dat(:,[1:size(allmaskdata.dat,2)]~=m) = [];
        MASKSTATS(m).maskfile = deblank(allmaskdata.fullpath(m,:));
    else
        evalc('maskdata = fmri_data(msks{m});');
        MASKSTATS(m).maskfile = msks{m};
    end
    fprintf('GETTING DATA FOR MASK: %s\n',MASKSTATS(m).maskfile);
    maskdata.dat = double(maskdata.dat); % convert singles to doubles
    %if DO_ZERO2NAN_MASK, maskdata.dat(maskdata.dat == 0) = NaN; end % SHOULD THIS HAPPEN HERE?   remove zeros
    maskdata = maskdata.resample_space(imgdata); % resample
    if DO_ZERO2NAN_MASK, maskdata.dat(maskdata.dat == 0) = NaN; end % remove zeros

    % select in-mask voxels
    wh_inmask = ~isnan(maskdata.dat);
    maskdat = maskdata.dat(wh_inmask);
    imgdat = imgdata.dat(wh_inmask,:);

    % trinarize
    if DO_TRINARIZE
        maskdat(maskdat<0) = -1;
        maskdat(maskdat>0) = 1;
    end

    % warn about in-mask zeros
    if DO_ZERO2NAN_DATA
        inmaskzeros = isnan(imgdat);
        if any(inmaskzeros)
            fprintf('WARNING! There are zeros in your data within this mask!\n')
            %fprintf('Consider carefully whether this impairs your ability to compare data points.\n')
            %fprintf('  These are being ignored as non-data but your results will be impacted!\n')
            for i = find(sum(inmaskzeros))
                fprintf(' %7d in-mask zeros in %s\n',sum(inmaskzeros(:,i)),deblank(imgdata.fullpath(i,:)));
            end
        end
    end

    % perform operation(s)
    for i = 1:numel(OP)
        switch OP{i}
            case 'mean'
                if DO_BIN
                    MASKSTATS(m).stats.mean = nanmean(imgdat)';
                else
                    MASKSTATS(m).stats.nonbinmean = nanmean(bsxfun(@times,imgdat,maskdat))';
                end

            case 'std'
                if DO_BIN
                    MASKSTATS(m).stats.std = nanstd(imgdat)';
                else
                    MASKSTATS(m).stats.nonbinstd = nanstd(bsxfun(@times,imgdat,maskdat))';
                end

            case 'norm'
                MASKSTATS(m).stats.norm = (nansum(imgdat .^ 2) .^ .5)';

            case 'dot_product'
                MASKSTATS(m).stats.dot_product = nansum(bsxfun(@times,imgdat,maskdat))';

            case 'centered_dot_product'
                imgdatcent = bsxfun(@minus,imgdat,nanmean(imgdat));
                maskdatcent = bsxfun(@minus,maskdat,nanmean(maskdat));
                MASKSTATS(m).stats.centered_dot_product = nansum(bsxfun(@times,imgdatcent,maskdatcent))';

            case 'cosine_similarity'
                imgdatnorm = nansum(imgdat .^ 2) .^ .5;
                maskdatnorm = nansum(maskdat .^ 2) .^ .5;
                MASKSTATS(m).stats.cosine_similarity = (nansum(bsxfun(@times,imgdat,maskdat)) ./ (imgdatnorm .* maskdatnorm))';

            case 'correlation'
                MASKSTATS(m).stats.correlation = corr(imgdat,maskdat,'rows','pairwise');

            otherwise
                error('Comparison type (%s) unrecognized',OP{i})
        end

        % reshape according to mode
        if DO_RESHAPE
            if DO_TS
                if numel(unique(tsdim)) == 1
                    tslen = tsdim(1);
                else
                    % not all timeseries are same length
                    % assume all start at same time and pad with NaNs
                    tslen = max(tsdim);
                    for j = 1:numel(tsdim)
                        cutind = ((j-1)*tslen) + tsdim(j);
                        MASKSTATS(m).stats.(OP{i}) = [...
                            MASKSTATS(m).stats.(OP{i})(1:cutind); ...
                            nan(tslen-tsdim(j),1); ...
                            MASKSTATS(m).stats.(OP{i})(cutind+1:end)];
                    end
                    % alternative coding option: vector -> cells -> NaN-pad the cells -> cell2mat %
                end
                MASKSTATS(m).stats.(OP{i}) = reshape(MASKSTATS(m).stats.(OP{i}),[tslen numel(imgfiles)]);
            elseif DO_CELLS
                MASKSTATS(m).stats.(OP{i}) = mat2cell(MASKSTATS(m).stats.(OP{i}),reshaperows,1)';
            else
                try MASKSTATS(m).stats.(OP{i}) = reshape(MASKSTATS(m).stats.(OP{i}),size(imgfiles)); end %#ok
            end
        end
    end
end

end


function [ G ] = gsp_update_weights( G, W )
%GSP_UPDATE_WEIGHTS update weight matrix of the graph G
%   Usage: G = gsp_update_weight( G, W );
%
%   Input parameters
%       G   : Graph
%       W   : W new weight matrix
%   Output parameters
%       G   : Graph
%
%   This function will update the weight of graph and recompute the
%   Laplacian the new Laplacian. It will also recompute the value *G.lmax*
%   if it is present in the graph.
%
%   For now this function does not recompute the Fourier basis!
%
%   Example::
%
%          G.W = Wnew;
%          G = gsp_graph_default_parameters( G );
%
%
%   See also: gsp_graph_default_parameters gsp_graph
%

% Author: Nathanael Perraudin
% Date  : 19.11.2014

G.W = W;

if isfield(G,'U')
    G = rmfield(G,'U');
end

if isfield(G,'e')
    G =rmfield(G,'e');
end

if isfield(G,'mu')
    G =rmfield(G,'mu');
end

G = gsp_graph_default_parameters(G);

if isfield(G,'lmax')
    G = rmfield(G,'lmax');
    G = gsp_estimate_lmax(G);
end

end


function ypost = fmri_spatfil(ypre, SpatialFil)
%
% ypost = fmri_spatfil(ypre, SpatialFilter)
%
% Spatially filters a functional slice.
%
% -------- Input Arguments ------
% 1. ypre - functional slice to be processed. Dimension is
%       [nRows nCols nTP nRuns].
% 2. SpatialFilter - coefficients of spatial filter (2D).
%
% -------- Output Arguments ------
% 1. ypost - spatially filtererd slice of the same dimension
%       as the preprocessed slice, ie, [nRows nCols nTP nRuns].
%
% Douglas Greve (greve@nmr.mgh.harvard.edu)
% January 25, 1999
% February 12, 1999
%
% $Id: fmri_spatfilter.m,v 1.1 2004/03/11 01:30:19 sayres Exp $
%

% Check that the number of input arguments is correct %
if(nargin ~= 2)
  msg = 'ypost = fmri_spatfil(ypre, SpatialFilter)';
  qoe(msg);error(msg);
end

% Get function slice dimensions %
nRows = size(ypre,1);
nCols = size(ypre,2);
nTP   = size(ypre,3);
nRuns = size(ypre,4);
nVoxels = nRows*nCols;

y = ones(nRows,nCols);
EdgeCorrection = conv2(y,SpatialFil,'same');

%%% Initialize matricies %%
ypost = zeros(nRows,nCols,nTP,nRuns);

%% Pass through each run %%
for r = 1:nRuns,

  %% Put slice in a temporary variable %%
  y = ypre(:,:,:,r);

  %% Pass through each time point %%
  for n = 1:nTP,
     z = conv2(y(:,:,n),SpatialFil,'same') ./ EdgeCorrection;
     y(:,:,n) = z;
   end

  ypost(:,:,:,r) = reshape(y, [nRows nCols nTP]);

end

return;


function segmentation = PTKGetSurfaceFromSegmentation(segmentation, exclude_direction)
    % PTKGetSurfaceFromSegmentation. Finds the surface of a segmented 3D binary volume.
    %
    % The input and output images are raw image matrices containing a mask of 0s
    % and 1s where 1 is a segmented voxel.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2012.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    if nargin < 2
        exclude_direction = [];
    end

    segmentation = int8(segmentation > 0);

    % Find voxels that are nonzero and do not have 6 nonzero neighbours
    filter = zeros(3, 3, 3);
    if isempty(exclude_direction)
        filter(:) = [0 0 0 0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0];
    elseif exclude_direction == PTKImageOrientation.Coronal
        filter(:) = [0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0];
    else
        error('PTKGetSurfaceFromSegmentation:UnsupportedExcludeDirection', 'Unsupported exclude direction');
    end
    max_neighbours = sum(filter(:));
    image_conv = convn(segmentation, filter, 'same');
    segmentation = (segmentation & (image_conv < max_neighbours));
end


function [x]=mesh
%------------------------------------------------
% GENERATE MATCHING DISTANCE X FOR DIFFERENT MESH
% -----------------------------------------------
global N L
dx=L/N;
x(1)=0;
x(2)=dx/2;
for i=3:N+1
    x(i)=x(i-1)+dx;
end
x(N+2)=L;


function Z = minus(X,Y)
%MINUS Binary subtraction (-) for tenmat.
%
%   See also TENMAT, TENMAT/TENMATFUN.
%
%MATLAB Tensor Toolbox.
%Copyright 2012, Sandia Corporation.

% This is the MATLAB Tensor Toolbox by T. Kolda, B. Bader, and others.
% http://www.sandia.gov/~tgkolda/TensorToolbox.
% Copyright (2012) Sandia Corporation. Under the terms of Contract
% DE-AC04-94AL85000, there is a non-exclusive license for use of this
% work by or on behalf of the U.S. Government. Export of this data may
% require a license from the United States Government.
% The full license terms can be found in the file LICENSE.txt

fun = @minus;

% One argument is a scalar
if ((prod(size(X)) == 1 || prod(size(Y)) == 1))
  if (prod(size(Y)) == 1) && isa(X,'tenmat')
    Z = X;
    Z.data = fun(Z.data,Y);
  else
    Z = Y;
    Z.data = fun(X,Z.data);
  end
  return;
end

% Both arguments are tenmats
Z = tenmat(Y);
if ~(isequal(size(Y),size(Z)))
  error('Tenmat size mismatch.')
end
Z.data = fun(X.data,Z.data);


function visualizetiles(board, orientation, tiles, visualizationMethod)
% VISUALIZETILES Draws the board and the tiles

% The MATLAB Contest Team
% Copyright 2012 The MathWorks, Inc.

clf;
if visualizationMethod == 1
    BoardVisualizer(tiles, board, orientation);
elseif visualizationMethod == 2
    ScoreVisualizer(tiles, board ,orientation);
end

end

function h = BoardVisualizer(tiles, pos, rot)

[row,col] = size(pos);
boardcapacity = nnz(pos);
y_tile_loc = (pos.') ~= 0;
x_tile_loc = (pos.') ~= 0;

%Rotate tiles matrix into correct position
tiles = rotateTiles(tiles,rot);

%Rearrange tiles and add zeros
inds = pos';
inds = inds(:);
inds(inds == 0) = [];
tiles = tiles(inds,:);

%Set up figure
axis equal
axis off
hold on
colormap(rot90(pink,2));
set(gcf,'color','w')

%Plot background mesh
h.mesh = mesh(0:col,0:row,zeros(row+1,col+1));
set(h.mesh,'facealpha',0,'linewidth',1,'edgecolor','k');

if isempty(tiles)
    return;  % empty board -- nothing else to do
end

%Plot patch for north, east, south, and west wedges
X = repmat([0:col-1; .5:col; 1:col],1,row);
X = X(:,x_tile_loc);
y1 = repmat(row:-1:1,col,1);
y1 = y1(y_tile_loc);
Y = [reshape(y1,1,boardcapacity);
    reshape(y1,1,boardcapacity)-.5;
    reshape(y1,1,boardcapacity)];
h.north = patch('XData',X, 'YData',Y, 'CDataMapping','scaled', 'CData',tiles(:,1)','linestyle','none', 'FaceColor','flat');
hold on
Xt = X(2,:);
Yt = Y(1,:) - 1/6;
h.northText = text(Xt,Yt,num2str(tiles(:,1)),'fontweight','bold');

X = repmat([1:col; .5:col; 1:col],1,row);
X = X(:,x_tile_loc);
y1 = repmat(row:-1:1,col,1);
y1 = y1(y_tile_loc);
Y = [reshape(y1,1,boardcapacity);
    reshape(y1,1,boardcapacity)-.5;
    reshape(y1,1,boardcapacity)-1];
h.east = patch('XData',X, 'YData',Y, 'CDataMapping','scaled', 'CData',tiles(:,2)','linestyle','none', 'FaceColor','flat');
Xt = X(1,:) - 1/6;
Yt = Y(2,:);
h.eastText = text(Xt,Yt,num2str(tiles(:,2)),'fontweight','bold');

X = repmat([0:col-1; .5:col; 1:col],1,row);
X = X(:,x_tile_loc);
y1 = repmat(row-1:-1:0,col,1);
y1 = y1(y_tile_loc);
Y = [reshape(y1,1,boardcapacity);
    reshape(y1,1,boardcapacity)+.5;
    reshape(y1,1,boardcapacity)];
h.south = patch('XData',X, 'YData',Y, 'CDataMapping','scaled', 'CData',tiles(:,3)','linestyle','none', 'FaceColor','flat');
Xt = X(2,:);
Yt = Y(1,:) + 1/6;
h.southText = text(Xt,Yt,num2str(tiles(:,3)),'fontweight','bold');

X = repmat([0:col-1; .5:col; 0:col-1],1,row);
X = X(:,x_tile_loc);
y1 = repmat(row:-1:1,col,1);
y1 = y1(y_tile_loc);
Y = [reshape(y1,1,boardcapacity);
    reshape(y1,1,boardcapacity)-.5;
    reshape(y1,1,boardcapacity)-1];
h.west = patch('XData',X, 'YData',Y, 'CDataMapping','scaled', 'CData',tiles(:,4)','linestyle','none', 'FaceColor','flat');
Xt = X(1,:) + 1/6;
Yt = Y(2,:);
h.westText = text(Xt,Yt,num2str(tiles(:,4)),'fontweight','bold');

clim = [min(tiles(:)), max(tiles(:))];
range = diff(clim);
clim(1) = clim(1) - 0.1*range;
clim(2) = clim(2) + 0.1*range;
set(gca,'CLim',clim);
end

function h = ScoreVisualizer(tiles,pos,rot)

%Get size information and initialize values matrix
brow = size(pos,1);
bcol = size(pos,2);
bsize = [brow, bcol];
vsize = [2*brow+1,bcol+1];

%Rotate tiles matrix into correct position
tiles = rotateTiles(tiles,rot);
%Determine the score of each element in values matrix
values = evaluateBoard(tiles,pos,vsize,bsize);

h = drawResults(values,bsize);
end

function tout = rotateTiles(tin,rot)
tout = zeros(size(tin));
for i = 1:length(rot)
    tout(i,:) = circshift(tin(i,:), [0 1-rot(i)]);
end
end

function values = evaluateBoard(tiles,pos,vsize,bsize)
values = zeros(vsize(1),vsize(2));
values(logical(mod(1:vsize(1),2)),end) = NaN(bsize(1)+1,1);
for r = 1:2:vsize(1)
    for c = 1:vsize(2)-1
        above = (r-1)/2;
        below = (r+1)/2;
        if r == 1 %first row
            if pos(below,c) ~= 0
                values(r,c) = abs(tiles(pos(below,c),1));
            end
        elseif r == vsize(1) %last row
            if pos(above,c) ~= 0
                values(r,c) = abs(tiles(pos(above,c),3));
            end
        else %middle rows
            if pos(below,c) ~= 0 && pos(above,c) ~= 0
                values(r,c) = abs(tiles(pos(above,c),3)-...
                    tiles(pos(below,c),1));
            elseif pos(below,c) ~= 0 && pos(above,c) == 0
                values(r,c) = abs(tiles(pos(below,c),1));
            elseif pos(below,c) == 0 && pos(above,c) ~= 0
                values(r,c) = abs(tiles(pos(above,c),3));
            end
        end
    end
end
for r = 2:2:vsize(1)
    for c = 1:vsize(2)
        left = c-1;
        right = c;
        if c == 1 % first column
            if pos(r/2,right) ~= 0
                values(r,c) = abs(tiles(pos(r/2,right),4));
            end
        elseif c == vsize(2) % last column
            if pos(r/2,left) ~= 0
                values(r,c) = abs(tiles(pos(r/2,left),2));
            end
        else % middle columns
            if pos(r/2,right) ~= 0 && pos(r/2,left) ~= 0
                values(r,c) = abs(tiles(pos(r/2,right),4)-...
                    tiles(pos(r/2,left),2));
            elseif pos(r/2,right) ~= 0 && pos(r/2,left) == 0
                values(r,c) = abs(tiles(pos(r/2,right),4));
            elseif pos(r/2,right) == 0 && pos(r/2,left) ~= 0
                values(r,c) = abs(tiles(pos(r/2,left),2));
            end
        end
    end
end
end

function h = drawResults(values,b)
%Define x coordinates of patches
X = repmat([  0:b(2)-1  -0.5:b(2)  ;
    0.5:b(2)       0:b(2)  ;
    1:b(2)     0.5:b(2)+1;
    0.5:b(2)       0:b(2)   ],1,b(1));
X = [X [  0:b(2)-1  ;
    0.5:b(2)    ;
    1:b(2)    ;
    0.5:b(2)]];

%Define y coordinates of patches
Y =    repmat([b(1)     b(1)-.5  b(1)     b(1)+.5]',1,b(2));
Y = [Y repmat([b(1)-.5  b(1)-1   b(1)-.5  b(1)   ]',1,b(2)+1)];
Y = repmat(Y,1,b(1));
start = 1;
for i = 1:b(1)
    Y(:,start:i*(b(2)*2+1)) = Y(:,start:i*(b(2)*2+1)) - (i-1);
    start = i*(b(2)*2+1) + 1;
end
Y = [Y repmat([0 -.5 0 .5]',1,b(2))];

%Define colors of patches
C = values';
C = C(:)';
C(isnan(C)) = [];

h.p = patch(X,Y,C);
set(h.p,'linestyle','none');
axis equal
axis off
set(gcf,'color','k')
colormap copper
if max(values(:)) < 1e-8
    set(gca,'climmode','manual','clim',[0 1]);
end

hold on
h.m = mesh(0:b(2),0:b(1),zeros(b(1)+1,b(2)+1));
set(h.m,'facealpha',0,'linewidth',2,'edgecolor','w')
hold off
end


function code=sparse_code_wrapper(test)
    tic;
	n=length(test.X); dim=size(test.X{1},1);
    if iscell(test.B)
        code=zeros(length(test.B),n);
    else
        code = zeros(size(test.B,2),n);
    end
	if ~isfield(test,'gamma')
		test.gamma=0;
	end
	for i=1:n
		if isfield(test,'X')
			out = sdivLasso(test.B, test.X{i}, test.lambda, test.numiter, test.algo, test.gamma);
			code(:,i) = out.x;
		end
	end
end


function [K, Kc] = sdrbfKernCompute(sdrbfKern, t1, t2)

% SDRBFKERNCOMPUTE Compute the SDRBF kernel given the parameters and t1.
% FORMAT
% DESC computes the kernel matrices for the switching dynamical radial
% basis function kernel. It is used together with the switching dynamical
% latent force model. The kernel matrices are stored in a cell structure
% and each component of the cell corresponds to the kernel matrix of a
% particular sequence of latent forces.
% ARG kern : the kernel structure for which the matrix is computed.
% ARG t1 : the input points associated with the rows of the kernel.
% ARG t2 : the input points associated with the columns of the kernel.
% RETURN K : the kernel matrices computed at the given points.
% RETURN Kc : the kernel matrices grouped in cells. Suitable form for the
% sparse approximations.
%
% FORMAT
% DESC computes the kernel matrices for the switching dynamical radial
% basis function kernel. It is used together with the switching dynamical
% latent force model. The kernel matrices are stored in a cell structure
% and each component of the cell corresponds to the kernel matrix of a
% particular sequence of latent forces.
% ARG kern : the kernel structure for which the matrix is computed.
% ARG t1 : input data matrix in the form of a design matrix.
% RETURN K : the kernel matrix computed at the given points.
% RETURN Kc : the kernel matrices grouped in cells. Suitable form for the
% sparse approximations.
%
% SEEALSO : rbfKernParamInit, kernCompute, kernCreate, rbfKernDiagCompute
%
% COPYRIGHT : Mauricio A. Alvarez, 2010

% KERN

if nargin < 3
    t2 = t1;
end

if size(t1, 2) > 1 || size(t2, 2) > 1
    error('Input can only have one column');
end

%Form the basic kernels
rbfKern = struct();

% Create structures that will make easy the computation of the kernels
% spVector = [sdrbfKern.switchingTimes t1(end)+0.1]; % For the last interval include the last point

spVector = [cumsum(sdrbfKern.switchingTimes) t1(end)+50];

dim1 = zeros(1, sdrbfKern.nIntervals);
dim2 = zeros(1, sdrbfKern.nIntervals);

for i =1:sdrbfKern.nIntervals
    for j=1:sdrbfKern.nlfPerInt
        rbfKern(i,j).variance = sdrbfKern.variance;
        rbfKern(i,j).inverseWidth = sdrbfKern.inverseWidth(j,i);
        rbfKern(i,j).isNormalised = sdrbfKern.isNormalised;
    end
    newt1 = t1(t1> spVector(i) & t1<spVector(i+1));
    newt2 = t2(t2> spVector(i) & t2<spVector(i+1));
    dim1(i) = length(newt1);
    dim2(i) = length(newt2);
end

if sum(dim1)~=length(t1) || sum(dim2)~=length(t2)
    error('A problem with the dimensions of the switching intervals occured')
end

% Compute some necessary constants

K = cell(sdrbfKern.nlfPerInt,1);
Kc = cell(sdrbfKern.nlfPerInt,1);

for q=1:sdrbfKern.nlfPerInt
    startValOne = 1;
    endValOne   = 0;
    startValThree = 1;
    endValThree = 0;
    tK = zeros(sum(dim1), sum(dim2));
    for i=1:sdrbfKern.nIntervals
        endValOne = endValOne + dim1(i);
        endValThree = endValThree + dim2(i);
        tK(startValOne:endValOne, startValThree:endValThree) = rbfKernCompute(rbfKern(i,q),...
            t1(startValOne:endValOne) - spVector(i), t2(startValThree:endValThree) - spVector(i));
        Kc{q}{i} = tK(startValOne:endValOne, startValThree:endValThree);
        startValThree = endValThree + 1;
        startValOne = endValOne + 1;
    end
    tK = real(tK);
    K{q} = tK;
end


function []=sb_identify_good_pixels()
%SB_IDENTIFY_GOOD_PIXELS
%   Do the closure tests to identify 'good pixels', i.e. ones that are
%   likely unwrapped properly.
%   Ekbal Hussain @ Uni Leeds
%   19/11/2013
%
%   ======================================================================
%   06/2014 AH: Modify for StaMPS and fix
%   04/2015 EH: Speed optimisations
%   09/2015 EH/DB: Account for Nan values
%   ======================================================================
logit;
fprintf('Identifying good pixels...\n')

load psver
psname=['ps',num2str(psver)];
phuwname=['phuw_sb',num2str(psver)];
loopname=['phuw_loops',num2str(psver)];
goodname=['phuw_good',num2str(psver)];

sb_make_closure_loops;

ps=load(psname);
load(loopname);
load(phuwname,'ph_uw')

good_pixels = false(ps.n_ps,ps.n_ifg);

for m=1:size(intfg_loops,1)

    %Sum positive interferograms in each loop
    positive = find(intfg_loops(m,:)==1);
    positive_ints = zeros(size(ph_uw,1),1);
    for p=1:size(positive,2)
       positive_ints = positive_ints + ph_uw(:,positive(1,p));
    end

    %Sum negative interferograms in each loop
    negative = find(intfg_loops(m,:)==-1);
    negative_ints = zeros(size(ph_uw,1),1);
    for p=1:size(negative,2)
       negative_ints = negative_ints + ph_uw(:,negative(1,p));
    end

    ints_used = [positive, negative];

    %Remove the average residual (closest 2*pi value) to ensure each int is
    %in the same reference
    average_resid = nanmean(positive_ints-negative_ints);

    average_resid = 2*pi*(round(average_resid/2/pi));

    phase_resid = positive_ints-negative_ints-average_resid;
    %hist(positive_ints-negative_ints,100)
    %a = phase_resid(find(phase_resid(:,1)<=1 & phase_resid(:,1)>=-1),:);
    %size(a,1)

    %Index each interferogram with the pixels that are good=1 and bad=0
    %A good pixel is good if: -1<closure residual<1
    good_pixels(phase_resid(:,1)<=1 & phase_resid(:,1)>=-1,ints_used)=true;
end

save(goodname,'good_pixels')
logit(1);


function [ comp ] = getHypInfo( hyps )
%GETHYPINFO Summary of this function goes here
%   Detailed explanation goes here
num_hyps = length(hyps);
comp = repmat(struct('objcenter',[],'objsize',[],'objtype',[]), num_hyps, 1 );
for i = 1:num_hyps
    if isempty(hyps{i})
        continue;
    end
    T = reshape(vertcat(hyps{i}.align)', 24, []);
    comp(i).objcenter = (T(1:3,:)+T(19:21,:))/2;
    comp(i).objcenter = comp(i).objcenter - ...
        repmat(comp(i).objcenter(:,1), 1, size(comp(i).objcenter, 2));
    comp(i).objsize = T(19:21,:)-T(1:3,:)+0.1;
    comp(i).objtype = horzcat(hyps{i}.objtype);
    comp(i).objaspectXY = comp(i).objsize(2,:)./comp(i).objsize(1,:);
    comp(i).objregionXY = comp(i).objsize(2,:).*comp(i).objsize(1,:);

    comp(i).objcenter = single(comp(i).objcenter);
    comp(i).objsize = single(comp(i).objsize);
    comp(i).objtype = single(comp(i).objtype);
    comp(i).objaspectXY = single(comp(i).objaspectXY);
    comp(i).objregionXY = single(comp(i).objregionXY);
end

end