classdef AbstractFixedStepIntegrator < AbstractIntegrator
    %AbstractFixedStepIntegrator Summary of this class goes here
    %   Detailed explanation goes here

    properties(Constant, Access=private)
        %RK5
%         At = [ 1/5,          0,           0,            0,         0
%                3/40,         9/40,        0,            0,         0
%                44/45        -56/15,       32/9,         0,         0
%                19372/6561,  -25360/2187,  64448/6561,  -212/729,   0
%                9017/3168,   -355/33,      46732/5247,   49/176,   -5103/18656];
%
%         Bt = [35/384, 0, 500/1113, 125/192, -2187/6784, 11/84];
%
%         Ct = [1/5; 3/10; 4/5; 8/9; 1];

        %RK4
%         At = [1/2,  0,  0;
%                0, 1/2,  0;
%                0,   0,  1;]
%
%        Bt = [1/6, 1/3, 1/3, 1/6];
%
%        Ct = [1/2, 1/2, 1];

        %RK2
%         At = [1, 1];
%         Bt = [1/2, 1/2];
%
%         Ct = [1];

        %Ralston's 4th Order Method
%         At = [1/2,   0,   0;
%                 0, 1/2,   0;
%                 0,   0,   1];
%
%        Bt = [1/6, 1/3, 1/3, 1/6];
%
%        Ct = [1/2, 1/2, 1];
    end

    methods(Static)
        function [t,y, te,ye,ie] = integrate(odefun, tspan, y0, options)
            [h,y0,~] = AbstractFixedStepIntegrator.checkInputs(odefun, tspan, y0);

            if(all(h>0))
                propDirPos = true;
            elseif(all(h<0))
                propDirPos = false;
            else
                error('Prop direction might be consistently forward or backwards.');
            end

            if(not(isempty(options.OutputFcn)) && ...
               isa(options.OutputFcn,'function_handle'))
                hasOutput = true;
                outputFcn = options.OutputFcn;
            else
                hasOutput = false;
                outputFcn = [];
            end

            if(not(isempty(options.Events)) && ...
               isa(options.Events,'function_handle'))
                hasEvents = true;
                eventFcn = options.Events;
            else
                hasEvents = false;
                eventFcn = [];
            end

            neq = length(y0);
            N = length(tspan);
            t = NaN(N,1);
            Y = NaN(neq,N);

            Y(:,1) = y0;
            t(1) = tspan(1);

            if(hasOutput)
                outputFcn([tspan(1) tspan(end)],y0,'init');
            end

            ie = [];
            te = [];
            ye = [];
            if(hasEvents)
                [prevEvtValues,~,~] = eventFcn(t(1),Y(:,1)); %#ok<RHSFN>
            else
                prevEvtValues = [];
            end

            evtTerminate = false;
            outputTerminate = false;

            i = 2;
            while(keepLooping(propDirPos, i, tspan))
                ti = tspan(i-1);
                if(breakLoop(propDirPos, ti, tspan(end)))
                    break;
                end

                hi = h(i-1);
                yi = Y(:,i-1);

                t(i) = tspan(i);
                Y(:,i) = AbstractFixedStepIntegrator.stepOnce(odefun, ti, yi, hi, neq);

                if(hasEvents)
                    [evtValues,evtIsTerminal,evtDirection] = eventFcn(t(i),Y(:,i)); %#ok<RHSFN>

                    signChangesBool = (prevEvtValues .* evtValues < 0);
                    evtValZeroBool = evtValues == 0;

                    rootDetect = signChangesBool | evtValZeroBool;
                    if(any(rootDetect))
                        rootFcnFzero = @(subHi) AbstractFixedStepIntegrator.rootFindingFunc(subHi, odefun, ti, yi, neq, eventFcn, true);

                        if(all(rootDetect == evtValZeroBool)) %we nailed it on the money
                            tSubI = t(i);
                            exitflag = 1;

                        else %use root finding to actually find the event root
                            m = (evtValues - prevEvtValues) / (t(i) - t(i-1));
                            b = (evtValues - t(i) .* m);
                            t0 = -b./m;

                            t0(rootDetect == 0) = NaN;
                            [minT0, ~] = min(t0);

%                             [tSubI, ~, exitflag] = fzero(rootFcnFzero, minT0);

                            tSubI = SecantMethod(rootFcnFzero, t(i-1), minT0, 1e-6);

                            if(isnan(tSubI))
                                exitflag = -1;
                            else
                                exitflag = 1;
                            end

                            if(exitflag ~= 1 || tSubI < t(i-1) || tSubI > t(i))
                                rootFcnFminBnd = @(subHi) AbstractFixedStepIntegrator.rootFindingFunc(subHi, odefun, ti, yi, neq, eventFcn, false);
                                [tSubI,~,exitflag,~] = fminbnd(rootFcnFminBnd, t(i-1), t(i), optimset('TolX',1E-5));
                            end
                        end

                        if(exitflag == 1)
                            diffForDeriv = sign(evtValues - prevEvtValues);

                            [~, evtInd] = rootFcnFzero(tSubI);
                            if(evtDirection(evtInd) == 0 || ...
                               diffForDeriv(evtInd) == evtDirection(evtInd))

                                tspan1 = tspan(1:i-1);
                                tspan2 = tspan(i:end);
                                tspan = [tspan1, tSubI, tspan2];

                                h1 = h(1:i-1);
                                h2 = h(i:end);
                                hi = tSubI - ti;
                                h = [h1, hi, h2];

                                t(i) = tspan(i);
                                Y(:,i) = AbstractFixedStepIntegrator.stepOnce(odefun, ti, yi, hi, neq);

                                ie(end+1,1) = evtInd;
                                te(end+1,1) = tSubI;
                                ye(end+1,:) = Y(:,i)';

                                if(evtIsTerminal(evtInd) == 1)
                                    evtTerminate = true;
                                else
                                    evtTerminate = false;
                                end
                            else
                                evtTerminate = false;
                            end
                        end
                    end

                    prevEvtValues = evtValues;
                end

                if(hasOutput)
                    status = outputFcn(t(i),Y(:,i),[]);
                    if(status == 1)
                        outputTerminate = true;
                    else
                        outputTerminate = false;
                    end
                end

                if(evtTerminate || outputTerminate)
                    break;
                end

                i=i+1;
            end

            y = Y.';

            bool = ~isnan(t);
            t = t(bool);
            y = y(bool,:);

            if(hasOutput)
                outputFcn([],[],'done');
            end
        end

    end

    methods(Static, Access=protected)
        [A,B,C] = getButcherTableauData();

        function [h,y0,f0] = checkInputs(odefun, tspan, y0)
            if ~isnumeric(tspan)
                error('TSPAN should be a vector of integration steps.');
            end

            if ~isnumeric(y0)
                error('Y0 should be a vector of initial conditions.');
            end

            h = diff(tspan);
            if any(sign(h(1))*h <= 0)
                error('Entries of TSPAN are not in order.')
            end

            y0 = y0(:);   % Make a column vector.
            try
                f0 = odefun(tspan(1),y0);
            catch ME
                msg = ['Unable to evaluate the ODEFUN at t0,y0: ',ME.message];
                error(msg);
            end

            if ~isequal(size(y0),size(f0))
                error('Inconsistent sizes of Y0 and f(t0,y0).');
            end
        end

        function [yNp1, fEvals] = stepOnce(odefun, ti, yi, hi, neq)
            [A,B,C] = ODE5Integrator.getButcherTableauData(); %needs to be generalized

            nstages = length(B);
            F = NaN(neq,nstages);

            % General explicit Runge-Kutta framework
            F(:,1) = odefun(ti,yi);
            for stage = 2:nstages
                tstage = ti + C(stage-1)*hi;
                ystage = yi + F(:,1:stage-1)*(hi*A(1:stage-1,stage-1));
                F(:,stage) = odefun(tstage,ystage);
            end
            yNp1 = yi + F*(hi*B);
            fEvals = 1 + (nstages - 1);
        end
    end

    methods(Static, Access=private)
        function [rootOutput, I] = rootFindingFunc(subT, odefun, ti, yi, neq, eventFcn, forRootFinder)
            subHi = subT - ti;
            yNp1 = AbstractFixedStepIntegrator.stepOnce(odefun, ti, yi, subHi, neq);

            [evtValues,~,~] = eventFcn(subT,yNp1);

            rootOutput = evtValues;
            [~,I] = min(abs(rootOutput));

            if(forRootFinder)
                rootOutput = rootOutput(I); %for fzero and the like
            else
                rootOutput = abs(rootOutput(I)); %for an optimizer like fminbnd
            end
        end
    end
end

function tf = keepLooping(propDirPos, i, tspan)
    ti = tspan(i-1);
    if(propDirPos)
        tf = ti < tspan(end);
    else
        tf = ti > tspan(end);
    end
end

function tf = breakLoop(propDirPos, ti, tspanEnd)
    if(propDirPos)
        tf = ti >= tspanEnd;
    else
        tf = ti <= tspanEnd;
    end
end


function [policy, EU] = upot_to_opt_policy(pot)
% UPOT_TO_OPT_POLICY Compute an optimal deterministic policy given a utility potential
% [policy, EU] = upot_to_opt_policy(pot)
%
% policy(a,b, ..., z) = P(do z | a, b, ..), which will be a delta function
% EU is the contraction of this potential, i.e., P .* U

sz = pot.sizes; % mysize(pot.p);
if isempty(sz)
  EU = pot.u;
  policy = [];
  return;
end

parent_size = prod(sz(1:end-1));
self_size = sz(end);
C = pot.p .* pot.u; % contraction
C = reshape(C, parent_size, self_size);
policy = zeros(parent_size, self_size);
for i=1:parent_size
  act = argmax(C(i,:));
  policy(i, act) = 1;
end
policy = myreshape(policy, sz);
EU = sum(C(:));


function test_ft_determine_units

% MEM 1gb
% WALLTIME 00:10:00
% DEPENDENCY ft_determine_units

if nargout
  % assume that this is called by RUNTESTS
  tests = functiontests(localfunctions);
else
  % assume that this is called from the command line
  func = localfunctions;
  for i=1:numel(func)
    fprintf('evaluating %s\n', func2str(func{i}));
    feval(func{i});
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function testElec(testCase)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

elec = [];
elec.elecpos = randn(32,3);
for i=1:32
  elec.elecpos(i,:) = 100*elec.elecpos(i,:) ./ norm(elec.elecpos(i,:));
end
elec.unit = 'mm';

elec_mm = ft_determine_units(rmfield(ft_convert_units(elec, 'mm'), 'unit'));
elec_cm = ft_determine_units(rmfield(ft_convert_units(elec, 'cm'), 'unit'));
elec_m  = ft_determine_units(rmfield(ft_convert_units(elec, 'm'), 'unit'));

assert(strcmp(elec_mm.unit, 'mm'));
assert(strcmp(elec_cm.unit, 'cm'));
assert(strcmp(elec_m.unit, 'm'));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function testSphere(testCase)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

headmodel = [];
headmodel.r = 120;
headmodel.o = [0 0 40];
headmodel.unit = 'mm';

headmodel_mm = ft_determine_units(rmfield(ft_convert_units(headmodel, 'mm'), 'unit'));
headmodel_cm = ft_determine_units(rmfield(ft_convert_units(headmodel, 'cm'), 'unit'));
headmodel_m  = ft_determine_units(rmfield(ft_convert_units(headmodel, 'm'), 'unit'));

assert(strcmp(headmodel_mm.unit, 'mm'));
assert(strcmp(headmodel_cm.unit, 'cm'));
assert(strcmp(headmodel_m.unit, 'm'));


%% Importing Tensor Data
%
%%
% Single crystal tensor are imported using the command <tensor.load.html
% tensor.load>. This function automatically detect the file format and
% imports the data. In dependency of the specific format it might be
% necessary to specify the crystal symmetry seperately

% define crystal symmetry
CS = crystalSymmetry('32', [4.916 4.916 5.4054],...
  'X||a*', 'Z||c', 'mineral', 'Quartz');

% define the file name
fname = fullfile(mtexDataPath,'tensor', 'Single_RH_quartz_poly.P');

% import the single crystal tensor
P = tensor.load(fname,CS,'propertyname','piecoelectricity','unit','C/N','DoubleConvention')

%%
% For specific types of tensors, e.g. stiffness tensors there exist
% dedicated import functions that have the form *tensorName.load*

fname = fullfile(mtexDataPath,'tensor','Olivine1997PC.GPa');

cs = crystalSymmetry('mmm',[4.7646 10.2296 5.9942],'mineral','Olivin');

C = stiffnessTensor.load(fname,cs)


function im_rec = tomo_recon_myart_im(im, angles, n_it)
%TOMO_RECON_ART_IM   Tomographic reconstruction using ART method.
%
%   Phymhan
%   09-Aug-2013 09:15:41

if nargin < 3
    n_it = 100;
end
siz = size(im);
[W, p, ~, ~] = buildWeightMatrix(im,angles);
f = myart_solve(W,p,n_it);
im_rec = reshape(f,siz);
end


% Originally Coded By: Niall Mangan
% Copyright 2017, All Rights Reserved
% Code by Niall Mangan for paper "Inferring biological networks by sparse
% identification of nonlinear dynamics"
% by N. M. Mangan S. L. Brunton, J. L. Proctor, and J. N. Kutz
% Original Code: https://github.com/niallmm/iSINDy
%%
% This file is modified to compare the performance of i-SINDy on
% insufficient data.
% Modified by:K, 2019/07/16
% Find equations for yeast glycolysis state variable 4
%%
clc;close all;clear all;

addpath('./utils');
addpath('./bioutils');

% define libarary parameters
laurentorder = 0;
polyorder = 3;
usesine = 0;
dyorder = 1;

% clear variables from other solutions.
clear Theta Thetastring Xi indTheta lambdavec numterms errorv indopt
clear indTheta1 Xi1 numterms1 nT

% Here we load the previously simulated data
load('TrainingData.mat')

% Define the new data length
percent=0.006;new_length=round(percent*length(xt));

% Shuffel the original data
Sequence=randperm(size(xt,1));
xt=xt(Sequence,:);
dxt=dxt(Sequence,:);

% Assign the value to the new variables
Data=xt(1:new_length,:);dData=dxt(1:new_length,:);

% Define the number of states
n=size(Data,2);

% pool Data  (i.e., build library of nonlinear time series)
[Theta, Thetastring] = poolDatady(Data,n,polyorder,usesine, laurentorder, dData(:,4), dyorder);
% %initial lambda value, which is the value used for soft thresholding in ADM

tol = 2e-3;
lambda = 8e-3;

jj = 1; % counter
num= 1; % initialize the number of nonzero terms found for the lambda
errorvec= 0;

MaxIter = 1e3;

% for now calculate null space using null function
nT = null(Theta);

% Define the parameters for plooting
plottag=2;

[indTheta1, Xi1, numterms1] = ADMinitvary(nT,lambda,MaxIter,tol, plottag);
Thetastring(indTheta1)'
n0Xi = Xi1(Xi1~=0);
n0Xi/n0Xi(end)
save('Results/4rd_state_variable.mat')


function i4vec_direct_product_test ( )

%*****************************************************************************80
%
%% I4VEC_DIRECT_PRODUCT_TEST tests I4VEC_DIRECT_PRODUCT.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 April 2009
%
%  Author:
%
%    John Burkardt
%
  factor_num = 3;
  point_num = 24;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'I4VEC_DIRECT_PRODUCT_TEST\n' );
  fprintf ( 1, '  I4VEC_DIRECT_PRODUCT forms the entries of a\n' );
  fprintf ( 1, '  direct product of a given number of I4VEC factors.\n' );

  x(1:factor_num,1:point_num) = 0;

  for factor_index = 1 : factor_num

    if ( factor_index == 1 )
      factor_order = 4;
      factor_value = [ 1, 2, 3, 4 ];
    elseif ( factor_index == 2 )
      factor_order = 3;
      factor_value = [ 50, 60, 70 ];
    elseif ( factor_index == 3 )
      factor_order = 2;
      factor_value = [ 800, 900 ];
    end

    x = i4vec_direct_product ( factor_index, factor_order, factor_value,  ...
      factor_num, point_num, x );

  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '     J     X(1)  X(2)  X(3)\n' );
  fprintf ( 1, '\n' );

  for j = 1 : point_num
    fprintf ( 1, '  %4d    %4d  %4d  %4d\n', j, x(1:factor_num,j) );
  end

  return
end


% minimum distance from head of fly to central of any other fly
function [data,units] = compute_dhead2central(trx,n)

larvae = trx.exp2flies{n};
nlarvae = numel(larvae);
data = cell(1,nlarvae);

for i1 = 1:nlarvae,
  larva1 = larvae(i1);
  % access closestfly to ensure that dhead2central is computed
  trx(larva1).closestlarva_head2central;
  data{i1} = trx(larva1).dhead2central;
end
units = parseunits('mm');


function [Z,Q1,R] = sparsenull(A)

[Q,R] = qr(A');
n = max(find(sum(abs(R),2)));
Q1 = Q(:,1:n);
R = R(1:n,:);
Z = Q(:,n+1:end); % New basis


% Sample layer automatically
function [X, mu, sigma] = vargplvmSampleLatent(model, dim, X, startingPoint)
if nargin <4 || isempty(startingPoint)
     % This point will be initially drawn. Then, we will sample and alter
     % only one if its dimensions.
    startingPoint = 1;
end

if nargin < 4 || isempty(X)
    Xorig = model.vardist.means;
    N = size(Xorig,1);
    xmin = min(Xorig(:,dim));
    xmax = max(Xorig(:,dim));
    df = xmax - xmin;
    xmin = xmin - 4*df/N; % also catch some points before xmin
    xmax = xmax + 4*df/N;
    x = linspace(xmin,xmax, 3*N); % this is the series of changes made in a specific dimension
    X = repmat(Xorig(startingPoint,:), length(x),1); % Just select some initial point
    X(:,dim) = x';
end

if nargout > 2
    [mu sigma] = vargplvmPosteriorMeanVar(model, X);
else
    mu = vargplvmPosteriorMeanVar(model, X);
end


function i4vec_amax_test ( )

%*****************************************************************************80
%
%% I4VEC_AMAX_TEST tests I4VEC_AMAX;
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 April 2009
%
%  Author:
%
%    John Burkardt
%
  n = 10;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'I4VEC_AMAX_TEST\n' );
  fprintf ( 1, '  For an integer vector:\n' );
  fprintf ( 1, '  I4VEC_AMAX:   maximum absolute entry;\n' );

  seed = 123456789;
  b = -n;
  c = n;

  [ a, seed ] = i4vec_uniform_ab ( n, b, c, seed );

  i4vec_print ( n, a, '  Input vector:' );

  aval = i4vec_amax ( n, a );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Maximum absolute value: %f\n', aval );

  return
end


function ierror = setpart_check ( m, nsub, s, index )

%*****************************************************************************80
%
%% SETPART_CHECK checks a set partition.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 August 2012
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Donald Kreher, Douglas Simpson,
%    Combinatorial Algorithms,
%    CRC Press, 1998,
%    ISBN: 0-8493-3988-X,
%    LC: QA164.K73.
%
%  Parameters:
%
%    Input, integer M, the number of elements of the set.
%    M must be positive.
%
%    Input, integer NSUB, the number of nonempty subsets into
%    which the set is partitioned.  1 <= NSUB <= M.
%
%    Input, integer INDEX(NSUB), lists the location in S of the
%    last element of each subset.  Thus, the elements of subset 1
%    are S(1) through S(INDEX(1)), the elements of subset 2
%    are S(INDEX(1)+1) through S(INDEX(2)) and so on.
%
%    Input, integer S(M), contains the integers from 1 to M,
%    grouped into subsets as described by INDEX.
%
%    Output, integer IERROR, error flag.
%    0, no error.
%    -I, the I-th element of INDEX is illegal.
%    +I, the I-th element of S is illegal.
%
  ierror = 0;
%
%  Check INDEX.
%
  imin = 0;
  for i = 1 : nsub
    if ( index(i) <= imin || m < index(i) )
      ierror = -i;
      return
    end
    imin = index(i);
  end
%
%  Check the elements of S.
%
  for i = 1 : nsub

    if ( s(i) <= 0 || m < s(i) )
      ierror = i;
      return
    end

    for j = 1 : i - 1
      if ( s(j) == s(i) )
        ierror = i;
        return
      end
    end

  end

  return
end


function [fevd_estimates]=fevd(struct_irf_record,gamma_record,It,Bu,n,IRFperiods,FEVDband)

% function [fevd_record]=fevd(struct_irf_record,gamma_record,It,Bu,IRFperiods,n)
% runs the gibbs sampler to obtain draws from the posterior distribution of FEVD
% inputs:  - cell 'struct_irf_record': record of the gibbs sampler draws for the orthogonalised IRFs
%          - matrix 'gamma_record': record of the gibbs sampler draws for the structural disturbances variance-covariance matrix gamma
%          - integer 'It': total number of iterations of the Gibbs sampler (defined p 28 of technical guide)
%          - integer 'Bu': number of burn-in iterations of the Gibbs sampler (defined p 28 of technical guide)
%          - integer 'IRFperiods': number of periods for IRFs
%          - integer 'n': number of endogenous variables in the BVAR model (defined p 7 of technical guide)
% outputs: - cell 'fevd_record': record of the gibbs sampler draws for the FEVD

% this function implements algorithm 3.1.1
% preliminary tasks
% define the time horizon of FEVD as that of IRFs
FEVDperiods=IRFperiods;

% create the first cell
temp=cell(n,n+1);

% now prepare the evaluation of (3.1.13)
% start by filling the first column of every Tij matrix in the cell
% loop over rows of temp
for jj=1:n
   % loop over columns of temp
   for ii=1:n
   % square each IRF element
   temp{jj,ii}(:,1)=struct_irf_record{jj,ii}(:,1).^2;
   end
end

% fill all the other entries of the Tij matrices
% loop over rows of temp
for jj=1:n
   % loop over columns of temp
   for ii=1:n
      % loop over remaining columns
      for kk=2:FEVDperiods
      % define the column as the square of the corresponding column in orthogonalised_irf_record
      % additioned to the value of the preceeding columns, which creates the cumulation
      temp{jj,ii}(:,kk)=struct_irf_record{jj,ii}(:,kk).^2+temp{jj,ii}(:,kk-1);
      end
   end
end

% multiply each matrix in the cell by the variance of the structural shocks
% to do so, loop over simulations (rows of the Tij matrices)
for jj=1:It-Bu
% recover the covariance matrix of structural shocks gamma for this iteration
gamma=reshape(gamma_record(:,jj),n,n);
% loop over rows of temp
   for ii=1:n
   % loop over columns of temp
      for kk=1:n
      % multiply row jj of the matrix by the variance of the structural shock
      temp{ii,kk}(jj,:)=temp{ii,kk}(jj,:)*gamma(kk,kk);
      end
   end
% then go for next iteration
end

% obtain now the values for Ti, the (n+1)th matrix of each row
% loop over rows of temp
for jj=1:n
% start the summation over Tij matrices
temp{jj,n+1}=temp{jj,1};
   % sum over remaining columns
   for ii=2:n
   temp{jj,n+1}=temp{jj,n+1}+temp{jj,ii};
   end
end

% create the output cell fevd_record
fevd_record=cell(n,n);

% fill the cell
% loop over rows of fevd_record
for jj=1:n
   % loop over columns of fevd_record
   for ii=1:n
   % define the matrix Vfij as the division (pairwise entry) of Tfij by Tfj
   fevd_record{jj,ii}=temp{jj,ii}./temp{jj,n+1};
   end
end

%% create the FEVD estimates output
% create first the cell that will contain the estimates
fevd_estimates=cell(n,n);

% for each variable and each variable contribution along with each period, compute the median, lower and upper bound from the Gibbs sampler records
% consider variables in turn
for ii=1:n
   % consider contributions in turn
   for jj=1:n
      % consider periods in turn
      for kk=1:IRFperiods
      % compute first the lower bound
      fevd_estimates{ii,jj}(1,kk)=quantile(fevd_record{ii,jj}(:,kk),(1-FEVDband)/2);
      % then compute the median
      fevd_estimates{ii,jj}(2,kk)=quantile(fevd_record{ii,jj}(:,kk),0.5);
      % finally compute the upper bound
      fevd_estimates{ii,jj}(3,kk)=quantile(fevd_record{ii,jj}(:,kk),1-(1-FEVDband)/2);
      end
   end
end


function [fMc, fMc95, fMc90] = calc_McBest(mag, fBinning);
    %CALC_MCBEST Calculate best Mc from combining methods

    % First estimation of magnitude of completeness (maximum curvature)
    [vEvents, vMag] = hist(mag, -2:0.1:6);
    nSel = max(find(vEvents == max(vEvents)));
    fMcStart = vMag(nSel);

    % Data container
    mData = [];

    % Magnitude increment
    if ~exist('fBinning')
        fBinning = 0.1;
    end

    for nCnt = (fMcStart - 0.9):fBinning:(fMcStart + 1.5)
        vSel = mag > (nCnt - (fBinning/2));
        %vSel = mag >= nCnt - 0.0499;
        nNumberEvents = length(mag(vSel));
        if nNumberEvents >= 25;
            [fDummy fBValue fDummy fDummy] =  Catalog.bvalue_lib.bmemag(mag(vSel));

            fStartMag = nCnt; % Starting magnitude (hypothetical Mc)

            % log10(N)=A-B*M
            vMag = [fStartMag:fBinning:15]; % Ending magnitude must be sufficiently high
            vNumber = 10.^(log10(nNumberEvents)-fBValue*(vMag - fStartMag));
            vNumber = round(vNumber);

            % Find the last bin with an event
            nLastEventBin = min(find(vNumber == 0)) - 1;
            if isempty(nLastEventBin)
                nLastEventBin = length(vNumber);
            end

            %    ctM=vMag(ct1);

            % Determine set of all magnitude bins with number of events > 0
            ct = round((vMag(nLastEventBin)-fStartMag)*(1/fBinning) + 1);
            %     ct=0;
            %     for I=fStartMag:fBinning:ctM;
            %       ct=ct+1;
            %     end;

            PM=vMag(1:ct);
            vNumber = vNumber(1:ct);
            [bval, vDummy] = hist(mag(vSel),PM);
            b3 = fliplr(cumsum(fliplr(bval)));    % N for M >= (counted backwards)
            res2 = sum(abs(b3 - vNumber))/sum(b3)*100;
            mData = [mData; nCnt res2];
        else
            mData = [mData; nCnt NaN];
        end
    end

    % Evaluation of results

    % Is fMc90 available
    nSel = min(find(mData(:,2) < 10));
    if isempty(nSel)
        fMc90 = NaN
    else
        fMc90 = mData(nSel,1)
    end

    % Is fMc95 available
    nSel = min(find(mData(:,2) < 5));
    if isempty(nSel)
        fMc95 = NaN;
    else
        fMc95 = mData(nSel,1);
    end

    % ?????
    j =  min(find(mData(:,2) < 10 ));
    if isempty(j) == 1; j =  min(find(mData(:,2) < 15 )); end
    if isempty(j) == 1; j =  min(find(mData(:,2) < 20 )); end
    if isempty(j) == 1; j =  min(find(mData(:,2) < 25 )); end
    %j2 =  min(find(dat(:,2) == min(dat(:,2)) ));

    fMc = mData(j,1);
    if isempty(fMc)
        fMc = NaN;
    end
end


function [lp,lj,tr] = lineline(pa,pb,pc,pd,varargin)
%LINELINE intersection between lines in d-dimensional space.
%   [LP,LI] = LINELINE(PA,PB,PC,PD) finds intersections bet-
%   ween line segments in d-dimensions. Lines are specified
%   as a set of endpoints [PA,PB] and [PC,PD] where PA, PB,
%   PC and PD are NL-by-ND arrays of coordinates, where ND
%   is the number of dimensions.
%
%   A set of intersecting lines from [PA,PB] is returned for
%   each query line in [PC,PB], such that the II-th query
%   line is associated with the lines LI(LP(II,1):LP(II,2)).
%   Lines without intersections have LP(II,1) == 0.
%
%   [LP,LI,TR] = LINELINE(PA,PB,PC,PD) additionally returns
%   the supporting aabb-tree used internally to compute the
%   query. If the underlying collection [PA,PB] is static,
%   the  tree TR may be recycled for subsequent calls, using
%   [LP,LI,TR] = FINDLINE(PA,PB,PC,PD,TR). This syntax may
%   lead to improved performance, especially when the number
%   of lines is large w.r.t. the number of query lines. Note
%   that in such cases the distribution of underlying lines
%   is NOT permitted to change between calls, or erroneous
%   results may be returned. Additional parameters used to
%   govern the creation of the underlying aabb-tree may be
%   passed via [...] = LINELINE(...,TR,OP). See MAKETREE for
%   additional information.
%
%   See also MAKETREE, FINDTRIA, FINDBALL, FINDLINE

% Please see the following for additional information:
%
%   Darren Engwirda, "Locally-optimal Delaunay-refinement &
%   optimisation-based mesh generation". Ph.D. Thesis, Scho-
%   ol of Mathematics and Statistics, Univ. of Sydney, 2014:
%   http://hdl.handle.net/2123/13148

%-----------------------------------------------------------
%   Darren Engwirda : 2017 --
%   Email           : de2363@columbia.edu
%   Last updated    : 10/10/2017
%-----------------------------------------------------------

    lp = []; lj = []; tr = []; op = [];

%---------------------------------------------- basic checks
    if (nargin < +4 || nargin > +6)
        error('lineline:incorrectNumInputs', ...
            'Incorrect number of inputs.');
    end

    if (nargin >= +5), tr = varargin{1}; end
    if (nargin >= +6), op = varargin{2}; end

%------------------------------ quick return on empty inputs
    if (isempty(pa)), return ; end
    if (isempty(pb)), return ; end
    if (isempty(pc)), return ; end
    if (isempty(pd)), return ; end

%---------------------------------------------- basic checks
    if (~isnumeric(pa) || ~isnumeric(pb) || ...
        ~isnumeric(pc) || ~isnumeric(pd) )
        error('lineline:incorrectInputClass', ...
            'Incorrect input class.') ;
    end

    if (ndims(pa) ~= +2 || size(pa,2) < +2 || ...
        ndims(pb) ~= +2 || size(pb,2) < +2 || ...
        ndims(pc) ~= +2 || size(pc,2) < +2 || ...
        ndims(pd) ~= +2 || size(pd,2) < +2 )
        error('lineline:incorrectDimensions', ...
            'Incorrect input dimensions.');
    end
    if (size(pa,1) ~= size(pb,1) || ...
        size(pc,1) ~= size(pd,1) )
        error('lineline:incorrectDimensions', ...
            'Incorrect input dimensions.');
    end

    if (~isempty(tr) && ~isstruct(tr) )
        error('lineline:incorrectInputClass', ...
            'Incorrect input class.') ;
    end
    if (~isempty(op) && ~isstruct(op) )
        error('lineline:incorrectInputClass', ...
            'Incorrect input class.') ;
    end

    nd = size(pa,2);
    nl = size(pa,1);
    ml = size(pc,1);

    if (isempty(tr))
%------------------------------ compute aabb-tree for d-line
    ab = zeros(nl,nd*+2) ;
    for ax = +1:nd            % compute aabb's
    ab(:,ax+nd*0) = min(pa(:,ax), ...
                        pb(:,ax)) ;
    ab(:,ax+nd*1) = max(pa(:,ax), ...
                        pb(:,ax)) ;
    end
    tr = maketree(ab,op) ;

    end

%------------------------------ compute tree-to-vert mapping
    ab = zeros(ml,nd*+2) ;
    for ax = +1:nd            % compute aabb's
    ab(:,ax+nd*0) = min(pc(:,ax), ...
                        pd(:,ax)) ;
    ab(:,ax+nd*1) = max(pc(:,ax), ...
                        pd(:,ax)) ;
    end
    tm = maprect (tr,ab) ;

%------------------------------ compute line-to-line queries
   [li,ip,lj] = queryset( ...
    tr,tm,@linekern,pc,pd,pa,pb) ;

%------------------------------ re-index onto full obj. list
    lp = zeros(size(pc,1),2) ;
    lp( :,2) = -1 ;

    if (isempty(li)), return ; end

    lp(li,:) = ip ;

end

function [i1,i2] = linekern(l1,l2,pa,pb,pc,pd)
%LINEKERN d-dim. line//line intersection kernel routine.

        m1 = length(l1) ;
        m2 = length(l2) ;

    %-------------------------- push line/vert onto n*m tile
        l1 = l1.' ;

        l1 = l1(ones(m2,1),:) ;
        l1 = l1(:);
        l2 = l2(:,ones(1,m1)) ;
        l2 = l2(:);

    %-------------------------- compute O(n*m) intersections
       [ok,tp,tq] = linenear( ...
           pa(l1,:),pb(l1,:), ...
           pc(l2,:),pd(l2,:)) ;

        rt = +1.+eps;

        ix = abs(tp) <= +rt & ...
             abs(tq) <= +rt ;

        ix(~ok) = false ;

        i1 = l1(ix) ;
        i2 = l2(ix) ;

end


function ins=ins_mech(ins,imu)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% INS mechanization
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (C) 2020-2025, by Kai Chen, All rights reserved.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
persistent old_dw old_dv

ins.time=imu.time;
if isempty(old_dw)
    old_dw=zeros(3,1);
end
if isempty(old_dv)
    old_dv=zeros(3,1);
end

% correct bias and scaling factor errors
dw0 = imu.dw';
dv0 = imu.dv';
dw = ins.Kg*dw0-ins.bg*ins.nt;
dv = ins.Ka*dv0-ins.ba*ins.nt;

% extrapolate velocity and position
vel_mid = ins.vel+ins.acc*(ins.nt/2);
pos_mid = ins.pos+ins.Mpv*(ins.vel+vel_mid)/2*ins.nt;

% update the related parameters
ins.eth = earth_update(pos_mid,vel_mid);
ins.wib = dw/ins.nt;
ins.fb  = dv/ins.nt;
ins.fn  = ins.Cnb*ins.fb;
ins.web = ins.wib-ins.Cnb'*ins.eth.wnie;

% update velocity
dv_rot  = 0.5*cross(dw0,dv0);
dv_scul = 1/12*(cross(old_dw,dv0)+cross(old_dv,dw0));
dv_sf   = (eye(3)-0.5*ins.nt*askew(ins.eth.wnin))*ins.Cnb*dv + ins.Cnb*(dv_rot+dv_scul);
dv_cor  = ins.eth.gcc*ins.nt;
vel_new = ins.vel+dv_sf+dv_cor;

% update position
ins.Mpv(2) = ins.eth.Mpv2;
ins.Mpv(4) = ins.eth.Mpv4;
pos_new    = ins.pos + ins.Mpv*(ins.vel+vel_new)/2*ins.nt;

% update attitude
dw_cone  = 1/12*cross(old_dw,dw0);
phi_b_ib = dw+dw_cone;
phi_n_in = ins.eth.wnin*ins.nt;
Cbb = rvec2mat(phi_b_ib);
Cnn = rvec2mat(phi_n_in)';
Cnb_new = Cnn*ins.Cnb*Cbb;
att_new = Cnb2att(Cnb_new);

% update INS result
ins.Cnb = Cnb_new;
ins.att = att_new;
ins.vel = vel_new;
ins.pos = pos_new;
ins.x = [ins.att;ins.vel;ins.pos;ins.bg;ins.ba];

old_dw=dw0;
old_dv=dv0;

return


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
%
% Tutorial for FAIR: SSD and Force Fields
%
%==============================================================================

clear, close all, help(mfilename);
sdiag = @(a) spdiags(reshape(a,[],1),0,length(a),length(a));
setup2DHNSPData;
level = 7; omega = ML{level}.omega; m = ML{level}.m; % load data
imgModel('reset','imgModel','splineInter')
viewImage('set','axis','off');
[T,R] = imgModel('coefficients',ML{level}.T,ML{level}.R,omega);
X = reshape(getCellCenteredGrid(omega,m),[],2);

[Tc,dT] = imgModel(T,omega,X);
[Rc,dR] = imgModel(R,omega,X);

axT   = [0.55,0.85,0.32,0.47];
axR   = [0.6,0.9,0.20,0.35];
axTF  = [0.55,0.70,0.32,0.395];

FAIRfigure(1,'color','w');
viewImage(Tc,omega,m); hold on; axis off;
ph = plot(axT([1,1,2,2,1]),axT([3,4,4,3,3]),'w-','linewidth',4);

set(ph,'visible','off');  axis(axT);

clf;
viewImage(Rc,omega,m); hold on; axis off;
ph = plot(axR([1,1,2,2,1]),axR([3,4,4,3,3]),'w-','linewidth',4);

set(ph,'visible','off');  axis(axR);

clf;
viewImage(128+0.5*(Tc-Rc),omega,m); hold on; axis off;
% ph = plot(axT([1,1,2,2,1]),axT([3,4,4,3,3]),'w-','linewidth',4);
% set(ph,'visible','off');  axis(axR);

X = getCellCenteredGrid(omega,m); X = reshape(X,[],2);
n = prod(m);
gradT     = spdiags(dT,[0,n]);
maxGradT  = norm(gradT,'inf');
ngradT    = 128+128/maxGradT*gradT;
normGradT = sqrt(sum(gradT.^2,2));
J     = find(normGradT>5e1);
F     = sdiag(Tc-Rc)*gradT;      maxF = norm(F,'inf');
nF    = 128+128/maxF*F;
normF = sqrt(sum(F.^2,2));
K     = find(normF>1e2);

figure(1); clf; set(1,'position',FAIRposition(800),'color','w');
clf; viewImage(ngradT(:,1),omega,m); axis(axT);
clf; viewImage(ngradT(:,2),omega,m); axis(axT);

clf; viewImage(128+0.5*Tc,omega,m); hold on;
qh = quiver(X(J,1),X(J,2),gradT(J,1),gradT(J,2),2);
set(qh,'linewidth',3,'color','k'); axis(axTF);

clf; viewImage(128+0.5*Tc,omega,m); hold on;
qh = quiver(X(K,1),X(K,2),F(K,1),F(K,2),2);
set(qh,'linewidth',3,'color','k'); axis(axTF)

%==============================================================================


function b = zhpsl ( ap, n, ipvt, b )

%*****************************************************************************80
%
%% ZHPSL solves a complex hermitian system factored by ZHPFA.
%
%  Discussion:
%
%    A division by zero may occur if ZHPCO set RCOND to 0.0
%    or ZHPFA set INFO nonzero.
%
%    To compute
%
%      inverse ( A ) * C
%
%    where C is a matrix with P columns
%
%      call zhpfa(ap,n,ipvt,info)
%
%      if ( info == 0 )
%        do j = 1, p
%          call zhpsl(ap,n,ipvt,c(1,j))
%        end do
%      end
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%  Parameters:
%
%    Input, complex AP(N*(N+1)/2), the output from ZHPFA.
%
%    Input, integer N, the order of the matrix.
%
%    Input, integer IPVT(N), the pivot vector from ZHPFA.
%
%    Input, complex B(N), the right hand side.
%
%    Output, complex B(N), the solution.
%

%
%  Loop backward applying the transformations and inverse ( D ) to B.
%
  k = n;
  ik = ( n * ( n - 1 ) ) / 2;

  while ( 0 < k )

    kk = ik + k;
%
%  1 x 1 pivot block.
%
    if ( 0 <= ipvt(k) )

      if ( k ~= 1 )

        kp = ipvt(k);

        if ( kp ~= k )
          t     = b(k);
          b(k)  = b(kp);
          b(kp) = t;
        end

        b(1:k-1) = b(1:k-1) + b(k) * ap(ik+1:ik+k-1);

      end
%
%  Apply D inverse.
%
      b(k) = b(k) / ap(kk);
      k = k - 1;
      ik = ik - k;

    else
%
%  2 x 2 pivot block.
%
      ikm1 = ik - ( k - 1 );

      if ( k ~= 2 )

        kp = abs ( ipvt(k) );

        if ( kp ~= k - 1 )
          t      = b(k-1);
          b(k-1) = b(kp);
          b(kp)  = t;
        end

        b(1:k-2) = b(1:k-2) + b(k)   * ap(ik+1:ik+k-2);
        b(1:k-2) = b(1:k-2) + b(k-1) * ap(ikm1+1:ikm1+k-2);

      end
%
%  Apply D inverse.
%
      km1k = ik + k - 1;
      kk = ik + k;
      ak = ap(kk) / conj ( ap(km1k) );
      km1km1 = ikm1 + k - 1;
      akm1 = ap(km1km1) / ap(km1k);
      bk = b(k) / conj ( ap(km1k) );
      bkm1 = b(k-1) / ap(km1k);
      denom = ak * akm1 - 1.0;
      b(k) = ( akm1 * bk - bkm1 ) / denom;
      b(k-1) = ( ak * bkm1 - bk ) / denom;
      k = k - 2;
      ik = ik - ( k + 1 ) - k;

    end

  end
%
%  Loop forward applying the transformations.
%
  k = 1;
  ik = 0;

  while ( k <= n )
%
%  1 x 1 pivot block.
%
    if ( 0 <= ipvt(k) )

      if ( k ~= 1 )

        b(k) = b(k) + conj ( ap(ik+1:ik+k-1) ) * transpose ( b(1:k-1) );
        kp = ipvt(k);

        if ( kp ~= k )
          t     = b(k);
          b(k)  = b(kp);
          b(kp) = t;
        end

      end

      ik = ik + k;
      k = k + 1;
%
%  2 x 2 pivot block.
%
    else

      if ( k ~= 1 )

        b(k) = b(k) + conj ( ap(ik+1:ik+k-1) ) * transpose ( b(1:k-1) );
        ikp1 = ik + k;
        b(k+1) = b(k+1) ...
          + conj ( ap(ikp1+1:ikp1+k-1) ) * transpose ( b(1:k-1) );
        kp = abs ( ipvt(k) );

        if ( kp ~= k )
          t     = b(k);
          b(k)  = b(kp);
          b(kp) = t;
        end

      end

      ik = ik + k + k + 1;
      k = k + 2;

    end

  end

  return
end


function [gx,dG_dX,dG_dPhi] = g_fullDCM4fmri(Xt,Phi,ut,inG)
% full DCM observation function (embedding dynamic Ballon model)

% function [gx,dG_dX,dG_dPhi] = g_fullDCM4fmri(Xt,Phi,ut,inG)
% This function evaluates the observation function of the neuronal level in
% DCM for fMRI. Note that this "generalized" observation function includes
% the HRF convolution model (balloon model).

persistent xh dxhdx dxhdp ph ti ko
% These variables are described bellow:
%   - xh{i}: current hemodynamic states for region i.
%   - dxhdx{i}: derivatives of the hemodynamic states of region i w.r.t.
%   neuronal state of region i.
%   - dxhdp{i}: derivatives of the hemodynamic states of region i w.r.t.
%   hemodynamic parameters of region i.
%   - ph: the last remembered hemodynamic parameters. This is only used
%   when this function is called from f_fullDCM4fmri.m. It is updated each
%   time this function is called outside f_fullDCM4fmri.m.
%   - ti: the index within the time series. This is used to reinitialize
%   the persistent variables.
% These are reinitialized at the beginning of the time series.

try % just to get lastly updated phi

    inG.getPhi;
    ph = Phi;

catch

    n = size(Xt,1);

    % Check whether the system is at initial state
    if isempty(xh)
        ti = 0;
        xh = kron(ones(n,1),[0;0;0;0]);
        dxhdx = zeros(n,n*4);
        dxhdp = zeros(size(inG.Phi,1),n*4);
        ko = kron(eye(n),[1 0 0 0]);
    end

    if isempty(Phi)    %- Function is called from f_fullDCM4fmri

        % Get current observation parameters mode
        if ~isempty(ph)
            Phi = ph;
        else % only the first iteration
            Phi = inG.Phi;
        end

        %- hemodynamic response convolution operation
        [fx,dfdxh,dfdp] = f_HRF2(xh,Phi,Xt,inG);

        xh = fx;
        % update gradients
        dxhdx = dxhdx*dfdxh + ko;
        dxhdp = dfdp + dxhdp*dfdxh;

    else    %- Function is called outside of f_fullDCM4fmri

        % Update persistent observation parameters
        ph = Phi;
        ti = ti+1;

        %- Get predicted observations and gradients
        [gx,dgdxh,dgdp] = g_HRF3(xh,Phi,ut,inG);
        %
        %     dgdxh = numericDiff('g_HRF',1,xh,Phi,ut,inG);
        %     dgdp = numericDiff('g_HRF',2,xh,Phi,ut,inG);

        dG_dX = dxhdx*dgdxh;
        dG_dPhi = dgdp + dxhdp*dgdxh;
        %         % empty gradients w.r.t. states
        %         dxhdx = zeros(n,n*4);

    end

    if ti==inG.n_t
        xh = [];
    end
end


% Batch script for sparse prediction
clear all

% --- training method for variable sample size data
method_id = 1;
%case	1 linear_sparse_space_sw
%case	2 linear_sparse_space_vec_sw
%case	3 linear_sparse_stepwise_sw
%case	4 linear_sparse_stepwise_em_sw

% --- Basic Learning Parameters
parm.Ntrain = 2000; % # of total training iteration
parm.Nskip  = 100;	% skip steps for display info

% --- Time delay embedding parameter
parm.Tau   = 1 ;   % Lag time steps
parm.Dtau  = 3 ;   % Number of embedding dimension
parm.Tpred = 0 ;   % Prediction time step : y(t+Tpred) = W * x(t)

% --- Normalization parameter
parm.data_norm  = 1;	% Normalize input and output

% File name of old training result for retraining
old_file = [];

% File name for test data
datafile  = ['./test/test.mat'];
modelfile = ['./test/model'];
newdata   = 1; % = 1: make new data

%parm.Trial  = [1000 200 100];% # of samples in each trial
parm.Trial  = [1000 600];% # of samples in each trial

% --- Make or Load training & test data
if newdata == 0 && exist(datafile,'file')
	load(datafile, ...
		'xdata','ydata','xtest','ytest')
else
	% Training & test data setting
	Tdata  = 1000 ; % # of training data
	Ttest  = 1000 ; % # of test data

	parm.Ydim = 3;
	parm.Xdim = 200;   % Input dim
	parm.Meff = 30;    % Effective Input
	parm.Sdim = 10; % number of sinusoidal input
	parm.Tmin = 50; % minimum period
	parm.Tmax = 200;% maximum period
	parm.SY   = [0.3; 0.1; 0.5];% output moise variance
	parm.Ntrial = length(parm.Trial);

	parm.sy = parm.SY;
	[xdata,ydata,Wout,Weff,Wrdn,Win,Wirr] = ...
		make_train_data(parm, Tdata);

	parm.sy = 0.0;
	[xtest,ytest] = ...
		make_train_data(parm, Ttest, Wout,Wrdn,Win,Wirr);

	if ~isempty(datafile)
		save(datafile, ...
			'xdata','ydata','xtest','ytest','Wout','Weff','parm')
	end
end

T = size(ydata,2);
if T~=size(xdata,2), error('Time of X and Y is not match'); end

if isfield(parm,'data_norm') && parm.data_norm==2
	% Add Bias term
	[M,T,K] = size(xdata);
	xdata = [xdata; ones(1,T,K)];
end;

% Time alignment for prediction using embedding input
[tx,ty] = pred_time_index(xdata,parm);
xdata = xdata(:,tx,:);
ydata = ydata(:,ty,:);
% Adjust sample length for each trial by time embedding
if isfield(parm,'Trial'), parm.Trial = parm.Trial - (T - length(ty)); end;

% Normalize input data
[X,nparm] = normalize_data(xdata, parm.data_norm);
parm.xmean = nparm.xmean;
parm.xnorm = nparm.xnorm;

% Normalize output data
[Y,nparm] = normalize_data(ydata, parm.data_norm);
parm.ymean = nparm.xmean;
parm.ynorm = nparm.xnorm;

% --- Initialization of Model Parameters
if ~isempty(old_file)
	% Start from old result
	load([old_file], 'Model')
else
	Model = [];
end

%profile_on = 1;
%profile_start(profile_on);

%
% --- Sparse estimation
%
switch	method_id
case	1
	[Model, Info] = linear_sparse_space_sw(X, Y, Model, parm);
case	2
	[Model, Info] = linear_sparse_space_vec_sw(X, Y, Model, parm);
case	3
	[Model, Info] = linear_sparse_stepwise_sw(X, Y, Model, parm);
case	4
	[Model, Info] = linear_sparse_stepwise_em_sw(X, Y, Model, parm);
end

%
% --- Estimate prediction error for test data
%

% Time alignment for prediction using embedding input
[tx,ty] = pred_time_index(xtest,parm);
xtest = xtest(:,tx,:);
ytest = ytest(:,ty,:);

if isfield(parm,'data_norm') && parm.data_norm==2
	% Add Bias term
	[M,T,K] = size(xtest);
	xtest = [xtest; ones(1,T,K)];
end;

% Use normalization constant calculated by training data
xtest = normalize_data(xtest, parm.data_norm, parm);

% --- Prediction for test data
ypred = predict_output(xtest, Model, parm);
err   = sum((ytest(:)-ypred(:)).^2)/sum(ytest(:).^2)

if ~isempty(modelfile)
	fsave = [modelfile sprintf('_id%d.mat',method_id)];
	save(fsave, 'Model', 'Info', 'parm');
end

plot_predict

%profile_end(profile_on)
return


function monomial_test035 ( )

%*****************************************************************************80
%
%% MONOMIAL_TEST035 tests MONO_NEXT_GRLEX.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 December 2013
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'MONOMIAL_TEST035\n' );
  fprintf ( 1, '  MONO_NEXT_GRLEX computes the next monomial\n' );
  fprintf ( 1, '  in M variables, in graded lexicographic order.\n' );

  m = 4;

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Let M =  %d\n', m );

  a = 0;
  b = 3;
  seed = 123456789;

  for i = 1 : 10

    [ x, seed ] = i4vec_uniform_ab ( m, a, b, seed );

    fprintf ( 1, '\n' );
    for j = 1 : m
      fprintf ( 1, '  %1d', x(j) );
    end
    fprintf ( 1, '\n' );

    for j = 1 : 5
      x = mono_next_grlex ( m, x );
      for j = 1 : m
        fprintf ( 1, '  %1d', x(j) );
      end
      fprintf ( 1, '\n' );
    end

  end

  return
end


function test_ft_spikedensity()

% MEM 1gb
% WALLTIME 00:10:00
% DEPENDENCY ft_spikedensity

data = [];
nTrials = 100;
nSamples = 1001;
R = 0.51;
% create artificial data.
for iTrial = 1:nTrials
    data.trial{iTrial}(1,:) = round(R*rand(1,nSamples));
    data.trial{iTrial}(2,:) = (R*rand(1,nSamples));
end

data.time(1:nTrials) = {linspace(0,1,nSamples)};
data.fsample = 1000;
data.label{1} = 'spk1';
data.label{2} = 'eeg1';
data.hdr = [];
data.cfg.trl = [];

%%
cfgSdf.timwin        = [-0.02 0.02];
cfgSdf.winfunc        = 'gausswin';
cfgSdf.latency       = [0 3];
cfgSdf.keeptrials = 'yes';
cfgSdf.spikechannel = 1
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
%% show that we can also enter a spike input
spike = ft_checkdata(data, 'datatype', 'spike', 'feedback', 'yes');
%%
[sdf2 sdfdata] = ft_spikedensity(cfgSdf,spike);

any(sdf2.trial(:)-sdf.trial(:))>0
%%
nTrials = length(data.trial);
for iTrial = 1 : 5
    figure, plot(sdfdata.time{iTrial}, sdfdata.trial{iTrial}), hold on,

    spks = find(data.trial{iTrial}(1,:));
    xx = [data.time{iTrial}(1,spks); data.time{iTrial}(1,spks)];
    yy = [ones(1,length(spks))*max(sdfdata.trial{iTrial});ones(1,length(spks))*min(sdfdata.trial{iTrial})];
    hold on
    plot(xx,yy,'r'),
end
nanmean(sdf.avg) % expect 20 hz
close all
%%
% do the same for rectwin and alphawin
cfgSdf.winfunc = 'rectwin';

tic
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
toc
%%
nTrials = length(data.trial);
for iTrial = 1 : 5
    figure, plot(sdfdata.time{iTrial}, sdfdata.trial{iTrial}), hold on,

    spks = find(data.trial{iTrial}(1,:));
    xx = [data.time{iTrial}(1,spks); data.time{iTrial}(1,spks)];
    yy = [ones(1,length(spks))*max(sdfdata.trial{iTrial});ones(1,length(spks))*min(sdfdata.trial{iTrial})];
    hold on
    plot(xx,yy,'r'),
end
close all

% note that the firing rate matches to 1000/41ms ~ 25 hz

%% for alphawin
cfgSdf.winfunc = 'alphawin';

[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
nTrials = length(data.trial);
for iTrial = 1 : 5
    figure, plot(sdfdata.time{iTrial}, sdfdata.trial{iTrial}), hold on,

    spks = find(data.trial{iTrial}(1,:));
    xx = [data.time{iTrial}(1,spks); data.time{iTrial}(1,spks)];
    yy = [ones(1,length(spks))*max(sdfdata.trial{iTrial});ones(1,length(spks))*min(sdfdata.trial{iTrial})];
    hold on
    plot(xx,yy,'r'),
end
close all

%% now check if we use different timwinsif we see that back with a gaussian
cfgSdf = [];
cfgSdf.timwin = [0 0.02];
cfgSdf.winfunc = 'gausswin';
cfgSdf.latency = [0 1];

[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
nTrials = length(data.trial);
for iTrial = 1 : 5
    figure, plot(sdfdata.time{iTrial}, sdfdata.trial{iTrial}), hold on,

    spks = find(data.trial{iTrial}(1,:));
    xx = [data.time{iTrial}(1,spks); data.time{iTrial}(1,spks)];
    yy = [ones(1,length(spks))*max(sdfdata.trial{iTrial});ones(1,length(spks))*min(sdfdata.trial{iTrial})];
    hold on
    plot(xx,yy,'r'),
end
close all

%% try if this function also works with different latencies as promised in the help

clear
nTrials = 100;
nSamples = 1001;
R = 0.51;
% create artificial data.
data.fsample = 1000;

for iTrial = 1:nTrials
    % first put the latency as an integer of the sample frequency
    latency = 0 + round(20*(rand-0.5))/1000; % is going to include some trials, and exlude some
    latencyEnd = 1 + round(20*(rand-0.5))/1000;
    timeaxis = latency:(1/data.fsample):latencyEnd;
    data.time{iTrial}  = timeaxis;
    data.trial(iTrial) = {round(R*rand(1,length(timeaxis)))};
    latencies(iTrial,:) = minmax(timeaxis);
end
close all

data.label{1} = 'spk1';
data.hdr = [];
data.cfg.trl = [];
%% set the defaults
cfgSdf = [];
cfgSdf.latency = 'minperiod'
%cfgSdf.checkspikechan = 'no'
cfgSdf.timwin = [-0.25 0.25]
cfgSdf.winfunc = 'rectwin'
[sdf sdfdata] = ft_spikedensity(cfgSdf,data); % warning here!
figure, plot(sdf.time,sdf.avg)

%% allow variable trial length, check the dof
cfgSdf = [];
cfgSdf.keeptrials = 'yes';
cfgSdf.timwin = [-0.05 0.05];
cfgSdf.winfunc = 'rectwin';
cfgSdf.latency = 'maxperiod';
cfgSdf.vartriallen = 'yes';
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
figure, plot(sdf.time,sdf.avg)
any(cellfun(@length,data.trial)-cellfun(@length,sdfdata.trial))
% note the discrepancy of one sample, why?
%%
nTrials = length(data.trial);
for iTrial = 1 : 5
    figure, plot(sdfdata.time{iTrial}, sdfdata.trial{iTrial}), hold on,

    spks = find(data.trial{iTrial});
    xx = [data.time{iTrial}(spks); data.time{iTrial}(spks)];
    yy = [ones(1,length(spks))*max(sdfdata.trial{iTrial});ones(1,length(spks))*min(sdfdata.trial{iTrial})];
    hold on
    plot(xx,yy,'r'),
end
close all

%sdfdata.trial has maximum length if it fits the window, otherwise it has less length
figure, plot(sdf.time,sdf.avg)
pause(1)
close all

%% do not allow variable trial length
cfgSdf = [];
cfgSdf.timwin = [-0.001 0.001];
cfgSdf.winfunc = 'rectwin';
%cfgSdf.winfuncopt = 0.0;
cfgSdf.latency = [0 1];
cfgSdf.vartriallen = 'yes';
sum(latencies(:,1)>0| latencies(:,2)<1)
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
figure, plot(sdf.time,sdf.avg)
%% do not allow variable trial length
cfgSdf = [];
cfgSdf.timwin = [-0.02 0.02];
cfgSdf.winfunc = 'rectwin';
cfgSdf.latency = [0 1];
cfgSdf.vartriallen = 'no';
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
latencies(sdf.cfg.trials,:)
figure, plot(sdf.time,sdf.avg)
pause(1)
close all

%% check all options one for one
cfgSdf = [];
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
%%
cfgSdf.keeptrials = 'no';
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
cfgSdf = [];
%%
cfgSdf.latency = 'prestim'
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
cfgSdf = [];
%%
cfgSdf.winfunc = 'gauss'
[sdf sdfdata] = ft_spikedensity(cfgSdf,data);
cfgSdf = [];


function []=plot_reprojectVSreal_points(CBimagesInfo,cameraCBparameters)
%% function for plot each image with reprojected points vs. real points and straight lines, and reprojection error statistics in STEP0
%
% INPUTS:
% * CBimagesInfo
% * cameraCBparameters:  a structure containing all the calibration parameters created in STEP0
%
%%
imageIndecesToDisplay=1:numel(cameraCBparameters.imagesUsed);

% plot each image with reprojected points vs. real points and straight lines
I=CBimagesInfo.I;
Nimages=numel(imageIndecesToDisplay);
imagePoints=cameraCBparameters.imagePoints(:,:,imageIndecesToDisplay);
reprojectedPoints=cameraCBparameters.cameraParameters.ReprojectedPoints(:,:,imageIndecesToDisplay);
reprojectionErrors=cameraCBparameters.cameraParameters.ReprojectionErrors(:,:,imageIndecesToDisplay);
Nrows=cameraCBparameters.boardSize(1);
Ncols=cameraCBparameters.boardSize(2);
icam=cameraCBparameters.icam;

reprojectedPointsMat=reshape(reprojectedPoints,Nrows-1,Ncols-1,2,Nimages);
reprojectedPointsHorizonal=reprojectedPointsMat([1 size(reprojectedPointsMat,1)],:,:,:);
reprojectedPointsVertical=reprojectedPointsMat(:,[1 size(reprojectedPointsMat,2)],:,:);

% PLOT
% define tabs
f = figure('name',['Reprojected points on all images taken by camera ' num2str(icam) '. Scroll between tabs to view the different images'],'units','normalized','outerposition',[.1 .1 .8 .8]);;
tabgp = uitabgroup(f);

icount=0;
for iplot=cameraCBparameters.imagesUsed(imageIndecesToDisplay)
    icount=icount+1;
    %plot
    tab(icount) = uitab(tabgp,'Title',['IM' num2str(iplot)]);

    axes('Parent',tab(icount)); % somewhere to plot

    subplot(1,6,1:5)

    imshow(I(:,:,:,iplot)); hold all;
    plot(imagePoints(:,1,icount), imagePoints(:,2,icount),'go','linewidth',1.5);
    plot(reprojectedPoints(:,1,icount),reprojectedPoints(:,2,icount),'r+','linewidth',1.5);
    title(['Camera ' num2str(icam) ' Image ' num2str(iplot)]);
    drawnow
    % plot straight lines
    plot(squeeze(reprojectedPointsHorizonal(:,1,1,icount)),squeeze(reprojectedPointsHorizonal(:,1,2,icount)),'-c','linewidth',1.5);
    plot(squeeze(reprojectedPointsVertical(1,:,1,icount)),squeeze(reprojectedPointsVertical(1,:,2,icount)),'-m','linewidth',1.5);
    for icol=2:Ncols-1
        plot(squeeze(reprojectedPointsHorizonal(:,icol,1,icount)),squeeze(reprojectedPointsHorizonal(:,icol,2,icount)),'-c','linewidth',1.5);
    end
    for irow=1:Nrows-1
        plot(squeeze(reprojectedPointsVertical(irow,:,1,icount)),squeeze(reprojectedPointsVertical(irow,:,2,icount)),'-m','linewidth',1.5);
    end
    legend('Detected Points','Reprojected Points','straight horizontal lines','straight vertical lines');
    hold off;

    reprojectionErrorsNow=reprojectionErrors(:,:,icount);
    reprojectionErrorsMgnNow=sqrt(sum(reprojectionErrorsNow.^2,2));
    reprojectionErrorsNow=[reprojectionErrorsNow reprojectionErrorsMgnNow];

    subplot(1,6,6)
    boxplot(reprojectionErrorsNow,'Labels',{'X','Y','Mgn'});
    ylim([-max(abs(reprojectionErrorsNow(:))) max(abs(reprojectionErrorsNow(:)))]);
    title({'Reprojection error'; 'statistics [pix]'});

    drawnow
end

end

%%
% MultiDIC: a MATLAB Toolbox for Multi-View 3D Digital Image Correlation
%
% License: <https://github.com/MultiDIC/MultiDIC/blob/master/LICENSE.txt>
%
% Copyright (C) 2018  Dana Solav
%
% If you use the toolbox/function for your research, please cite our paper:
% <https://engrxiv.org/fv47e>


function [W]=downbeam_lambda(A,H,K,M,grt,beta,lambda)
    W=zeros(M,K);
    A=A+lambda.*eye(M);
    A=A^(-1);
    for k0=1:K
        W(:,k0)=sqrt(grt(k0))*beta(k0)*A*H(k0,:)';
    end
end


function [vDrate] = calc_InterpBgrate(mGrid,fMmin)
% function [vDrate] = calc_InterpBgrate(mGrid,fMmin)
% --------------------------------------------------
% Get background rates from a Frankel model on the grid points of a rate
% change grid. Sums the rates for magnitudes larger than fMmin
%
% Incoming:
% mGrid : X-Y grid to interpolate on ([Lon Lat])
% fMmin : Minimum magnitude (generally the same as Mc)
%
% Outgoing:
% vDrate : Vector of DAILY seismicity rates
%
% last update: 09.07.2004
% jochen.woessner@sed.ethz.ch

% Load Frankel model with daily background rate
% Contains variable nullRates :[Lonmin Lonmax Latmin Latmax Dpethmin Depthmax Magmin Magmax DailyRate
% Weight]

% Load CFS file
[sFilename, sPathname] = uigetfile('*.mat', 'Pick Frankel DailyRate MAT-file');
sHelp = [sPathname sFilename];
sFile = [sFilename(1:length(sFilename)-4)];
load(sHelp)

% Loop over grid node positions
for nCnt = 1:length(mGrid(:,1))
    fXcoord = mGrid(nCnt,1);
    fYcoord = mGrid(nCnt,2);
    vSel = (fXcoord >= nullRates(:,1) & fXcoord < nullRates(:,2) &...
        fYcoord >= nullRates(:,3) & fYcoord < nullRates(:,4) & fMmin > nullRates(:,7));
    if ~isempty(nullRates(vSel,9))
        fAllSumMagRate = max(cumsum(nullRates(vSel,9)));
        vDrate(nCnt) = fAllSumMagRate;
    else
        vDrate(nCnt) = nan;
    end
end


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

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

[Hkt_r, cx, cy, Wxk] = loglikGaPreadparamHfix(x,varargin);

Hkt=exp(Hkt_r); %nonnegativity constrains
[Wxkbg,Hktbg]=addbg(Wxk, Hkt, peval.bg);

P=Wxkbg*Hktbg; %current approximation

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

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

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

% gf = [reshape(gfHkt,1,peval.nt*peval.ncomp), gfcx', gfcy'];
% gf = [reshape(gfHkt,1,peval.nt*peval.ncomp)];
gf = [gfcx', gfcy'];
gf=-gf; %conjugate gradient is minimizing!
end

function xxvc = lineargrad(sizevec, cx, dir)
switch dir
    case 'xx'
        xxp=double(xx(sizevec, 'corner')); %linear function - pixels
    case 'yy'
        xxp=double(yy(sizevec, 'corner')); %linear function - pixels
    otherwise
        error('Wrong dir')
end
xxv=reshape(xxp,sizevec(1)*sizevec(2),sizevec(3)); %linear function - vector
xxvc=xxv-repmat(cx,sizevec(1)*sizevec(2),1);
end


% op_CSIFOurierTransform.m
% Brenden Kadota, SunnyBrook Hosptial 2021.
%
% Does spectral and spatial fourier transform on MRSI structure. The fast
% fourier transform is done on the spectral dimension. If the spatial k
% space is cartesian, the fast fourier transform is applied.
% USAGE:
% out = op_CSIFourierTransform(out, spatialFT, spectralFT, isCartesian)
%
%
% input:    in         = Twix object of CSI data
%           spatialFT  = Boolean flag (1 or 0) to compute fourier
%                        transfrom along spatial dimension
%           spectralFT = Same as above but for the spectral dimension
%           isCartesian= boolean flag for fft or slow fourier tranform alon
%                        the spatial dimension
%
% output:   in         = Twix object with new out.specs field of the
%                         fourier transformed data
function MRSIStruct = op_CSIFourierTransform(MRSIStruct, k_file, fourierTransform)
    arguments
        MRSIStruct (1,1) struct
        k_file (1,:) char {mustBeFileorDefault} = ""
        fourierTransform.spatial (1,1) logical {mustHaveSpatial(fourierTransform.spatial, MRSIStruct)}
        fourierTransform.spectral (1,1)  logical {mustHaveSpectral(fourierTransform.spectral, MRSIStruct)}
    end
    % set default values for spatial and spectral fourier transform
    fourierTransform = setDefaultFlags(fourierTransform, MRSIStruct);

    % spatial dimension fourier transform
    if (fourierTransform.spatial == 1)
        disp('Calculating spatial dimension');
        if(k_file == "")
            %applying the fast fourier transform if k space is cartesian
            MRSIStruct = applyFastFourierTransformSpatial(MRSIStruct);
        else
            [kTrajectory, numSpatial, numSpectral] = readKSpaceFile(k_file, MRSIStruct);
            MRSIStruct = slowFourierTransfrom(MRSIStruct, kTrajectory, numSpatial, numSpectral);
            MRSIStruct = calculateSpectralValues(MRSIStruct, numSpatial, numSpectral);
        end

        MRSIStruct = setFlags(MRSIStruct, 'spatialFT', true);
        %waterRemoved = op_CSIRemoveWater(MRSIStruct);
    end

    % spectral fourier transform
    if (fourierTransform.spectral)
        % fast fourier transform along the time dimension
        disp('Calculating spectral dimension');
        MRSIStruct = fastFourierTransformTime(MRSIStruct);
    end

end

function sft2_Oper = sft2_Operator(InTraj, OutTraj, Ift_flag)
    %
    % sft2 Perform 2-dimensional slow Fourier transform
    %
    % This function was written by Bernhard Strasser, April 2018.
    %
    %
    % The function performs a slow Fourier transform in two spatial dimensions by using the definition of the Fourier Transform
    % FT(f)(a_j) = sum(k=-N/2;N/2-1) f(x_k)exp(-2pi i x_k a_j)
    % (For even N. For odd, change sum slightly)
    %
    %
    % sft2Operator = sft2(A,Ifft_flag)
    %
    % Input:
    % -         Ift_flag                    ...     Flag of 0 or 1 determining if an inverse Fourier transform or normal should be performed.
    % -         InputSize                   ...     Size of Input data.
    %
    % Output:
    % -         sft2Operator                ...     Fourier transformation matrix which can be applied to the data by Out = sft2Operator*In
    %
    %
    % Feel free to change/reuse/copy the function.
    % If you want to create new versions, don't degrade the options of the function, unless you think the kicked out option is totally useless.
    % Easier ways to achieve the same result & improvement of the program or the programming style are always welcome!
    % File dependancy: ?
    % 0. Preparations

    % Define Exponent of exp
    if(~Ift_flag)
        Expy = -2*pi*1i;
    else
        Expy = 2*pi*1i;
    end

    % Define Output Size
    NOut = size(OutTraj,1);

    % 1. FT

    sft2_Oper = zeros([size(OutTraj,1) size(InTraj,1)]);
    for j=1:NOut
        sft2_Oper(j,:) = exp(Expy*(OutTraj(j,1)*InTraj(:,1) ...
            + OutTraj(j,2)*InTraj(:,2)));
    end

    if(Ift_flag)
        sft2_Oper = sft2_Oper / (size(InTraj,1));
    end

end

function mustHaveSpatial(a, in)
    if isfield(in, 'spatialFT') && (a == true && in.spatialFT == 1)
        eidType = 'spatialTransform:noSpatialTransform';
        msgType = 'Spaitial Fourier Transform already done!';
        throwAsCaller(MException(eidType,msgType))
    end
end

function mustHaveSpectral(a, in)
    if isfield(in, 'spectral') && (a == true && in.spectral == 1)
        eidType = 'spectralTransform:noSpectralTransform';
        msgType = 'Spectral Fourier Transform already done!';
        throwAsCaller(MException(eidType,msgType))
    end
end

function mustBeFileorDefault(file)
    if ~isfile(file) && ~strcmp(file, "")
        eidType = 'mustBeFile:notAFile';
        msgType = 'Invalid value fo k_file, must be a file';
        throwAsCaller(MException(eidType,msgType))
    end
end

function fourierTransform = setDefaultFlags(fourierTransform, in)
    if(~isfield(fourierTransform, 'spatial'))
        if(in.flags.spatialFT)
            fourierTransform.spatial = 0;
        else
            fourierTransform.spatial = 1;
        end
    end
    if(~isfield(fourierTransform, 'spectral'))
        if(in.flags.spectralFT)
            fourierTransform.spectral = 0;
        else
            fourierTransform.spectral = 1;
        end
    end
end

function MRSIStruct = applyFastFourierTransformSpatial(MRSIStruct)
    disp('Applying fast fourier transform');
    %apply half pixel shift
    MRSIStruct = halfPixelShift(MRSIStruct);
    %get data
    data = getData(MRSIStruct);
    xDimension = getDimension(MRSIStruct, 'kx');
    if(mod(getSizeFromDimensions(MRSIStruct, {'kx'}), 2) == 1)
        data = circshift(data, 1, xDimension);
    end
    data = fftshift(fft(fftshift(data, xDimension), [], xDimension), xDimension);

    yDimension = getDimension(MRSIStruct, 'ky');
    if(mod(getSizeFromDimensions(MRSIStruct,{'ky'}), 2) == 1)
        data = circshift(data, 1, yDimension);
    end
    data = fftshift(fft(fftshift(data, yDimension), [], yDimension), yDimension);
    MRSIStruct = setData(MRSIStruct, data);

    MRSIStruct = setDimension(MRSIStruct, 'x', getDimension(MRSIStruct, 'kx'));
    MRSIStruct = setDimension(MRSIStruct, 'y', getDimension(MRSIStruct, 'ky'));
    MRSIStruct = setDimension(MRSIStruct, 'z', getDimension(MRSIStruct, 'kz'));
    MRSIStruct = setDimension(MRSIStruct, 'kx', 0);
    MRSIStruct = setDimension(MRSIStruct, 'ky', 0);
    MRSIStruct = setDimension(MRSIStruct, 'kz', 0);
end

function MRSIStruct = slowFourierTransfrom(MRSIStruct, kTrajectory, numSpatial, numSpectral)

    [xCoordinates, yCoordinates, imageTrajectory] = getImageTrajectory(MRSIStruct);

    %creating fourier transform operator for spatial domain
    sftOperator = sft2_Operator(kTrajectory, imageTrajectory, 0);

    %permute so first 3 dimensions are x, y and t
    [MRSIStruct, prevPermute, prevSize] = reshapeDimensions(MRSIStruct, {'t', 'ky'});
    data = getData(MRSIStruct);

    % apply slow fourier transform matrix to data
    image = applySlowFourierTranformMatrix(MRSIStruct, sftOperator, data, numSpectral, numSpatial);
    MRSIStruct = setData(MRSIStruct, image);

    kyDimension = getDimension(MRSIStruct, 'ky');
    prevPermute = removeDimPrevPermute(prevPermute, kyDimension);
    prevPermute = addDimPrevPermute(prevPermute, 'y', kyDimension);
    prevPermute = addDimPrevPermute(prevPermute, 'x', kyDimension + 1);

    prevSize(1) = numSpectral;
    prevSize(2) = length(yCoordinates);
    prevSize = [prevSize(1:2), length(xCoordinates), prevSize(3:end)];
    MRSIStruct = reshapeBack(MRSIStruct, prevPermute, prevSize);
end

function image = applySlowFourierTranformMatrix(MRSIStruct, sftOperator, data, numSpectral, numSpatial)
    yLength = length(getCoordinates(MRSIStruct, 'y'));
    xLength = length(getCoordinates(MRSIStruct, 'x'));

    %image dimensions after fourier tranform is time, y, x, and extras.
    imageDimensions = [numSpectral, yLength, xLength, ...
                                        getSizeFromDimensions(MRSIStruct, {'extras'})];
    image = zeros(imageDimensions);

    for iPoint = 1:numSpectral
        startingPoint = (iPoint - 1)*numSpatial + 1;
        endingPoint = iPoint * numSpatial;
        kSpaceSlice = data(startingPoint:endingPoint, :, :);
        vectorizedSlice = reshape(kSpaceSlice, [], size(kSpaceSlice,3));
        ftVectorizedSlice = sftOperator*vectorizedSlice;

        imageSlice = reshape(ftVectorizedSlice, [yLength, xLength, size(ftVectorizedSlice,2)]);
        image(iPoint, :, :, :) = imageSlice;
    end
end

function [xCoordinates, yCoordinates, imageTrajectory] = getImageTrajectory(MRSIStruct)
    xCoordinates = getCoordinates(MRSIStruct, 'x');
    yCoordinates = getCoordinates(MRSIStruct, 'y');

    %applying the slow fourier transform if the k space is non cartesian
    [x, y] = meshgrid(xCoordinates, yCoordinates);
    imageTrajectory = [x(:), y(:)];
end

function MRSIStruct = fastFourierTransformTime(MRSIStruct)
    data = getData(MRSIStruct);
    timeDimension = getDimension(MRSIStruct, 't');
    %fourier transform in the spectral domain
    data = fftshift(fft(data, [], timeDimension), timeDimension);

    MRSIStruct = setData(MRSIStruct, data);
    ppm = calculatePPM(MRSIStruct);

    if strcmp(MRSIStruct.nucleus,'1H')
        ppm = ppm + 4.65;
    end

    MRSIStruct = setPPM(MRSIStruct, ppm);
    %flip ppm
    MRSIStruct = setFlags(MRSIStruct, 'spectralFT', true);
end

function ppm = calculatePPM(MRSIStruct)
    %get gamma and nucleus
    gamma = MRSIStruct.gamma;

    %lower bounds of frequency
    spectralWidth = getSpectralWidth(MRSIStruct);
    timeSize = getSizeFromDimensions(MRSIStruct, {'t'});

    step = spectralWidth/timeSize;
    lowerBound = -spectralWidth/2 + step/2;
    %upper bounds of frequency
    upperBound = spectralWidth/2 - step/2;

    %calculating the frequency
    frequency=lowerBound:step:upperBound;

    %calculating the ppm
    ppm=-frequency/(MRSIStruct.Bo*gamma);
end

function MRSIStruct = calculateSpectralValues(MRSIStruct, numSpatial, numSpectral)
    spectralDwellTime = calculateSpectralDwellTime(MRSIStruct, numSpatial);
    spectralWidth = 1/spectralDwellTime;
    spectralTime = calculateSpectralTime(spectralDwellTime, numSpectral);

    MRSIStruct = setSpectralWidth(MRSIStruct, spectralWidth);
    MRSIStruct = setSpectralDwellTime(MRSIStruct, spectralDwellTime);
    MRSIStruct = setSpectralTime(MRSIStruct, spectralTime);
end

function spectralDwellTime = calculateSpectralDwellTime(MRSIStruct, spatialPoints)
    adcDwellTime = getAdcDwellTime(MRSIStruct);
    spectralDwellTime = spatialPoints * adcDwellTime;
end

function spectralTime = calculateSpectralTime(spectralDwellTime, spatialPoints)
    spectralTime = 0:spectralDwellTime:spectralDwellTime*(spatialPoints - 1);
end

function MRSIStruct = halfPixelShift(MRSIStruct)
    kx = getCoordinates(MRSIStruct, 'kx');
    ky = getCoordinates(MRSIStruct, 'ky');
    halfPixelX = getVoxSize(MRSIStruct, 'x')/2;
    halfPixelY = getVoxSize(MRSIStruct, 'y')/2;
    kShift = kx*halfPixelX + ky'*halfPixelY;

    [MRSIStruct, prevPermute, prevSize] = reshapeDimensions(MRSIStruct, {'ky', 'kx'});
    data = getData(MRSIStruct);
    data = data .* exp(-1i*2*pi*kShift);
    MRSIStruct = setData(MRSIStruct, data);
    MRSIStruct = reshapeBack(MRSIStruct, prevPermute, prevSize);
end


% CLASSIF_ERR Calculates the classification error.
%
% Usage
%    err = CLASSIF_ERR(labels, test_set, src)
%
% Input
%    labels (int): The predicted labels corresponding to the testing in-
%       stances.
%    test_set (int): The object indices of the testing instances.
%    src (struct): The source from which the objects were taken.
%
% Output
%    err (numeric): The classification error.
%
% See also
%    AFFINE_TEST, SVM_TEST

function err = classif_err(labels,test_set,src)
	truth = [src.objects(test_set).class];

	if isfield(src,'cluster')
		cluster = src.cluster;
	else
		cluster = 1:max(truth);
	end

	err = 1-sum(bsxfun(@eq,cluster(labels),cluster(truth)),2)/length(truth);
end


function res = eq(a,b)
%EQ           Implements  a == b  elementwise for intervals a and b
%
% a and b must be either both real or both complex
%

% written  10/16/98     S.M. Rump
% modified 11/30/98     S.M. Rump
% modified 06/24/98     S.M. Rump  multi-dimensional arrays
% modified 09/01/00     S.M. Rump  result array
%                                  comparison real/complex
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
%

  if ~isa(a,'intval')
    if b.complex
      res = ( b.mid==a ) & ( b.rad==0 );
    else
      res = ( b.inf==a ) & ( b.sup==a );
    end
    return
  end

  if ~isa(b,'intval')
    if a.complex
      res = ( a.mid==b ) & ( a.rad==0 );
    else
      res = ( a.inf==b ) & ( a.sup==b );
    end
    return
  end

  if ( a.complex ~= b.complex )
    if a.complex
      error('intval comparison == of complex and real')
    else
      error('intval comparison == of real and complex')
    end
  end

  if a.complex
    res = (a.mid==b.mid) & (a.rad==b.rad);
  else
    res = (a.inf==b.inf) & (a.sup==b.sup);
  end


% Script: call_rcgrid.m
% Script to determine rate changes in aftershock sequences on a grid with calc_rcgrid.m.
% Plots the first time slice at the end.
% The function works on the catalog newt2!!!
%
% Output variables:
% RCREL : Relative rate change matrix
%
% J.Woessner
% last update: 03.07.03

% Get input parameters
prompt  = {'Enter forecast period (number of events):','Enter maximum time of learning period (days):',...
    'Enter timesteps (days):','Longitude spacing / [deg]:','Latitude spacing / [deg]:','Radius / [deg]:'};
title   = 'Parameters ';
lines= 1;
def     = {'50','100','5','0.1','0.1','0.15'};
answer  = inputdlg(prompt,title,lines,def);
step = str2double(answer{1});
maxtime = str2double(answer{2});
timestep = str2double(answer{3});
dx = str2double(answer{4});
dy = str2double(answer{5});
r = str2double(answer{6});

% Calculate rate changes on grid
[RCREL,xx,yy] = calc_rcgrid(newt2,dx,dy,r,step,maxtime,timestep);

[existFlag,figNumber]=figure_exists('Rate change time slice',1);
newRCMapFlag=~existFlag;

% Set up figure for time slice plots
if newRCMapFlag
    rctfig = figure_w_normalized_uicontrolunits('tag','rtslice',...
        'Name','Rate change time slice',...
        'NumberTitle','off', ...
        'NextPlot','replace', ...
        'backingstore','on',...
        'Visible','on');
    rctax = axes('tag','axrctfig','NextPlot','replace','box','on');

    matdraw
    %
    uimenu('Label','Choose time slice', 'Callback','plot_timeslice')
end

% Other colormap
% cc = colormap;
% for i = 25:40
%     cc(i,:) = [1 1 1];
% end
% colormap(cc)

% get longitude / latitude
lon = a.Longitude; lat = a.Latitude;
% define grid
xmax = round(10*max(lon))/10+dx;
xmin = round(10*min(lon))/10-dx;
ymax = round(10*max(lat))/10+dy;
ymin = round(10*min(lat))/10-dy;

figure_w_normalized_uicontrolunits(rctfig)
%gcf=findobj('tag','rtslice')
%set(gcf,'Name','Rate change time slice');
set(gca,'tag','axrctfig');
hold on
xx = xmin-dx/2:dx:xmax-dx/2;
yy = ymax+dy/2:-dy:ymin+dy/2; yy = yy';
pcolor(xx,yy,RCREL(:,:,1))
shading flat
axis equal
caxis([-4 4])
colorbar

% plot_tslice=uicontrol('Style', 'pushbutton', 'String', 'Choose time slice','Units','normalized',...
%     'Position',[0.02 0.02 0.3 0.06],'Callback','plot_timeslice');
%hold off;


function r8_cosd_test ( )

%*****************************************************************************80
%
%% R8_COSD_TEST tests R8_COSD.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 January 2015
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'R8_COSD_TEST\n' );
  fprintf ( 1, '  R8_COSD computes the cosine of an angle\n' );
  fprintf ( 1, '  given in degrees.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  ANGLE    R8_COSD(ANGLE)\n' );
  fprintf ( 1, '\n' );

  for i = 0 : 15 : 360
    angle = i;
    fprintf ( 1, '  %8.2f  %14.6g\n', angle, r8_cosd ( angle ) );
  end

  return
end


function [] = fcnninfo()
%FCNNINFO Parameters and notation of fully-connected neural net.
%   Background for the terminology and parameters used in all fcnn
%   related functions can be found in Section 14.5 of DIPUM3E. In
%   paticular, see Fig. 14.15.
%
%   This function is used to reduce duplication in the documentation of
%   the various functions used to implement a fully-connected neural net.
%   In those functions, the user is asked to type
%
%    >> help fcnninfo
%
%   at the prompt for a list of parameters and a detailed explanation of
%   the role they play in each function and in the network.
%
% PARAMETERS FOR SPECIFYING THE ARCHITECTURE OF AN FCNN.
%
%  The fully-connected neural net requires only three (TWO!!!) parameters
%  specified by a user: (1) The number of nodes per layer. (2) The
%  activation function used in each layer. (3) The learning rate
%  constant. These are specified as a structure, fcnnparam, with the
%  following fields.
%
% fcnnparam.NumNodes
%  A vector containing the number of nodes per layer. The number of
%  nodes in the first layer is equal to the dimensionality of the input
%  vectors. The number of nodes in the output layer is equal to the
%  number of pattern classes. The number of hidden layers, and the
%  number of nodes in each is arbitrary. If no hidden layers are
%  specifived, the neural net will act as a linear classifier. Example:
%  fcnnparam.NumNodes = [6 3 2] is an fcnn whose input vectors are
%  6-dimensional, it has one hidden layer with three nodes, and the
%  number of pattern classes it can recognize is two. The number of
%  layers, L, is computed as L = numel([fcnnparam.NumNodes]).
%
% fcnnparam.ActivationFunction
%  A cell array of size L - 1, the kth element of which is a character
%  string giving the activation function to be used in layer k for 2 <=
%  k <= L. Valid activation functions are: 'sigmoid', 'tanh', and
%  'ReLU'. If only one activation function is specified, that activation
%  function is used in all layers. The default when no activation is
%  specified is {'sigmoid'}.
%
% fcnnparam.Alpha
%  The learning rate constant. It defaults to 1.0.
%
% FCNN PARAMETERS COMPUTED BY VARIOUS FUNCTIONS IN THE FCNN TOOLKIT.
% THESE ARE THE VALUES THAT ARE PASSED BACK-AND-FORTH BETWEEN
% FEEDFORWARD, BACKPROPAGATION, AND WHEN THE FCNN IS ULTIMATELY USED FOR
% CLASSIFICATION.
%
%  A fully-connected neural network is defined by a structure named
%  fcnn, whose fields are as follows:
%
%  L denotes the number of layers in the fcnn. k = 1 is the input layer,
%  and k = L is the output layer. Layers 1 < k < L are hidden layers.
%
% fcnn(k).NumNodes           (formatted in func fcnninit from fcnnparam)
%  A 1-by-L vector containing the number of nodes per layer in the fcnn.
%  The number of nodes in the 1st layer, fcnn(1).NumNodes, is equal to
%  the dimension of the input pattern vectors. The number of nodes in
%  the last layer, fcnn(L).NumNodes is equal to the number of pattern
%  classes. The number L of layers is computed as L =
%  numel([fcnn.NumNodes]).
%
% fcnn(k).ActivationFunction (formatted in func fcnninit from fcnnparam)
%  The kth element of a 2-by-Lc cell array giving the type of activation
%  function used in layer k, for 2 <= k <= L. Valid activation functions
%  are: 'sigmoid', 'tanh', and 'ReLU'. If only one activation function
%  is specified in fcnnparam.ActivationFunction, that activation
%  function is used in all layers. The default when no activation is
%  specified is fcnn(k).ActivationFunction = {'sigmoid'} for k =
%  2,...,L.
%
% fcnn(k).Alpha              (formatted in func fcnninit from fcnnparam)
%  The learning rate constant. This is a scalar specified in
%  fcnnparam.Alpha, but for consistency in structure notation, it is
%  converted two a vector, all elements of which are the same:
%  fcnn(k).Alpha = fcnnparam.Alpha for for k = 1,2,...,L.
%
% fcnn(k).Weights   (computed initially in function fcnninit and updated
%                    in function fcnnbp during training)
%  For each layer k, 2 <= k <= L, fcnn(k).Weights is a matrix of size
%  fcnn(k - 1).NumNodes-by-fcnn(k).NumNodes, containing the weights
%  associated with the nodes in layer k.
%
% fcnn(k).Biases    (computed initially in function fcnninit and updated
%                     in function fcnnbp during training)
%  For each layer k, 2 < k <= L, this is a fcnn(k).NumNodes-by-1 vector
%  containing the biases associated with the nodes in layer k.
%
%  fcnn(k).HprimeZ                         (computed in function fcnnff)
%  The output of layer k before activation, 2 <= k <= L. This is a
%  matrix of size fcnn(k).NumNodes-by-NP, where NP is the number of
%  pattern vectors input into the fcnn simultaneously.
%
% fcnn(k).A                                (computed in function fcnnff)
%  The output (activation) values of layer k, 1 <= k <= L. This is a
%  matrix of size fcnn(k).NumNodes-by-NP, where NP is the number of
%  pattern vectors input into the fcnn simultaneously. fcnn(1).A is
%  equal to the input pattern matrix, and fcnn(L).A is the matrix of
%  output values. Each colum of A are all the output activation values
%  corresponding to one input pattern vector.
%
% fcnn(k).D                                (computed in function fcnnbp)
%  This is the error matrix of layer k, 2 <= k <= L. It is computed
%  during backpropagation and its dimensions are the same as the
%  dimensions of fcnn(k).A. The error matrix and fcnn.HprimeZ are used
%  to update the weights (and biases) for the fcnn. An extra backprop
%  step is taken to generate fcnn(1).D. The extra backprop step brings
%  the backprop output (going in the reverse direction) to the same
%  location as the feedforward output of the cnn after vectorization. No
%  fcnn(1).HprimeZ is computed because this quantity is related only to
%  the fully connected net.The extra step does not affect any other fcnn
%  functions.
%
% APPLICATION-SPECIFIC INPUTS.
%
% fcnndatain.X                                        (provided by user)
%  The input training patterns. This is a matrix of size dim-by-NP where
%  dim = the dimensionality of the patterns and NP = number of pattern
%  vectors. That is, fcnndatain.X(:,k) is the kth input pattern vector.
%
% fcnndatain.R                                        (provided by user)
%  The class membership matrix. This is a matrix of size NC-by-NP, where
%  NC is the number of pattern classes. As explained in Section 14.SS,
%  column fcnndatain.R(:,k) has a 1 in the jth position if the kth
%  pattern vector belongs to class j.
%
% fcnndatain.Epochs                                   (provided by user)
%  The number of training epochs.
%
% fcnndatain.MiniBatchSize                            (provided by user)
%  The minibatch size used during training. The ratio of the number of
%  training patterns to the minibatch size must be an integer (whole
%  number).
%
% USING THE FCNN AS A CLASSIFIER
%
%  In DIPUM3E, the objective of training a fully-connected net is to use
%  it as a pattern classifier. This task is performed by function
%  fcnnclassifier, which is called as follows:
%
%           classifieroutput = fcnnclassifier(classifierinput)
%
%  where classifierinput and classfieroutput are structures whose fields
%  are explained below.
%
% classifierinput.fcnn                                (provided by user)
%  The fully connected neural net to be used as the classfier.
%  Typically, classifierinput.fcnn = fcnn, the neural net obtained from
%  training.
%
% classifierinput.X                                   (provided by user)
%  Pattern matrix, each column of which is a pattern vector.
%
% classifierinput.R                                   (provided by user)
%  Class membership matrix for the input pattern vectors. This is an
%  optional input that, if provided, will be used to compute the correct
%  classification rate.
%
% OUTPUTS FROM THE VARIOUS FUNCTIONS IN THE fcnn TOOLBOX
%
% fcnndataout.MSE                       (computed in function fcnntrain)
%  The mean-squared error during training, computed as the sum of the output errors squared, divided by 2. This a a vector with (NumInput
%  Patterns)/(MinibactSize)*fcnndatain.Epochs elements.
%
% fcnndataout.SmoothMSE                 (computed in function fcnntrain)
%  Smoothed version of fcnndataout.MSE.
%
% classifieroutput.Class           (computed in function fcnnclassifier)
%  A vector whose nunber of elements is equal to the number of input
%  patterns. The kth element of this vector gives the class to which the
%  kth vector was assigned (i.e., classified).
%
% classifieroutput.ClassificationRate (computed in function fcnnclassifier)
%  A scalar that gives the percent of patterns classified correctly,
%  assuming that classifierinput.R was provided. If this is not the case
%  then classifieroutput.ClassificationRate = [].
%
%   Copyright 2002-2020 Gatesmark
%
%   This function, and other functions in the DIPUM Toolbox, are based
%   on the theoretical and practical foundations established in the
%   book Digital Image Processing Using MATLAB, 3rd ed., Gatesmark
%   Press, 2020.
%
%   Book website: http://www.imageprocessingplace.com
%   License: https://github.com/dipum/dipum-toolbox/blob/master/LICENSE.txt

doc fcnninfo


function CA184rule()
n=1000;
X=rand(1,n)>0.9;
X(n+1)=X(1);
Timestep=500;
data=zeros(Timestep,n);
Y=zeros(1,n);
for j=1:Timestep
    for i=1:n
        if i~=1
            if X(i-1)==1&&X(i)==0
                Y(i)=1;
           % elseif X(i)==1&&X(i+1)==0
              %  Y(i)=0;
            elseif X(i)==1&&X(i+1)==1
                Y(i)=1;
            else Y(i)=0;
            end
        else
            if X(n)==1&&X(i)==0
                Y(i)=1;
            %elseif X(i)==1&&X(i+1)==0
               % Y(i)=0;
            elseif X(i)==1&&X(i+1)==1
                Y(i)=1;
            else Y(i)=0;
            end
        end
    end
   X=Y;
   X(n+1)=Y(1);
   data(j,:)=Y;
end
imshow(data);
axis on;


function [reg_corner,rho,eta,reg_param] = l_curve(U,sm,b,method,L,V)
%L_CURVE Plot the L-curve and find its "corner".
%
% [reg_corner,rho,eta,reg_param] =
%                  l_curve(U,s,b,method)
%                  l_curve(U,sm,b,method)  ,  sm = [sigma,mu]
%                  l_curve(U,s,b,method,L,V)
%
% Plots the L-shaped curve of eta, the solution norm || x || or
% semi-norm || L x ||, as a function of rho, the residual norm
% || A x - b ||, for the following methods:
%    method = 'Tikh'  : Tikhonov regularization   (solid line )
%    method = 'tsvd'  : truncated SVD or GSVD     (o markers  )
%    method = 'dsvd'  : damped SVD or GSVD        (dotted line)
%    method = 'mtsvd' : modified TSVD             (x markers  )
% The corresponding reg. parameters are returned in reg_param.  If no
% method is specified then 'Tikh' is default.  For other methods use plot_lc.
%
% Note that 'Tikh', 'tsvd' and 'dsvd' require either U and s (standard-
% form regularization) or U and sm (general-form regularization), while
% 'mtvsd' requires U and s as well as L and V.
%
% If any output arguments are specified, then the corner of the L-curve
% is identified and the corresponding reg. parameter reg_corner is
% returned.  Use routine l_corner if an upper bound on eta is required.

% Reference: P. C. Hansen & D. P. O'Leary, "The use of the L-curve in
% the regularization of discrete ill-posed problems",  SIAM J. Sci.
% Comput. 14 (1993), pp. 1487-1503.

% Per Christian Hansen, IMM, July 26, 2007.

% Set defaults.
if (nargin==3), method='Tikh'; end  % Tikhonov reg. is default.
npoints = 200;  % Number of points on the L-curve for Tikh and dsvd.
smin_ratio = 16*eps;  % Smallest regularization parameter.

% Initialization.
[m,n] = size(U); [p,ps] = size(sm);
if (nargout > 0), locate = 1; else locate = 0; end
beta = U'*b; beta2 = norm(b)^2 - norm(beta)^2;
if (ps==1)
  s = sm; beta = beta(1:p);
else
  s = sm(p:-1:1,1)./sm(p:-1:1,2); beta = beta(p:-1:1);
end
xi = beta(1:p)./s;

if (strncmp(method,'Tikh',4) | strncmp(method,'tikh',4))

  eta = zeros(npoints,1); rho = eta; reg_param = eta; s2 = s.^2;
  reg_param(npoints) = max([s(p),s(1)*smin_ratio]);
  ratio = (s(1)/reg_param(npoints))^(1/(npoints-1));
  for i=npoints-1:-1:1, reg_param(i) = ratio*reg_param(i+1); end
  for i=1:npoints
    f = s2./(s2 + reg_param(i)^2);
    eta(i) = norm(f.*xi);
    rho(i) = norm((1-f).*beta(1:p));
  end
  if (m > n & beta2 > 0), rho = sqrt(rho.^2 + beta2); end
  marker = '-'; txt = 'Tikh.';

elseif (strncmp(method,'tsvd',4) | strncmp(method,'tgsv',4))

  eta = zeros(p,1); rho = eta;
  eta(1) = abs(xi(1))^2;
  for k=2:p, eta(k) = eta(k-1) + abs(xi(k))^2; end
  eta = sqrt(eta);
  if (m > n)
    if (beta2 > 0), rho(p) = beta2; else rho(p) = eps^2; end
  else
    rho(p) = eps^2;
  end
  for k=p-1:-1:1, rho(k) = rho(k+1) + abs(beta(k+1))^2; end
  rho = sqrt(rho);
  reg_param = (1:p)'; marker = 'o';
  if (ps==1)
    U = U(:,1:p); txt = 'TSVD';
  else
    U = U(:,1:p); txt = 'TGSVD';
  end

elseif (strncmp(method,'dsvd',4) | strncmp(method,'dgsv',4))

  eta = zeros(npoints,1); rho = eta; reg_param = eta;
  reg_param(npoints) = max([s(p),s(1)*smin_ratio]);
  ratio = (s(1)/reg_param(npoints))^(1/(npoints-1));
  for i=npoints-1:-1:1, reg_param(i) = ratio*reg_param(i+1); end
  for i=1:npoints
    f = s./(s + reg_param(i));
    eta(i) = norm(f.*xi);
    rho(i) = norm((1-f).*beta(1:p));
  end
  if (m > n & beta2 > 0), rho = sqrt(rho.^2 + beta2); end
  marker = ':';
  if (ps==1), txt = 'DSVD'; else txt = 'DGSVD'; end

elseif (strncmp(method,'mtsv',4))

  if (nargin~=6)
    error('The matrices L and V must also be specified')
  end
  [p,n] = size(L); rho = zeros(p,1); eta = rho;
  [Q,R] = qr(L*V(:,n:-1:n-p),0);
  for i=1:p
    k = n-p+i;
    Lxk = L*V(:,1:k)*xi(1:k);
    zk = R(1:n-k,1:n-k)\(Q(:,1:n-k)'*Lxk); zk = zk(n-k:-1:1);
    eta(i) = norm(Q(:,n-k+1:p)'*Lxk);
    if (i < p)
      rho(i) = norm(beta(k+1:n) + s(k+1:n).*zk);
    else
      rho(i) = eps;
    end
  end
  if (m > n & beta2 > 0), rho = sqrt(rho.^2 + beta2); end
  reg_param = (n-p+1:n)'; txt = 'MTSVD';
  U = U(:,reg_param); sm = sm(reg_param);
  marker = 'x'; ps = 2;  % General form regularization.

else
  error('Illegal method')
end

% Locate the "corner" of the L-curve, if required.
if (locate)
  [reg_corner,rho_c,eta_c] = l_corner(rho,eta,reg_param,U,sm,b,method);
end

% Make plot.
plot_lc(rho,eta,marker,ps,reg_param);
if locate
  ax = axis;
  HoldState = ishold; hold on;
  loglog([min(rho)/100,rho_c],[eta_c,eta_c],':r',...
         [rho_c,rho_c],[min(eta)/100,eta_c],':r')
  title(['L-curve, ',txt,' corner at ',num2str(reg_corner)]);
  axis(ax)
  if (~HoldState), hold off; end
end


% MatrixUser, a multi-dimensional matrix analysis software package
% https://sourceforge.net/projects/matrixuser/
%
% The MatrixUser is a matrix analysis software package developed under Matlab
% Graphical User Interface Developing Environment (GUIDE). It features
% functions that are designed and optimized for working with multi-dimensional
% matrix under Matlab. These functions typically includes functions for
% multi-dimensional matrix display, matrix (image stack) analysis and matrix
% processing.
%
% Author:
%   Fang Liu <leoliuf@gmail.com>
%   University of Wisconsin-Madison
%   Aug-30-2014

function MU_update_dim_control(handles, dimSize)

% refresh dimension tabgroup
if isfield(handles,'MDimension_tabgroup')
    tabs=get(handles.MDimension_tabgroup,'Children');
    for i=1:length(tabs)
        delete(get(tabs(i),'Children'));
    end
    delete(handles.MDimension_tabgroup);
    handles = rmfield(handles,'MDimension_tabgroup');
end

% initialize dimension tabgroup
if  numel(dimSize)> 2
    handles.MDimension_tabgroup=uitabgroup(handles.MDimension_uipanel);
    for i=3:numel(dimSize)

        handles.(['MDim' num2str(i) '_tab'])=uitab( handles.MDimension_tabgroup,'title',['Dim' num2str(i)] ,'Units','normalized');
        handles.(['Dim' num2str(i) '_edit'])=uicontrol(handles.(['MDim' num2str(i) '_tab']),'Style', 'edit','Units','normalized','BackgroundColor',[1 1 1],...
            'Position', [0.81 0 0.1 1],'TooltipString',['Matrix Dimension ' num2str(i)],'string',1,'Enable','off');
        handles.(['Dim' num2str(i) '_text'])=uicontrol(handles.(['MDim' num2str(i) '_tab']),'Style', 'text','Units','normalized','BackgroundColor',[1 1 1],...
            'Position', [0.91 0 0.08 1],'string',['/' num2str(dimSize(i))]);
        if dimSize(i) > 1
            set(handles.(['Dim' num2str(i) '_edit']),'Enable','on');
            handles.(['Dim' num2str(i) '_slider'])=uicontrol(handles.(['MDim' num2str(i) '_tab']),'Style', 'slider','Units','normalized','BackgroundColor',[1 1 1],...
                'Position', [0.01 0 0.8 1],'TooltipString',['Matrix Dimension ' num2str(i)],...
                'Value',1,'Min',1,'Max',dimSize(i),'SliderStep',[1/dimSize(i), 4/dimSize(i)]);
            set(handles.(['Dim' num2str(i) '_slider']),'Callback',{@MU_linkSliderEditDim,handles.(['Dim' num2str(i) '_slider']),handles.(['Dim' num2str(i) '_slider']),handles.(['Dim' num2str(i) '_edit']),i});
            set(handles.(['Dim' num2str(i) '_edit'])  ,'Callback',{@MU_linkSliderEditDim,handles.(['Dim' num2str(i) '_edit']),handles.(['Dim' num2str(i) '_slider']),handles.(['Dim' num2str(i) '_edit']),i});
        end
    end
end

% turn off uitab warning
warning('off');
guidata(handles.MU_matrix_display, handles);

end


function a = bagging(alg,hyper)

% ============================================================================
% BAGGING bagging object
% ============================================================================
% A=bagging(A,H) returns a bagging object initialized with algorithm A and
%                hyperparameters H.
%
% Bagging trains BAGS classifiers on resamplings with replacement of the data
% of size M.  The final classifier is the averaged classifier.
% For classifiers that output a real-valued output in pattern recognition this
% gives you the choice of performing the average before or after taking the
% sign.
%
% You can also use the bagging object to average the results of already
% trained classifiers, simply define BAGGING(A) where A is a GROUP of
% classifiers
%
% Hyperparameters (with defaults)
%   child=svm            -- the algorithm to bag
%   bags=10              -- the number of times to bag
%   m=500                -- the number of points to sample for each bag
%                           (can also be a fraction of the training data)
%
% Example:
%    a1=svm; a1.C=10;
%    a=bagging(a1); a.bags=10; a.m=20;
%    [r a]=train(a,toy2d);
%    loss(test(a,toy2d))
%
% ============================================================================
% Reference : Bagging Predictors
% Author    : Leo Breiman
% Link      : http://citeseer.lcs.mit.edu/breiman96bagging.html
% ============================================================================

a.bags=10; a.m=500; a.child=svm;

p=algorithm('bagging');
a=class(a,'bagging',p);

if nargin>0
	a.child=alg;
end

if strcmp(a.child.algorithm.name,'group')
	%% already defined machines, can choose bags automatically
	a.bags=length(a.child.child);
end

if nargin==2
	eval_hyper;
end


function bin_seq = getBits(text)
matrix  = dec2bin(uint8(text),8);
bin_seq = reshape(matrix', 1, 8*length(text));
end


function [vRate,vTime] = plot_LogOmori(mCatalog,mMain)
    % function [vRate,vBin] = plot_LogOmori(mCatalog,fTMain)
    % -------------------------------------------------------
    % Create daily rate plot of aftershock sequence in loglog space
    %
    % Outgoing:
    % vRate : Events per day
    % vTime : Time bin

    vAfdate = datenum(floor(mCatalog(:,3)),mCatalog(:,4),mCatalog(:,5),mCatalog(:,8),mCatalog(:,9),mCatalog(:,10));
    fTmain = datenum(floor(mMain(:,3)),mMain(:,4),mMain(:,5),mMain(:,8),mMain(:,9),mMain(:,10));
    vTime = vAfdate-fTmain;

    [vRate,vTime] = hist(vTime,0:1:ceil(max(vTime)));

    figure
    loglog(vTime,vRate,'s','Linestyle','none','Markersize',8,'Color',[0 0 0]);
    xlabel('Time [years]','FontSize',14,'Fontweight','bold');
    ylabel('Number of events [per day]','FontSize',14,'Fontweight','bold');


classdef CosineSim < dagnn.Filter

  methods
    function outputs = forward(self, inputs, params)
      outputs{1} = vl_nncosinesim(inputs{1}, inputs{2}) ;
    end

    function [derInputs, derParams] = backward(self, inputs, params, derOutputs)
      derInputs{1} = vl_nncosinesim(inputs{1}, inputs{2}, derOutputs{1}) ;
      derParams = {} ;
    end

    function outputSizes = getOutputSizes(obj, inputSizes)
      outputSizes{1} = ones(1,4) ;
      outputSizes{1}(4) = inputSizes{1}(4) ;
    end

    function obj = CosineSim(varargin)
      obj.load(varargin) ;
    end
  end
end


function model = Initialization_Cluster_Basis(Seqs, ClusterNum, ...
                        baseType, bandwidth, landmark)

N = length(Seqs);
D = zeros(N,1);
for i = 1:N
    D(i) = max(Seqs(i).Mark);
end
D = max(D);
model.K = ClusterNum;
model.D = D;

switch nargin
    case 2
        sigma = zeros(length(Seqs), 1);
        Tmax = zeros(length(Seqs), 1);

        for i = 1:length(Seqs)
            sigma(i) = ((4*std(Seqs(i).Time)^5)/(3*length(Seqs(i).Time)))^0.2;
            Tmax(i) = Seqs(i).Time(end) + eps;
        end
        Tmax = mean(Tmax);

        model.kernel = 'gauss';
        model.w = mean(sigma);
        model.landmark = model.w*(0:ceil(Tmax/model.w));

    case 3
        model.kernel = baseType;
        model.w = 1;
        model.landmark = 0;
    case 4
        model.kernel = baseType;
        model.w = bandwidth;
        model.landmark = 0;
    otherwise
        model.kernel = baseType;
        model.w = bandwidth;
        model.landmark = landmark;
end

model.alpha = 1;
M = length(model.landmark);
model.beta = ones(D, M, model.K, D)./(M*D^2);
% hyperparameter of Rayleigh prior of basic intensity (upper bound)
model.b = ones(D, model.K)./(D);

% initialize label and responsibility randomly
label = ceil(model.K*rand(1,N));
model.R = full(sparse(1:N,label,1,N,model.K,N));


function [ n_unique, a_unique ] = i4vec_sorted_unique ( n, a )

%*****************************************************************************80
%
%% I4VEC_SORTED_UNIQUE finds the unique elements in a sorted I4VEC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 April 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of elements in A.
%
%    Input, integer A(N), the sorted integer array.
%
%    Output, integer N_UNIQUE, the number of unique elements in A.
%
%    Output, integer A_UNIQUE[N_UNIQUE], the unique elements.
%
  n_unique = 0;
  a_unique = [];

  if ( n <= 0 )
    return;
  end

  n_unique = 1;
  a_unique = [ a_unique a(1) ];

  for i = 2 : n

    if ( a(i) ~= a_unique(n_unique) )
      n_unique = n_unique + 1;
      a_unique = [ a_unique a(i) ];
    end

  end

  return
end


%compute dycentralhead_mm

function [data,units]=compute_dycentralhead_mm(trx,n)

larvae=trx.exp2flies{n};
numlarvae=numel(larvae);
dycentralhead_mm=cell(1,numlarvae);
for i=1:numlarvae
    larva=larvae(i);
    dycentralhead_mm{1,i}=(trx(larva).ycentralhead_mm(2:end)-trx(larva).ycentralhead_mm(1:end-1))./trx(larva).dt;
end

units=parseunits('mm/s');
data=dycentralhead_mm;