function [solutions, goodRxns]=randomSampling(model,nSamples,replaceBoundsWithInf,supressErrors,showProgress,goodRxns,minFlux)
% randomSampling
%   Returns a number of random solutions
%
%   model                   a model structure
%   nSamples                the number of solutions to return
%                           (opt, default 1000)
%   replaceBoundsWithInf    replace the largest upper bounds with Inf and
%                           the smallest lower bounds with -Inf. This is
%                           needed in order to get solutions without loops
%                           if your model has for example 1000/-1000 as
%                           arbitary large bounds. If your model only has
%                           "biologically relevant" bounds, then set this
%                           to false (opt, default true)
%   supressErrors           the program will halt if it has problems
%                           finding non-zero solutions which are not
%                           involved in loops. This could be because the
%                           constraints on the model are too relaxed (such
%                           as unlimited glucose uptake) or too strict
%                           (such as too many and too narrow constraints)
%                           (opt, default false)
%   showProgress            if true, it will display in the command window
%                           how many iterations have been done (opt, default
%                           false)
%   goodRxns                double vector of indexes of those reactions
%                           that are not involved in loops and can be used
%                           as random objective functions, as generated by
%                           a previous run of randomSampling on the same
%                           model (opt, default empty)
%   minFlux                 determines if a second optimization should be
%                           performed for each random sample, to minimize
%                           the number of fluxes and thereby preventing
%                           loops. Typically, loops are averaged out when a
%                           large number of samples are taken, but this is
%                           not always the case (opt, default false)
%
%   solutions               matrix with the solutions
%   goodRxns                double vector of indexes of those reactions
%                           that are not involved in loops and can be used
%                           as random objective functions
%
%   The solutions are generated by maximizing (with random weights) for a
%   random set of three reactions. For reversible reactions it randomly
%   chooses between maximizing and minimizing.
%
%   Usage: solutions=randomSampling(model,nSamples,replaceBoundsWithInf,supressErrors,showProgress,goodRxns,minFlux)

if nargin<2
    nSamples=1000;
end
if nargin<3
    replaceBoundsWithInf=true;
end
if nargin<4
    supressErrors=false;
end
if nargin<5
    showProgress=false;
end
if nargin<7
    minFlux=false;
end

nRxns=2; %Number of reactions in the objective function in each iteration

%First check that the model is feasible given the constraints
[sol,~]=solveLP(model);
if isempty(sol.x)
    EM='The model has no feasible solution, likely due to incompatible constraints';
    dispEM(EM);
elseif sol.f==0 && showProgress
    warning('The model objective function cannot reach a non-zero value. This might be intended, so randomSampling will continue, but this could indicate problems with your model')
end

%Simplify the model to speed stuff up a little. Keep original mapping
originalRxns=model.rxns;
model=simplifyModel(model,false,false,true,true);

%Then change the bounds to +/- Inf. This is needed in order to not have
%loops in the solutions
if replaceBoundsWithInf==true
    model.ub(model.ub==max(model.ub))=Inf;
    if min(model.lb)<0 % Only negative lower bounds should be set to -Inf
        model.lb(model.lb==min(model.lb))=-Inf;
    end
end

[~,hsSol]=solveLP(model);
%Reactions which can be involved in loops should not be optimized for.
%Check which reactions reach an arbitary high upper bound
if nargin<6 || isempty(goodRxns)
    goodRxns=true(numel(model.rxns),1);
    if showProgress
        fprintf('Prepare goodRxns list of reactions not involved in loops...   0%% complete');
    end
    for i=1:numel(model.rxns)
        if showProgress && rem(i,100) == 0
            progress=num2str(floor(100*i/numel(model.rxns)));
            progress=pad(progress,3,'left');
            fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b%s%% complete',progress);
        end
        if goodRxns(i)==true
            testModel=setParam(model,'eq',model.rxns(i),1000);
            sol=solveLP(testModel,0,[],hsSol);
            if ~isempty(sol.f)
                goodRxns(abs(sol.x)>999)=false;
            else
                %If the reaction is reversible, also check in that direction
                if model.rev(i)
                    testModel=setParam(model,'eq',model.rxns(i),-1000);
                    sol=solveLP(testModel,0,[],hsSol);
                    if ~isempty(sol.f)
                        goodRxns(abs(sol.x)>999)=false;
                    end
                end
            end
        end
    end
    if showProgress
        fprintf('\b\b\b\b\b\b\b\b\b\b\b\b\b100%% complete\n');
    end
    goodRxns=find(goodRxns);
end

%Reserve space for a solution matrix
sols=zeros(numel(model.rxns),nSamples);

%Main loop
counter=1;
badSolutions=0;
if showProgress
    itrStr=num2str(nSamples);
    fprintf('Performing random sampling: ready with%s0/%s iterations',repmat(' ',1,length(itrStr)),itrStr);
end
while counter<=nSamples
    if showProgress && rem(counter,100) == 0
        fprintf([repmat('\b',1,length(itrStr)*2) '\b\b\b\b\b\b\b\b\b\b\b\b%s/%s iterations'],pad(num2str(counter),length(itrStr),'left'),itrStr);
    end
    rxns=randsample(numel(goodRxns),nRxns);
    model.c=zeros(numel(model.rxns),1);
    multipliers=randsample([-1 1],nRxns,true);
    multipliers(model.rev(goodRxns(rxns))==0)=1;
    model.c(goodRxns(rxns))=rand(nRxns,1).*multipliers;
    if true(minFlux)
        sol=solveLP(model,1,[],hsSol);
    else
        sol=solveLP(model,0,[],hsSol);
    end
    if any(sol.x) && abs(sol.f)>10^-8
        sols(:,counter)=sol.x;
        counter=counter+1;
        badSolutions=0;
    else
        badSolutions=badSolutions+1;
        %If it only finds bad solutions then throw an error.
        if badSolutions==100 && supressErrors==false
            error('The program is having problems finding non-zero solutions (ignoring reactions that might be involved in loops). Review the constraints on your model. Set supressErrors to true to ignore this error');
        end
    end
end
if showProgress
    fprintf('\n')
end

%Map to original model
[~, I]=ismember(model.rxns,originalRxns);
solutions=zeros(numel(originalRxns),nSamples);
solutions(I,:)=sols;
solutions=sparse(solutions);
end

%To use instead of the normal Matlab randsample function. This is in order
%to not depend on the Matlab statistical toolbox.
function I=randsample(n,k,replacement)
if nargin<3
    replacement=false;
end
%n can be a integer, which leads to I being sampled from 1:n, or it can be
%a population to sample from.
if numel(n)==1 && isnumeric(n)
    n=1:n;
end
%Loop and get random numbers until the list is unique. This is only a good
%option is the number of samples is small compared to the population. There
%are several checks that should be made here, for example regarding size
%and that the number of samples is <=population size if replacement==false.
%This is not the case in randomSampling, so such checks are ignored
while true
    J=randi(numel(n),[k,1]);
    if replacement==true || numel(J)==numel(unique(J))
        I=n(J);
        break;
    end
end
I=I(:);
end


% VL_DEMO_SIFT_BASIC  Demo: SIFT: basic functionality

pfx = fullfile(vl_root,'figures','demo') ;
randn('state',0) ;
rand('state',0) ;
figure(1) ; clf ;

% --------------------------------------------------------------------
%                                                        Load a figure
% --------------------------------------------------------------------
I = imread(fullfile(vl_root,'data','roofs1.jpg')) ;

image(I) ; colormap gray ;
axis equal ; axis off ; axis tight ;
vl_demo_print('sift_basic_0') ;

% --------------------------------------------------------------------
%                                       Convert the to required format
% --------------------------------------------------------------------
I = single(rgb2gray(I)) ;

clf ; imagesc(I)
axis equal ; axis off ; axis tight ;
vl_demo_print('sift_basic_1') ;

% --------------------------------------------------------------------
%                                                             Run SIFT
% --------------------------------------------------------------------
[f,d] = vl_sift(I) ;

hold on ;
perm = randperm(size(f,2)) ;
sel  = perm(1:50) ;
h1   = vl_plotframe(f(:,sel)) ; set(h1,'color','k','linewidth',3) ;
h2   = vl_plotframe(f(:,sel)) ; set(h2,'color','y','linewidth',2) ;

vl_demo_print('sift_basic_2') ;

delete([h1 h2]);

h3 = vl_plotsiftdescriptor(d(:,sel),f(:,sel)) ;
set(h3,'color','k','linewidth',2) ;
h4 = vl_plotsiftdescriptor(d(:,sel),f(:,sel)) ;
set(h4,'color','g','linewidth',1) ;
h1   = vl_plotframe(f(:,sel)) ; set(h1,'color','k','linewidth',3) ;
h2   = vl_plotframe(f(:,sel)) ; set(h2,'color','y','linewidth',2) ;

vl_demo_print('sift_basic_3') ;

% --------------------------------------------------------------------
%                                                      Custom keypoint
% --------------------------------------------------------------------
clf ; imagesc(I(1:200,1:200,:))
axis equal ; axis off ; axis tight ;
hold on;

fc = [100;100;10;-pi/8] ;
[f,d] = vl_sift(I,'frames',fc) ;

h3   = vl_plotsiftdescriptor(d,f) ;  set(h3,'color','k','linewidth',3) ;
h4   = vl_plotsiftdescriptor(d,f) ;  set(h4,'color','g','linewidth',2) ;
h1   = vl_plotframe(f) ; set(h1,'color','k','linewidth',4) ;
h2   = vl_plotframe(f) ; set(h2,'color','y','linewidth',2) ;

vl_demo_print('sift_basic_4') ;

% --------------------------------------------------------------------
%                                   Custom keypoints with orientations
% --------------------------------------------------------------------

fc = [100;100;10;0] ;
[f,d] = vl_sift(I,'frames',fc,'orientations') ;

delete([h1 h2 h3 h4]) ;

h3   = vl_plotsiftdescriptor(d,f) ;  set(h3,'color','k', 'linewidth',3) ;
h4   = vl_plotsiftdescriptor(d,f) ;  set(h4,'color','g', 'linewidth',2) ;
h1   = vl_plotframe(f) ; set(h1,'color','k','linewidth',4) ;
h2   = vl_plotframe(f) ; set(h2,'color','y','linewidth',2) ;

vl_demo_print('sift_basic_5') ;


% Profiler extension for Kernel Least-Mean-Square algorithm
%
% This file is part of the Kernel Adaptive Filtering Toolbox for Matlab.
% https://github.com/steven2358/kafbox/

classdef klms_profiler < klms

    properties (GetAccess = 'public', SetAccess = 'private')
        elapsed = 0; % elapsed time
        prev_dict_size = 0; % previous dictionary size for growth check
    end

    methods

        function kaf = klms_profiler(parameters) % constructor
            if nargin<1, parameters = struct(); end
            kaf = kaf@klms(parameters);
        end

        function flops = lastflops(kaf) % flops for last iteration
            m = size(kaf.dict,1);
            if kaf.prev_dict_size < m % growing
                m1 = m - 1;
                floptions = struct(...
                    'sum', m1 - 1, ...
                    'mult', m1 + 1, ...
                    sprintf('%s_kernel',kaf.kerneltype), [m1, 1, size(kaf.dict,2)]);

                flops = kflops(floptions);
            else
                flops = 0;
            end
        end

        %% flops breakdown

        % k = kernel(kaf.dict,x,kaf.kerneltype,kaf.kernelpar);
        % kernel: m1

        % y_est = k'*kaf.alpha;
        % sum: m1 - 1
        % mult: m1

        % err = y - y_est;
        % sum: 1

        % kaf.alpha = [kaf.alpha; kaf.mu*err];
        % mult: 1

        %%

        function train_profiled(kaf,x,y)
            kaf.prev_dict_size = size(kaf.dict,1);
            t1 = tic;
            kaf.train(x,y);
            t2 = toc(t1);
            kaf.elapsed = kaf.elapsed + t2;
        end

        function bytes = lastbytes(kaf) % bytes used in last iteration
            m = size(kaf.dict,1);
            bytes = 8*(m + m*size(kaf.dict,2)); % 8 bytes for double precision
            % alpha, dict
        end

    end
end


function g = gama_dct(I)

import bliinds2.*;

temp1=dct2(I);
temp2=temp1(:);
temp3=temp2(2:end);

%g=kurtosis(temp3);
g=gama_gen_gauss(temp3);


function syntheticExperiment(method)

if (nargin<1)
    method = 'SDRSAC';
end

method = 'SDRSAC';
%method = '4PCS';
% Synthetic experiment

config = readConfig();
%config = readConfig('redwood');

load(config.matPath);

%outRANSAC = pointCloudReg(D, M, config, 'RANSAC');
%outICP = pointCloudReg(M, D, config, 'ICP');

% if (strcmp(method,'SDRSAC'))
%
%     D = normalize(D,2, 'center');
%     M = normalize(M,2, 'center');
%     %
%     D = normalize(D,2, 'range');
%     M = normalize(M,2, 'range');
% end

%out = pointCloudReg(D, M, config, method);
%plotPointClouds(D, M, 'r.','b.');
log_file_path = './logs/logs.txt';
for nrun = 1:10
    for m = 3
        config.k = m;
        for nsample = 16
            config.pointPerSample = nsample;
            out = pointCloudReg(D, M, config, method);
            disp(out);
            if strcmp(method,'SDRSAC')
                log_results(log_file_path, out, config);
            end
        end
    end
end

disp(out);

end

%outSDR = pointCloudReg(M, D, config, '4PCS');
%outGlobGM = pointCloudReg(M, D, config, 'GlobGM');
%[out] = SDRReg(D, M, config);


function [sMap,D] = som_make(D, varargin)

%SOM_MAKE Create, initialize and train Self-Organizing Map.
%
% sMap = som_make(D, [[argID,] value, ...])
%
%  sMap = som_make(D);
%  sMap = som_make(D, 'munits', 20);
%  sMap = som_make(D, 'munits', 20, 'hexa', 'sheet');
%  sMap = som_make(D, 'msize', [4 6 7], 'lattice', 'rect');
%
%  Input and output arguments ([]'s are optional):
%   D        (matrix) training data, size dlen x dim
%            (struct) data struct
%   [argID,  (string) See below. The values which are unambiguous can
%    value]  (varies) be given without the preceeding argID.
%
%   sMap     (struct) map struct
%
% Here are the valid argument IDs and corresponding values. The values
% which are unambiguous (marked with '*') can be given without the
% preceeding argID.
%   'init'       *(string) initialization: 'randinit' or 'lininit' (default)
%   'algorithm'  *(string) training: 'seq' or 'batch' (default), 'imp' or 'sompak'
%   'munits'      (scalar) the preferred number of map units
%   'msize'       (vector) map grid size
%   'mapsize'    *(string) do you want a 'small', 'normal' or 'big' map
%                          Any explicit settings of munits or msize override this.
%   'lattice'    *(string) map lattice, 'hexa' or 'rect'
%   'shape'      *(string) map shape, 'sheet', 'cyl' or 'toroid'
%   'neigh'      *(string) neighborhood function, 'gaussian', 'cutgauss',
%                          'ep' or 'bubble'
%   'topol'      *(struct) topology struct
%   'som_topol','sTopol' = 'topol'
%   'mask'        (vector) BMU search mask, size dim x 1
%   'name'        (string) map name
%   'comp_names'  (string array / cellstr) component names, size dim x 1
%   'tracking'    (scalar) how much to report, default = 1
%   'training'    (string) 'short', 'default', 'long'
%                 (vector) size 1 x 2, first length of rough training in epochs,
%                          and then length of finetuning in epochs
%
%
% For more help, try 'type som_make' or check out online documentation.
% See also SOM_MAP_STRUCT, SOM_TOPOL_STRUCT, SOM_TRAIN_STRUCT,
%          SOM_RANDINIT, SOM_LININIT, SOM_SEQTRAIN, SOM_BATCHTRAIN.

%%%%%%%%%%%%% DETAILED DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% som_make
%
% PURPOSE
%
% Creates, initializes and trains a SOM using default parameters.
%
% SYNTAX
%
%  sMap = som_make(D);
%  sMap = som_make(...,'argID',value,...);
%  sMap = som_make(...,value,...);
%
% DESCRIPTION
%
% Creates, initializes and trains a SOM with default parameters. Uses functions
% SOM_TOPOL_STRUCT, SOM_TRAIN_STRUCT, SOM_DATA_STRUCT and SOM_MAP_STRUCT to come
% up with the default values.
%
% First, the number of map units is determined. Unless they are
% explicitly defined, function SOM_TOPOL_STRUCT is used to determine this.
% It uses a heuristic formula of 'munits = 5*dlen^0.54321'. The 'mapsize'
% argument influences the final number of map units: a 'big' map has
% x4 the default number of map units and a 'small' map has x0.25 the
% default number of map units.
%
% After the number of map units has been determined, the map size is
% determined. Basically, the two biggest eigenvalues of the training
% data are calculated and the ratio between sidelengths of the map grid
% is set to this ratio. The actual sidelengths are then set so that
% their product is as close to the desired number of map units as
% possible.
%
% Then the SOM is initialized. First, linear initialization along two
% greatest eigenvectors is tried, but if this can't be done (the
% eigenvectors cannot be calculated), random initialization is used
% instead.  After initialization, the SOM is trained in two phases:
% first rough training and then fine-tuning. If the 'tracking'
% argument is greater than zero, the average quantization error and
% topographic error of the final map are calculated. If there are missing
% values (NaNs) in the data, it may be wise to use the Imputation SOM
% algorithm ('imp' agrument).
%
%
% REQUIRED INPUT ARGUMENTS
%
%  D           The data to use in the training.
%     (struct) A data struct. If a struct is given, '.comp_names' field as
%              well as '.comp_norm' field is copied to the map struct.
%     (matrix) A data matrix, size dlen x dim. The data matrix may
%              contain unknown values, indicated by NaNs.
%
% OPTIONAL INPUT ARGUMENTS
%
%  argID (string) Argument identifier string (see below).
%  value (varies) Value for the argument (see below).
%
% Here are the valid argument IDs and corresponding values. The values
% which are unambiguous (marked with '*') can be given without the
% preceeding argID.
%   'init'       *(string) initialization: 'randinit' or 'lininit' (default)
%   'munits'      (scalar) the preferred number of map units
%   'msize'       (vector) map grid size
%   'mapsize'    *(string) do you want a 'small', 'normal' or 'big' map
%                          Any explicit settings of munits or msize override this.
%   'lattice'    *(string) map lattice, 'hexa' or 'rect'
%   'shape'      *(string) map shape, 'sheet', 'cyl' or 'toroid'
%   'neigh'      *(string) neighborhood function, 'gaussian', 'cutgauss',
%                          'ep' or 'bubble'
%   'topol'      *(struct) topology struct
%   'som_topol','sTopol' = 'topol'
%   'mask'        (vector) BMU search mask, size dim x 1
%   'name'        (string) map name
%   'comp_names'  (string array / cellstr) component names, size dim x 1
%   'tracking'    (scalar) how much to report, default = 1
%   'training'    (string) 'short', 'default' or 'long'
%                 (vector) size 1 x 2, first length of rough training in epochs,
%                          and then length of finetuning in epochs
%
% OUTPUT ARGUMENTS
%
%  sMap (struct) the trained map struct
%
% EXAMPLES
%
%  To simply train a map with default parameters:
%
%   sMap = som_make(D);
%
%  With the optional arguments, the initialization and training can be
%  influenced. To change map size, use 'msize', 'munits' or 'mapsize'
%  arguments:
%
%   sMap = som_make(D,'mapsize','big'); or sMap=som_make(D,'big');
%   sMap = som_make(D,'munits', 100);
%   sMap = som_make(D,'msize', [20 10]);
%
%  Argument 'algorithm' can be used to switch between 'seq' and 'batch'
%  algorithms. 'batch' is the default, so to use 'seq' algorithm:
%
%   sMap = som_make(D,'algorithm','seq'); or sMap = som_make(D,'seq');
%
%  The 'tracking' argument can be used to control the amout of reporting
%  during training. The argument is used in this function, and it is
%  passed to the training functions. To make the function work silently
%  set it to 0.
%
%   sMap = som_make(D,'tracking',0);
%
% SEE ALSO
%
%  som_map_struct   Create a map struct.
%  som_topol_struct Default values for SOM topology.
%  som_train_struct Default values for SOM training parameters.
%  som_randinint    Random initialization algorithm.
%  som_lininit      Linear initialization algorithm.
%  som_seqtrain     Sequential training algorithm.
%  som_batchtrain   Batch training algorithm.
%  som_impbatch     The imputation SOM batch training algorithm.

% Copyright (c) 1999-2012 by the SOM toolbox programming team.
% http://www.cis.hut.fi/projects/somtoolbox/

% Version 2.0beta juuso 111199
% Version 2.1beta tommi 121212

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% check arguments

% D
if isstruct(D)
  data_name = D.name;
  comp_names = D.comp_names;
  comp_norm = D.comp_norm;
  D = D.data;
else
  data_name = inputname(1);
  sDummy = som_data_struct(D(1,:));
  comp_names = sDummy.comp_names;
  comp_norm = sDummy.comp_norm;
end
[dlen dim] = size(D);

% defaults
mapsize = '';
sM = som_map_struct(dim);
sTopol = sM.topol;
munits = prod(sTopol.msize); % should be zero
mask = sM.mask;
name = sM.name;
neigh = sM.neigh;
tracking = 1;
algorithm = 'batch';
initalg = 'lininit';
training = 'default';

% varargin
i=1;
while i<=length(varargin),
  argok = 1;
  if ischar(varargin{i}),
    switch varargin{i},
      % argument IDs
     case 'mask',       i=i+1; mask = varargin{i};
     case 'munits',     i=i+1; munits = varargin{i};
     case 'msize',      i=i+1; sTopol.msize = varargin{i};
                        munits = prod(sTopol.msize);
     case 'mapsize',    i=i+1; mapsize = varargin{i};
     case 'name',       i=i+1; name = varargin{i};
     case 'comp_names', i=i+1; comp_names = varargin{i};
     case 'lattice',    i=i+1; sTopol.lattice = varargin{i};
     case 'shape',      i=i+1; sTopol.shape = varargin{i};
     case {'topol','som_topol','sTopol'},
                        i=i+1; sTopol = varargin{i}; munits = prod(sTopol.msize);
     case 'neigh',      i=i+1; neigh = varargin{i};
     case 'tracking',   i=i+1; tracking = varargin{i};
     case 'init',       i=i+1; initalg = varargin{i};
     case 'training',   i=i+1; training = varargin{i};
     case 'mweight',    i=i+1; sTopol.mweight = varargin{i};
      % unambiguous values
     case {'hexa','rect'}, sTopol.lattice = varargin{i};
     case {'sheet','cyl','toroid'}, sTopol.shape = varargin{i};
     case {'gaussian','cutgauss','ep','bubble'}, neigh = varargin{i};
     case {'seq','batch','sompak','imp'}, algorithm = varargin{i};
     case {'small','normal','big'}, mapsize = varargin{i};
     case {'randinit','lininit'}, initalg = varargin{i};
     case {'short','default','long'}, training = varargin{i};
      otherwise, argok=0;
    end
  elseif isstruct(varargin{i}) && isfield(varargin{i},'type'),
    switch varargin{i}(1).type,
     case 'som_topol', sTopol = varargin{i};
       otherwise, argok=0;
    end
  else
    argok = 0;
  end
  if ~argok,
    disp(['(som_make) Ignoring invalid argument #' num2str(i+1)]);
  end
  i = i+1;
end

if any(isnan(D(:))) && ~strcmp('imp',algorithm)
  disp('Missing values in data. Consider using the Imputation SOM (see help)')
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% make the map struct

%% map size
if isempty(sTopol.msize) || ~prod(sTopol.msize),
  if tracking>0, fprintf(1,'Determining map size...\n'); end
  if ~munits,
    sTemp = som_topol_struct('dlen',dlen);
    munits = prod(sTemp.msize);
    switch mapsize,
     case 'small', munits = max(9,ceil(munits/4));
     case 'big',   munits = munits*4;
     otherwise % nil
    end
  end
  sTemp = som_topol_struct('data',D,'munits',munits);
  sTopol.msize = sTemp.msize;
  if tracking>0,
    fprintf(1,' map size [%d, %d]\n',sTopol.msize(1), sTopol.msize(2));
  end
end

% map struct
sMap = som_map_struct(dim,sTopol,neigh,'mask',mask,'name',name, ...
                      'comp_names', comp_names, 'comp_norm', comp_norm);

% function
if strcmp(algorithm,'sompak'),
  algorithm = 'seq';
  func = 'sompak';
else
  func = algorithm;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% initialization

if tracking>0, fprintf(1,'Initialization...\n'); end

switch initalg,
 case 'randinit', sMap = som_randinit(D, sMap);
 case 'lininit', sMap = som_lininit(D, sMap);
end
sMap.trainhist(1) = som_set(sMap.trainhist(1),'data_name',data_name);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% training
if tracking>0, fprintf(1,'Training using %s algorithm...\n',algorithm); end

% rough train
if tracking>0, fprintf(1,'Rough training phase...\n'); end
sTrain = som_train_struct(sMap,'dlen',dlen,'algorithm',algorithm,'phase','rough');
sTrain = som_set(sTrain,'data_name',data_name);
if isnumeric(training), sTrain.trainlen = training(1);
else
  switch training,
   case 'short', sTrain.trainlen = max(1,sTrain.trainlen/4);
   case 'long',  sTrain.trainlen = sTrain.trainlen*4;
  end
end
switch func,
 case 'seq',    sMap = som_seqtrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
 case 'sompak', sMap = som_sompaktrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
 case 'batch',  sMap = som_batchtrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
 case 'imp',    sMap = som_impbatch(sMap,D,sTrain,'tracking',tracking,'mask',mask);
end

% finetune
if tracking>0, fprintf(1,'Finetuning phase...\n'); end
sTrain = som_train_struct(sMap,'dlen',dlen,'phase','finetune');
sTrain = som_set(sTrain,'data_name',data_name,'algorithm',algorithm);
if isnumeric(training), sTrain.trainlen = training(2);
else
  switch training,
   case 'short', sTrain.trainlen = max(1,sTrain.trainlen/4);
   case 'long',  sTrain.trainlen = sTrain.trainlen*4;
  end
end
switch func,
 case 'seq',    sMap = som_seqtrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
 case 'sompak', sMap = som_sompaktrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
 case 'batch',  sMap = som_batchtrain(sMap,D,sTrain,'tracking',tracking,'mask',mask);
 case 'imp',    sMap = som_impbatch(sMap,D,sTrain,'tracking',tracking,'mask',mask);
end

% quality
if tracking>0,
  [mqe,tge,cbe] = som_quality(sMap,D);
  fprintf('Final quantization error: %5.3f\n',mqe)
  fprintf('Final topographic error:  %5.3f\n',tge)
  fprintf('Final combined error:  %5.3f\n',cbe)
end

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


% WAVELET_LAYER_2D Compute the wavelet transform of a scattering layer
%
% Usage
%    [U_phi, U_psi] = WAVELET_LAYER_2D(U, filters, options)
%
% Input
%    U (struct): input scattering layer
%    filters (struct): filter bank
%    options (struct): same as wavelet_2d
%
% Output
%    A (struct): Averaged wavelet coefficients
%    V (struct): Wavelet coefficients of the next layer
%
% Description
%    This function has a pivotal role between WAVELET_2D (which computes a
%    single wavelet transform), and WAVELET_FACTORY_2D (which creates the
%    whole cascade). Given inputs modulus wavelet coefficients
%    corresponding to a layer, WAVELET_LAYER_2D computes the wavelet
%    transform coefficients of the next layer using WAVELET_2D.
%
% See also
%   WAVELET_2D, WAVELET_FACTORY_2D, WAVELET_LAYER_1D

function [U_phi, U_psi] = wavelet_layer_2d(U, filters, options)

    calculate_psi = (nargout>=2); % do not compute any convolution
    % with psi if the user does get U_psi

    if ~isfield(U.meta,'theta')
        U.meta.theta = zeros(0,size(U.meta.j,2));
    end

    if ~isfield(U.meta, 'resolution'),
        U.meta.resolution = 0;
    end

    p2 = 1;
    for p = 1:numel(U.signal)
        x = U.signal{p};
        if (numel(U.meta.j)>0)
            j = U.meta.j(end,p);
        else
            j = -1E20;
        end

        % compute mask for progressive paths
        options.psi_mask = calculate_psi & ...
            (filters.psi.meta.j >= j + filters.meta.Q);

        % set resolution of signal
        options.x_resolution = U.meta.resolution(p);

        % compute wavelet transform
        [x_phi, x_psi, meta_phi, meta_psi] = wavelet_2d(x, filters, options);

        % copy signal and meta for phi
        U_phi.signal{p} = x_phi;
        U_phi.meta.j(:,p) = [U.meta.j(:,p); filters.phi.meta.J];
        U_phi.meta.theta(:,p) = U.meta.theta(:,p);
        U_phi.meta.resolution(1,p) = meta_phi.resolution;

        % copy signal and meta for psi
        for p_psi = find(options.psi_mask)
            U_psi.signal{p2} = x_psi{p_psi};
            U_psi.meta.j(:,p2) = [U.meta.j(:,p);...
                filters.psi.meta.j(p_psi)];
            U_psi.meta.theta(:,p2) = [U.meta.theta(:,p);...
                filters.psi.meta.theta(p_psi)];
            U_psi.meta.resolution(1,p2) = meta_psi.resolution(p_psi);
            p2 = p2 +1;
        end

    end

end


filename='Cantilever_hexahedra_coarse';
 ptype = 'MACRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'full';
cost = {'compliance';'perimeter'};
weights = [1, 0.1];
constraint = {'volumeConstraint'};
optimizer = 'MMA';
incrementFactor = 1;
designVariable = 'Density';
filterType = 'P1';

nsteps = 5;
Vfrac_final = 0.1;
Perimeter_target = 1;
optimality_final = 1e-3;
constr_final =1e-3;

Vfrac_initial = 1;
optimality_initial = 1e-2;
constr_initial = 1e-3;
TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;


function out=convert(in,varargin)
%OPTS Set gradient limits of the MR system.
%   out=convert(in,from,to) Convert the numerical data in, given in
%   specificed units 'from' to units specified in 'to'.
%
%   Valid unit strings are:
%    'Hz/m' 'mT/m' 'rad/ms/mm' 'Hz/m/s' 'mT/m/ms' 'T/m/s' 'rad/ms/mm/ms'

persistent parser
validGradUnits={'Hz/m','mT/m','rad/ms/mm'};
validSlewUnits={'Hz/m/s','mT/m/ms','T/m/s','rad/ms/mm/ms'};
validUnits=cat(2,validGradUnits,validSlewUnits);
if isempty(parser)
    parser = inputParser;
    parser.FunctionName = 'convert';
    parser.addRequired('in',@isnumeric);
    parser.addRequired('fromUnit',...
        @(x) any(validatestring(x,validUnits)));
    parser.addOptional('toUnit',[],...
        @(x) any(validatestring(x,validUnits)));
    parser.addParamValue('gamma',42.576e6,@isnumeric); % Hz/T
end
parse(parser,in,varargin{:});
opt = parser.Results;

% Set default output unit if not given
if isempty(opt.toUnit)
    if ismember(opt.fromUnit,validGradUnits)
        opt.toUnit = validGradUnits{1};
    elseif ismember(opt.fromUnit,validSlewUnits)
        opt.toUnit = validSlewUnits{1};
    end
end

% Convert to standard units
switch opt.fromUnit
    % Grad units
    case 'Hz/m'
        standard = in;
    case 'mT/m'
        standard = in*1e-3*opt.gamma;
    case 'rad/ms/mm'
        standard = in*1e6/(2*pi);
    % Slew units
    case 'Hz/m/s'
        standard = in;
    case {'mT/m/ms','T/m/s'}
        standard = in*opt.gamma;
    case 'rad/ms/mm/ms'
        standard = in*1e9/(2*pi);
end

% Convert from standard units
switch opt.toUnit
    % Grad units
    case 'Hz/m'
        out = standard;
    case 'mT/m'
        out = 1e3*standard/opt.gamma;
    case 'rad/ms/mm'
        out = standard*2*pi*1e-6;
    % Slew units
    case 'Hz/m/s'
        out = standard;
    case {'mT/m/ms','T/m/s'}
        out = standard/opt.gamma;
    case 'rad/ms/mm/ms'
        out = standard*2*pi*1e-9;
end


function [irf_estimates,D,gamma,D_estimates,gamma_estimates,strshocks_estimates,favar]...
    =olsirft5(betahat,IRFperiods,Y,X,n,m,p,k,endo,pref,IRFband,names,enddate,startdate,T,data_endo,data_exo,const,strctident,IRFt,IRF,favar)

% computes IRF values (point estimates and confidence bands) for the OLS VAR model
% inputs:  - vector 'betahat': OLS VAR coefficients in vectorised form (defined in 1.1.15)
%          - matrix 'sigmahat': OLS VAR variance-covariance matrix of residuals (defined in 1.1.10)
%          - integer 'IRFperiods': number of periods for IRFs
%          - integer 'IRFt': determines which type of structural decomposition to apply (none, Choleski, triangular factorization)
%          - matrix 'X': matrix of regressors for the VAR model (defined in 1.1.8)
%          - integer 'n': number of endogenous variables in the BVAR model (defined p 7 of technical guide)
%          - integer 'm': number of exogenous variables in the BVAR model (defined p 7 of technical guide)
%          - integer 'p': number of lags included in the model (defined p 7 of technical guide)
%          - integer 'k': number of coefficients to estimate for each equation in the BVAR model (defined p 7 of technical guide)
%          - integer 'q': total number of coefficients to estimate for the BVAR model (defined p 7 of technical guide)
%          - scalar 'IRFband': confidence level for IRFs
% outputs: - cell 'irf_estimates': lower bound, point estimates, and upper bound for the IRFs
%          - matrix 'D': structural matrix for the OLS model (defined in 2.3.3)
%          - matrix 'gamma': structural disturbance variance-covariance matrix (defined p 48 of technical guide)
%          - vector 'D_estimates': point estimate (median) of the structural matrix D, in vectorised form
%          - vector 'gamma_estimates': point estimate (median) of the structural disturbance variance-covariance matrix gamma, in vectorised form

It=1001;
Bu=0;
Acc=It-Bu;

%% IV routine
[~,~,~,~,~,irf_storage,storage2]=...
    bear.irfIVols(betahat,n,m,p,k,T,names,startdate,enddate,X,Y,endo,data_endo,data_exo,const,pref,strctident,IRFt,IRFperiods,It,Bu);

%% reorganise storage
% loop over iterations
for ii=1:Acc
    % loop over IRF periods
    for jj=1:IRFperiods
        % loop over variables
        for kk=1:n
            % loop over shocks
            for ll=1:n
                irf_record{kk,ll}(ii,jj)=irf_storage{ii,1}(kk,ll,jj);
            end
        end
    end
    D_record(:,ii)=storage2{ii,1}(:);
end

for ii=1:n^2
    D_estimates(ii,1)=quantile(D_record(ii,:),0.5);
end
D=reshape(D_estimates,n,n);
D_estimates=D(:);
gamma=eye(n); %equivalent to the gamma_record output of irfres
gamma_estimates=gamma(:);

% create then the cell storing the point estimates and confidence bands
irf_estimates=cell(n,n);

if IRF==1 | favar.IRFplot==1
    % rearrange
    for ii=1:n
        % loop over variables
        for jj=1:n
            % loop over IRF periods
            for kk=1:IRFperiods
                % median
                irf_estimates{jj,ii}(2,kk)=quantile(irf_record{jj,ii}(:,kk),0.5);
                % lower bound
                irf_estimates{jj,ii}(1,kk)=quantile(irf_record{jj,ii}(:,kk),(1-IRFband)/2);
                % upper bound
                irf_estimates{jj,ii}(3,kk)=quantile(irf_record{jj,ii}(:,kk),IRFband+(1-IRFband)/2);
            end
        end
    end
end

% check if the variables have been transformed
if favar.FAVAR==1
    if favar.transformation==1 || favar.plot_transform==1
        % re-transform irf_estimates
        favar.IRF.irf_estimates_nottransformed=irf_estimates; % before, save untransformed IRFs
        % re-transform
        [irf_estimates]=bear.favar_retransX_irf_estimates(irf_estimates,favar.transformationindex_endo,favar.levels);
    end
end

% finally, estimate structural shocks
% Compute first the model residuals
Bhat=reshape(betahat,k,n);
EPS=Y-X*Bhat;
% Then use (XXX) to recover the structural shocks
ETA=D\EPS';
% output
strshocks_estimates=ETA;


function [neg, zer, nd, pos] = convertGene2PathwayInteractions(E, epSys, uSys)
% This function was written to find out the type of epistatic interactions
% that either exist between two different or within same subsystem
%
% USAGE:
%
%     [neg,zer,nd,pos] = convertGene2PathwayInteractions(E,epSys,uSys)
%
% INPUT:
%    E:     A square epistatic interaction matrix (or genes or reactions)
%    epSys: Subsystems belonging to the gene at that index (a second
%           order cell array) Each cell array may contain one or more
%           subsystems.
%           e.g. for first gene or reaction in E:
%           epCmpt{1,1} = {'Glycolysis';'TCA cycle'}
%    uSys:  Unique Subsystems in the epCmpt (use this arguments if
%           interested in interactions between selected subsystems in the epSys)
%
% OUTPUTS:
%    neg:            matrix of number of aggravating (negative) pathway-pair interactions
%    zer:            matrix of number of no-epistatic interactions pathway-pair interactions
%    nd:             matrix of number of non-decisive interactions pathway-pair interactions
%    pos:            matrix of number of buffering (positive) interactions pathway-pair interactions
%
% NOTE:
%    See figures in following publication:
%    Joshi CJ and Prasad A, 2014, "Epistatic interactions among metabolic genes
%    depend upon environmental conditions", Mol. BioSyst., 10, 2578-2589.
%
% .. Authors:
%     - Chintan Joshi 10/26/2018

if (nargin < 3)
    uSys = unique(convertMyCell2List(epSys, 2));
end

negE = (E < -0.25);
zerE = (E >= -0.25) & (E < 0.25);
ndE = (E >= 0.25) & (E < 0.85);
posE = (E >= 0.85);
g1 = 0;
g2 = 0;
pos = zeros(length(uSys), length(uSys)); neg = pos; nd = pos; zer = pos;
for i = 1:length(uSys)
    index1 = cellfun(@strcmp, epSys, repmat(uSys(i), length(epSys), 1));
    for j = 1:length(uSys)
        index2 = cellfun(@strcmp, epSys, repmat(uSys(j), length(epSys), 1));
        pos(i, j) = sum(sum(posE(index1, index2)));
        neg(i, j) = sum(sum(negE(index1, index2)));
        nd(i, j) = sum(sum(ndE(index1, index2)));
        zer(i, j) = sum(sum(zerE(index1, index2)));
    end
end

function B = convertMyCell2List(A, dimSense)

% This function linearizes a cell array if some of the cells in the array are another embbedded cell arrays.
% (hence, two degrees of cell array)

% This will only work for atmost two degrees of cell array.

% A=cell array to be linearized.
% dimSense=determines if inner cells are row (dimSense=1) vectors or columns (dimSense=2, default)

cnt = 0;
if nargin < 2
    dimSense = 2;
end
for i = 1:length(A)
    for j = 1:length(A{i, 1})
        cnt = cnt + 1;
        if dimSense == 1
            B{cnt, 1} = A{i, 1}{1, j};
        elseif dimSense == 2
            B{cnt, 1} = A{i, 1}{j, 1};
        end
    end
end


function hoxlist = hoxsetup(numhox,hoxrange,sizeGenerations)
%
% Tor Wager, 12/29/01

if numhox ~= size(hoxrange,1), error('num hox genes does not equal number of rows of hoxrange.'),end

hoxlist = rand(numhox, sizeGenerations);

for i = 1:size(hoxlist,1)
    hoxlist(i,:) = hoxlist(i,:) * (hoxrange(i,2) - hoxrange(i,1)) + hoxrange(i,1);
end

return


function cascade = separable_wavelet_factory_2d(N, filter_options, scat_options, M)
	filters{1} = filter_bank(N(1),filter_options{1});
	filters{2} = filter_bank(N(2),filter_options{2});

	for m = 0:M
		filt1_ind = min(numel(filters{1}), m+1);
		filt2_ind = min(numel(filters{2}), m+1);
		cascade{m+1} = @(X)(separable_wavelet_layer_2d(X, ...
			{filters{1}{filt1_ind} filters{2}{filt2_ind}}, scat_options));
	end
end


function chronux
% This library performs time-frequency analysis (mostly using the
% multi-taper spectral estimation method) of univariate and multivariate
% data, both for continuous processes such as LFP/EEG and for point
% processes such as spike times. Point process can either be stored as
% times or as a binned process of counts. The routines in this library
% are named differently for the three cases. For calculations
% that can be performed for each of the three data types, we use suffixes
% c, pb, or pt to refer to continuous, point process binned counts, or
% point process times. For example, the spectrum calculation is performed
% mtspectrumc for continuous processes, mtspectrumpb for a binned point
% process, and mtspectrumpt for a point process consisting of times. There
% are also routines for calculating hybrid quantities involving one continuous
% and one point process. These are suffixed in a similar manner. For
% example, coherencycpb calculates the coherency between a binned point process
% and a continuous process.
%
% Certain variables are used repeatedly in this library.
%
% DATA
% data in most cases can be univariate or multivariate, and either point process,
% or continuous.
%
%      Continuous data: Continuous data is assumed to be a matrix with
%                       dimensions samples x channels/trials.
%
%      Point Process: A single time series of spike times can be in the form of
%                     a column vector.
%                     Multichannel/trial spike time data is not amenable to this
%                     storage format, since there are generally different
%                     number of spikes in each channel/trial. Instead,
%                     multichannel/trial spike data is stored in a structure
%                     array. A structure is a matlab data object with various
%                     fields. These fields contain the elements
%                       e.g. The command data=struct('times',[]); creates an empty
%                            structure with field 'times'. Similarly, the command
%                            data=struct('times',[1 2 3]); creates the structure with
%                            the field 'times' containing integers 1, 2, and 3.
%
%                     We can also have a structure array (or an array of structures)
%                     defined for example, by
%                     data(1)=struct('times',rand(1,100)); and
%                     data(2)=struct('times',rand(1,200));
%                     This is a 2 dimensional structure array where the
%                     first field is a 100 dimensional random vector, and
%                     the second field is a 200 dimensional random vector.
%                     This format allows storage of multichannel point
%                     process times in a single variable data.
%
%                     The above holds for point processes stored as times.
%                     If instead, the point processes are binned, then one
%                     can use a matrix to represent them
%
%
%      Summary: data - array of continuous data with dimensions time x channels
%                      structural array of spike times with dimensions
%                               equal to the number of channels
%                      1d array of spike times as a column vector
%                      array of binned spike counts with dimensions time x channels
%
% PARAMETERS:
% These are various parameters used in the spectral calculations. Since
% these parameters are used by most routines in Chronux, they are stored in
% a single structure params. The fields of params are
%
% tapers : precalculated tapers from dpss or in the one of the following
%          forms:
%          (1) A numeric vector [TW K] where TW is the
%              time-bandwidth product and K is the number of
%              tapers to be used (less than or equal to
%              2TW-1).
%          (2) A numeric vector [W T p] where W is the
%              bandwidth, T is the duration of the data and p
%              is an integer such that 2TW-p tapers are used. In
%              this form there is no default i.e. to specify
%              the bandwidth, you have to specify T and p as
%              well. Note that the units of W and T have to be
%              consistent: if W is in Hz, T must be in seconds
%              and vice versa. Note that these units must also
%              be consistent with the units of params.Fs: W can
%              be in Hz if and only if params.Fs is in Hz.
%              The default is to use form 1 with TW=3 and K=5
%
%
% pad:   (padding factor for the FFT) - optional (can take values -1,0,1,2...).
%         -1 corresponds to no padding, 0 corresponds to padding
%         to the next highest power of 2 etc.
%			  e.g. For N = 500, if PAD = -1, we do not pad; if PAD = 0, we pad the FFT
%			       to 512 points, if pad=1, we pad to 1024 points etc.
%			       Defaults to 0.
%
% Fs:sampling frequency.optional (default 1)
%
%
% fpass: frequencies in an fft calculation can range from 0 to Fs/2 where
%        Fs is the sampling frequency. Sometimes it may be useful to
%        compute fourier transforms (and resulting quantities like the
%        spectrum over a smaller range of frequencies). This is specified
%        by fpass, which can be in the form [fmin fmax] where fmin >=0 and
%        fmax<=Fs/2. optional (default [0 Fs/2])
%
% err=[errtype p] calculates theoretical error bars (confidence levels)
%                 when errtype=1 and jackknife error bars when errchk=2. In each case, the
%                 error is calculated at a p value specified by p. -
%                 optional (default 0)
%
% trialave: trialave controls whether or not to average over channels/trials for
%           multichannel/trial analyses. trialave=0 (default) implies no trial
%           averaging, trialave=1 implies that the quantity of interest is averaged
%           over channels/trials. optional (default 0)
%
% Other parameters are discussed in individual routines as and when they
% are used.


function OptimizationModel = buildMTAproblemFromModel(model,rxnFBS,Vref,varargin)
% Returns the COBRA Optimization model needed to perform the MTA
%
% USAGE:
%
%       OptimizationModel = buildMTAproblemFromModel(model,rxnFBS,Vref,alpha,epsilon)
%
% INPUT:
%    model:                 Metabolic model (COBRA format)
%    rxnFBS:                Forward, Backward and Unchanged (+1;0;-1) values
%                           corresponding to each reaction.
%    Vref:                  Reference flux of the source state.
%    alpha:                 parameter of the quadratic problem (default = 0.66)
%    epsilon                minimun disturbance for each reaction, (default = 0)
%
% OUTPUTS:
%    OptimizationModel:     COBRA model struct that includes the
%                           stoichiometric contrains, the thermodinamic
%                           constrains and the binary variables.
%
% .. Authors:
%       - Luis V. Valcarcel, 03/06/2015, University of Navarra, CIMA & TECNUN School of Engineering.
%       - Luis V. Valcarcel, 26/10/2018, University of Navarra, CIMA & TECNUN School of Engineering.

p = inputParser; % check the inputs
% check requiered arguments
addRequired(p, 'model');
addRequired(p, 'rxnFBS', @isnumeric);
addRequired(p, 'Vref', @isnumeric);
% Check optional arguments
addOptional(p, 'alpha', 0.66, @isnumeric);
addOptional(p, 'epsilon', zeros(size(model.rxns)), @isnumeric);
% extract variables from parser
parse(p, model, rxnFBS, Vref, varargin{:});
alpha = p.Results.alpha;
epsilon = p.Results.epsilon;

% sometimes epsilon can be given as a single value
if numel(epsilon)==1
    epsilon = epsilon * ones(size(model.rxns));
end

%% --- set the COBRA model ---

% variables
v = 1:length(model.rxns);
y_plus_F = (1:sum(rxnFBS==+1)) + v(end);             % 1 if change in rxnForward, 0 otherwise
y_minus_F = (1:sum(rxnFBS==+1)) + y_plus_F(end);     % 1 if no change in rxnForward, 0 otherwise
y_plus_B = (1:sum(rxnFBS==-1)) + y_minus_F(end);     % 1 if change in rxnBackward, 0 otherwise
y_minus_B = (1:sum(rxnFBS==-1)) + y_plus_B(end);     % 1 if no change in rxnBackward, 0 otherwise
n_var = y_minus_B(end);

% limits of the variables
lb = zeros(n_var,1);
ub = ones (n_var,1);
lb(v) = model.lb;
ub(v) = model.ub;

%type of variables
vartype(1:n_var) = 'B';
vartype(v) = 'C';

% constrains
Eq1 = 1:length(model.mets);                 % Stoichiometric matrix
Eq2 = (1:length(y_plus_F)) + Eq1(end);      % Changes in Forward
Eq3 = (1:length(y_plus_F)) + Eq2(end);      % Change or not change in Forward
Eq4 = (1:length(y_plus_B)) + Eq3(end);      % Changes in Backward
Eq5 = (1:length(y_plus_B)) + Eq4(end);      % Change or not change in Backward
nCon = Eq5(end);

% generate constrain matrix
A = spalloc(nCon, n_var, nnz(model.S) + 5*length(Eq2) + 5*length(Eq4));
b = zeros(nCon,1);
csense = char(zeros(nCon,1));

posF = find(rxnFBS == +1);
posB = find(rxnFBS == -1);
posS = find(rxnFBS == 0);

% First contraint, stoichiometric
A(Eq1,v) = model.S;
b(Eq1) = 0;
csense(Eq1) = 'E';

% Second contraint, Change or not change in Forward
A(Eq2,v(posF)) = eye(length(posF));
A(Eq2,y_plus_F) = - ( Vref(posF) + epsilon(posF) ) .* eye(length(posF));
A(Eq2,y_minus_F) = - model.lb(posF) .* eye(length(posF));
b(Eq2) = 0;
csense(Eq2) = 'G';

% Third contraint, Change or not change in Forward
A(Eq3,y_plus_F) = eye(length(Eq3));
A(Eq3,y_minus_F) = eye(length(Eq3));
b(Eq3) = 1;
csense(Eq3) = 'E';

% Fourth contraint, Backward changes
A(Eq4,posB) = eye(length(posB));
A(Eq4,y_plus_B) = - ( Vref(posB) - epsilon(posB) ) .* eye(length(posB));
A(Eq4,y_minus_B) = - model.ub(posB) .* eye(length(posB));
b(Eq4) = 0;
csense(Eq4) = 'L';

% Fiveth contraint, Change or not change in Backward
A(Eq5,y_plus_B) = eye(length(Eq5));
A(Eq5,y_minus_B) = eye(length(Eq5));
b(Eq5) = 1;
csense(Eq5) = 'E';

% Objective fuction
% linear part
c = zeros(n_var,1);
c(y_minus_F) = alpha/2;
c(y_minus_B) = alpha/2;
c(v(posS)) = -2 * Vref(posS) * (1-alpha);
% quadratic part
F = spalloc(n_var,n_var,length(posS));
F(v(posS),v(posS)) =  2 * (1-alpha) .* eye(length(posS));

% save the resultant model
OptimizationModel = struct();
[OptimizationModel.A, OptimizationModel.lb, OptimizationModel.ub] = deal(A, lb, ub);
[OptimizationModel.b, OptimizationModel.csense] = deal(b, csense);
[OptimizationModel.c, OptimizationModel.F] = deal(c, F);
[OptimizationModel.osense, OptimizationModel.vartype] = deal(+1, vartype); % +1 for minimization

%save the index of the variables
OptimizationModel.idx_variables.v = v;
OptimizationModel.idx_variables.y_plus_F = y_plus_F;
OptimizationModel.idx_variables.y_minus_F = y_minus_F;
OptimizationModel.idx_variables.y_plus_B = y_plus_B;
OptimizationModel.idx_variables.y_minus_B = y_minus_B;

end


function [p,t] = meshpoly(node,edge,qtree,p,options)

%*****************************************************************************80
%
% MESHPOLY: Core meshing routine called by mesh2d and meshfaces.
%
% Do not call this routine directly, use mesh2d or meshfaces instead!
%
% Inputs:
%
%  NODE     : Nx2 array of geometry XY co-ordinates
%  EDGE     : Mx2 array of connections between NODE, defining geometry
%             edges
%  QTREE    : Quadtree data structure, defining background mesh and element
%             size function
%  P        : Qx2 array of potential boundary nodes
%  OPTIONS  : Meshing options data structure
%  WBAR     : Handle to progress bar
%
% Outputs:
%
%  P        : Nx2 array of triangle nodes
%  T        : Mx3 array of triangles as indices into P
%
% Mesh2d is a delaunay based algorithm with a "Laplacian-like" smoothing
% operation built into the mesh generation process.
%
% An unbalanced quadtree decomposition is used to evaluate the element size
% distribution required to resolve the geometry. The quadtree is
% triangulated and used as a backgorund mesh to store the element size
% data.
%
% The main method attempts to optimise the node location and mesh topology
% through an iterative process. In each step a constrained delaunay
% triangulation is generated with a series of "Laplacian-like" smoothing
% operations used to improve triangle quality. Nodes are added or removed
% from the mesh to ensure the required element size distribution is
% approximated.
%
% The optimisation process generally returns well shaped meshes with no
% small angles and smooth element size variations. Mesh2d shares some
% similarities with the Distmesh code:
%
%   [1] P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB.
%       SIAM Review, Volume 46 (2), pp. 329-345, June 2004
%
%  Author:
%
%    Darren Engwirda
%

shortedge   = 0.75;
longedge    = 1.5;
smalltri    = 0.25;
largetri    = 4.0;
qlimit      = 0.5;
dt          = 0.2;

stats = struct('t_init',0.0,'t_tri',0.0,'t_inpoly',0.0,'t_edge',0.0, ...
                  't_sparse',0.0,'t_search',0.0,'t_smooth',0.0,'t_density',0.0, ...
                     'n_tri',0);

% Initialise mesh
%  P     : Initial nodes
%  T     : Initial triangulation
%  TNDX  : Enclosing triangle for each node as indices into TH
%  FIX   : Indices of FIXED nodes in P
tic
if options.output
   fprintf('Initialising Mesh \n');
end
[p,fix,tndx] = initmesh(p,qtree.p,qtree.t,qtree.h,node,edge);
stats.t_init = toc;

% Main loop
if options.output
   fprintf('Iteration   Convergence (%%)\n');
end
for iter = 1:options.maxit

   [p,i,j] = unique(p,'rows');                                             % Ensure unique node list
   fix = j(fix);
   tndx = tndx(i);

   tic
   [p,t] = cdt(p,node,edge);                                               % Constrained Delaunay triangulation
   stats.n_tri = stats.n_tri+1;
   stats.t_tri = stats.t_tri+toc;

   tic
   e = getedges(t,size(p,1));                                    % Unique edges
   stats.t_edge = stats.t_edge+toc;

   % Sparse node-to-edge connectivity matrix
   tic
   nume = size(e,1);
   S = sparse(e(:),[1:nume,1:nume],[ones(nume,1); -ones(nume,1)],size(p,1),nume);
   stats.t_sparse = stats.t_sparse+toc;

   tic
%
% Find enclosing triangle in background mesh for nodes
%
  opt = 4;
  if ( opt == 0 )
    tndx = mytsearch ( qtree.p(:,1), qtree.p(:,2), qtree.t, p(:,1), p(:,2), tndx );
  elseif ( opt == 1 )
    tndx = tsearch ( qtree.p(:,1), qtree.p(:,2), qtree.t, p(:,1), p(:,2) );
  elseif ( opt == 2 )
    tndx = tsearch_mex ( qtree.p(:,1), qtree.p(:,2), qtree.t, p(:,1), p(:,2) );
  elseif ( opt == 3 )
    dtri = DelaunayTri ( qtree.p );
    tndx = pointLocation ( dtri, p );
  elseif ( opt == 4 )
    tndx = tsearchn ( qtree.p, qtree.t, p );
  end

   hn = tinterp(qtree.p,qtree.t,qtree.h,p,tndx);  % Size function at nodes via linear interpolation
   h = 0.5*(hn(e(:,1))+hn(e(:,2)));                                        % from the background mesh. Average to edge midpoints.
   stats.t_search = stats.t_search+toc;

   edgev = p(e(:,1),:)-p(e(:,2),:);
   L = max(sqrt(sum((edgev).^2,2)),eps);                                   % Edge lengths

   % Inner smoothing sub-iterations
   time = cputime;
   move = 1.0;
   done = false;
   for subiter = 1:(iter-1)

      moveold = move;

      % Spring based smoothing
      L0 = h*sqrt(sum(L.^2)/sum(h.^2));
      F = max(L0./L-1.0,-0.1);
      F = S*(edgev.*[F,F]);
      F(fix,:) = 0.0;
      p = p+dt*F;

      % Measure convergence
      edgev = p(e(:,1),:)-p(e(:,2),:);
      L0 = max(sqrt(sum((edgev).^2,2)),eps);                               % Edge lengths
      move = norm((L0-L)./L,'inf');                                        % Percentage change
      L = L0;

      if move<options.mlim                                                 % Test convergence
         done = true;
         break
      end

   end
   stats.t_smooth = stats.t_smooth+(cputime-time);

   if options.output
      fprintf('%2i           %2.1f\n',[iter, 100.0*min(1.0, options.mlim/max(move,eps))]);
   end

   tic
   [p,t] = cdt(p,node,edge);                                               % Constrained Delaunay triangulation
   stats.n_tri = stats.n_tri+1;
   stats.t_tri = stats.t_tri+toc;

   tic
   e = getedges(t,size(p,1));                                              % Unique edges
   stats.t_edge = stats.t_edge+toc;

   edgev = p(e(:,1),:)-p(e(:,2),:);
   L = max(sqrt(sum((edgev).^2,2)),eps);                                   % Edge lengths

   tic
%
% Find enclosing triangle in background mesh for nodes
%
  opt = 4;
  if ( opt == 0 )
    tndx = mytsearch ( qtree.p(:,1), qtree.p(:,2), qtree.t, p(:,1), p(:,2), tndx );
  elseif ( opt == 1 )
    tndx = tsearch ( qtree.p(:,1), qtree.p(:,2), qtree.t, p(:,1), p(:,2) );
  elseif ( opt == 2 )
    tndx = tsearch_mex ( qtree.p(:,1), qtree.p(:,2), qtree.t, p(:,1), p(:,2) );
  elseif ( opt == 3 )
    dtri = DelaunayTri ( qtree.p );
    tndx = pointLocation ( dtri, p );
  elseif ( opt == 4 )
    tndx = tsearchn ( qtree.p, qtree.t, p );
  end

   hn = tinterp(qtree.p,qtree.t,qtree.h,p,tndx);                           % Size function at nodes via linear interpolation
   h = 0.5*(hn(e(:,1))+hn(e(:,2)));                                        % from the background mesh. Average to edge midpoints.
   stats.t_search = stats.t_search+toc;

   r = L./h;
   if done && (max(r)<3.0)                                                 % Main loop convergence
      break
   else
      if (iter==options.maxit)
         fprintf('WARNING: Maximum number of iterations reached. Solution did not converge! \n');
         fprintf('Please email the geometry and settings to d_engwirda@hotmail.com \n');
      end
   end

   % Nodal density control
   tic
   if iter<options.maxit
      % Estimate required triangle area from size function
      Ah = 0.5*tricentre(t,hn).^2;
      % Remove nodes
      i = find(abs(triarea(p,t))<smalltri*Ah);                             % Remove all nodes in triangles with small area
      k = find(sum(abs(S),2)<2);                                           % Nodes with less than 2 edge connections
      j = find(r<shortedge);                                               % Remove both nodes for short edges
      if ~isempty(j) || ~isempty(k) || ~isempty(i)
         prob = false(size(p,1),1);                                        % True for nodes to be removed
         prob(e(j,:)) = true;                                              % Edges with insufficient length
         prob(t(i,:)) = true;                                              % Triangles with insufficient area
         prob(k) = true;                                                   % Remove nodes with less than 2 edge connections
         prob(fix) = false;                                                % Don't remove fixed nodes
         pnew = p(~prob,:);                                                % New node list
         tndx = tndx(~prob);
         j = zeros(size(p,1),1);                                           % Re-index FIX to keep consistent
         j(~prob) = 1;
         j = cumsum(j);
         fix = j(fix);
      else
         pnew = p;
      end
      % Add new nodes
      i = abs(triarea(p,t))>largetri*Ah;                                   % Large triangles
      r = longest(p,t)./tricentre(t,hn);
      k = (r>longedge) & (quality(p,t)<qlimit);                            % Low quality triangles
      if any(i|k)

         k = find(k & ~i);
         i = find(i);

         % Add new nodes at circumcentres
         cc = circumcircle(p,[t(i,:); t(k,:)]);

         % Don't add multiple points in one circumcircle
         ok = [true(size(i)); false(size(k))];
         for ii = (length(i)+1):size(cc,1)
            % Current point
            x = cc(ii,1);
            y = cc(ii,2);
            % Check if inside any accepted circumcircles
            in = false;
            j = find(ok);
            for jj = 1:length(j)
               kk = j(jj);
               dx = (x-cc(kk,1))^2;
               if dx<cc(kk,3) && (dx+(y-cc(kk,2))^2)<cc(kk,3)
                  in = true;
                  break;
               end
            end
            if ~in
               ok(ii) = true;
            end
         end
         cc = cc(ok,:);
         cc = cc(inpoly(cc(:,1:2),node,edge),:);                           % Only take internal points

         % New arrays
         pnew = [pnew; cc(:,1:2)];
         tndx = [tndx; zeros(size(cc,1),1)];
      end
      p = pnew;
   end
   stats.t_density = stats.t_density+toc;

end

if options.debug
   disp(stats);
end

end      % meshpoly()

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [p,t] = cdt(p,node,edge)

% Approximate geometry-constrained Delaunay triangulation.

t = mydelaunayn(p);                                                        % Delaunay triangulation via QHULL

% Impose geometry constraints
i = inpoly(tricentre(t,p),node,edge);                                      % Take triangles with internal centroids
t = t(i,:);

end      % [p,t] = cdt(p,node,edge)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [p,fix,tndx] = initmesh(p,ph,th,hh,node,edge)

% Initialise the mesh nodes

% Boundary nodes for all geometry edges have been passed in. Only take
% those in the current face
i = findedge(p,node,edge,1.0e-08);
p = p(i>0,:);
fix = (1:size(p,1))';

% Initial nodes taken as fixed boundary nodes + internal nodes from
% quadtree.
[i,j] = inpoly(ph,node,edge);
p = [p; ph(i&~j,:)];
tndx = zeros(size(p,1),1);

end      % initmesh()

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function e = getedges(t,n)

% Get the unique edges and boundary nodes in a triangulation.

e = sortrows( sort([t(:,[1,2]); t(:,[1,3]); t(:,[2,3])],2) );
idx = all(diff(e,1)==0,2);                                                 % Find shared edges
idx = [idx;false]|[false;idx];                                             % True for all shared edges
bnd = e(~idx,:);                                                           % Boundary edges
e = e(idx,:);                                                              % Internal edges
e = [bnd; e(1:2:end-1,:)];                                                 % Unique edges and bnd edges for tri's

end      % getedges()

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function fc = tricentre(t,f)

% Interpolate nodal F to the centroid of the triangles T.

fc = (f(t(:,1),:)+f(t(:,2),:)+f(t(:,3),:))/3.0;

end      % tricentre()

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function d = longest(p,t)

% Return the length of the longest edge in each triangle.

d1 = sum((p(t(:,2),:)-p(t(:,1),:)).^2,2);
d2 = sum((p(t(:,3),:)-p(t(:,2),:)).^2,2);
d3 = sum((p(t(:,1),:)-p(t(:,3),:)).^2,2);

d = sqrt(max([d1,d2,d3],[],2));

end      % longest()


function G = edge_detect(im)
% Here we directly use canny

    [BW,~,G]=edge_canny(rgb2gray(im),'canny');
    BW = imdilate(BW,strel('diamond',5));
    BW = single(BW);
    BW(BW==0) = 0.5;
    BW(1:10,:) = 0;
    BW(end-10:end,:) = 0;
    BW(:,1:10) = 0;
    BW(:,end-10:end) = 0;
    G = G.*BW;
end


function test01 ( input_filename )

%*****************************************************************************80
%
%% TEST01 tests LATINIZE.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 December 2006
%
%  Author:
%
%    John Burkardt
%

%
%  Get the row and column dimensions of the dataset.
%
  [ m, n ] = r8mat_header_read (  input_filename );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read the header of "%s".\n', input_filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Spatial dimension M = %d\n', m );
  fprintf ( 1, '  Number of points N  = %d\n', n );
%
%  Read the array.
%
  table = r8mat_data_read ( input_filename, m, n );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read the data in "%s".\n', input_filename );

  r8mat_transpose_print_some ( m, n, table, 1, 1, 5, 5, ...
    '  Small portion of data read from file:' );
%
%  Latinize the array.
%
  table_latin = r8mat_latinize ( m, n, table );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Latinized the data.\n' );
%
%  Print out a small sample of the array.
%
  r8mat_transpose_print_some ( m, n, table_latin, 1, 1, 5, 5, ...
    '  Small portion of Latinized data:' );
%
%  Make up a name for the output file that is likely to be related
%  to the input file name, and unique.
%
  output_filename = file_name_ext_swap ( input_filename, 'latin.txt' );
%
%  Write the latinized array to a file.
%
  r8mat_write ( output_filename, m, n, table_latin );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Wrote the latinized data to "%s".\n', output_filename );

  return
end


function b = p04_b ( m )

%*****************************************************************************80
%
%% P04_B returns the right hand side B for problem 4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 April 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the number of equations.
%
%    Output, real B(M,1), the right hand side.
%
  b = [ 15.0; 55.0; 225.0 ];

  return
end


function [dS,t,f]=mtdspecgrampb(data,movingwin,phi,params)
% Multi-taper derivatives of time-frequency spectrum - binned point process
%
% Usage:
%
% [dS,t,f]=mtdspecgrampb(data,movingwin,phi,params)
% Input:
%   Note that all times can be in arbitrary units. But the units have to be
%   consistent. So, if E is in secs, win, t have to be in secs, and Fs has to
%   be Hz. If E is in samples, so are win and t, and Fs=1. In case of spike
%   times, the units have to be consistent with the units of data as well.
%       data        (in form samples x channels/trials or a single vector) -- required
%       movingwin         (in the form [window winstep] i.e length of moving
%                                                 window and step size.
%                                                 Note that units here have
%                                                 to be consistent with
%                                                 units of Fs
%       phi         (angle for evaluation of derivative) -- required.
%                       e.g. phi=[0,pi/2] giving the time and frequency
%                       derivatives
%       params: structure with fields tapers, pad, Fs, fpass,trialave
%       -optional
%           tapers : precalculated tapers from dpss or in the one of the following
%                    forms:
%                    (1) A numeric vector [TW K] where TW is the
%                        time-bandwidth product and K is the number of
%                        tapers to be used (less than or equal to
%                        2TW-1).
%                    (2) A numeric vector [W T p] where W is the
%                        bandwidth, T is the duration of the data and p
%                        is an integer such that 2TW-p tapers are used. In
%                        this form there is no default i.e. to specify
%                        the bandwidth, you have to specify T and p as
%                        well. Note that the units of W and T have to be
%                        consistent: if W is in Hz, T must be in seconds
%                        and vice versa. Note that these units must also
%                        be consistent with the units of params.Fs: W can
%                        be in Hz if and only if params.Fs is in Hz.
%                        The default is to use form 1 with TW=3 and K=5
%                    Note that T has to be equal to movingwin(1).
%
%	        pad		    (padding factor for the FFT) - optional (can take values -1,0,1,2...).
%                    -1 corresponds to no padding, 0 corresponds to padding
%                    to the next highest power of 2 etc.
%			      	 e.g. For N = 500, if PAD = -1, we do not pad; if PAD = 0, we pad the FFT
%			      	 to 512 points, if pad=1, we pad to 1024 points etc.
%			      	 Defaults to 0.
%           Fs   (sampling frequency) - optional. Default 1.
%           fpass    (frequency band to be used in the calculation in the form
%                                   [fmin fmax])- optional.
%                                   Default all frequencies between 0 and
%                                   Fs/2
%           trialave (average over trials when 1, don't average when 0) -
%           optional. Default 0
% Output:
%       dS      (spectral derivative in form phi x time x frequency x channels/trials if trialave=0;
%               phi x time x frequency if trialave=1)
%       t       (times)
%       f       (frequencies)

if nargin < 3; error('Need data, window parameters and angle'); end;
if nargin < 4; params=[]; end;

if length(params.tapers)==3 & movingwin(1)~=params.tapers(2);
    error('Duration of data in params.tapers is inconsistent with movingwin(1), modify params.tapers(2) to proceed')
end

[tapers,pad,Fs,fpass,err,trialave,params]=getparams(params);
clear err
data=change_row_to_column(data);
[N,Ch]=size(data);
Nwin=round(Fs*movingwin(1)); % number of samples in window
Nstep=round(movingwin(2)*Fs); % number of samples to step through
nfft=max(2^(nextpow2(Nwin)+pad),Nwin);
f=getfgrid(Fs,nfft,fpass); Nf=length(f);
params.tapers=dpsschk(tapers,Nwin,Fs); % check tapers

winstart=1:Nstep:N-Nwin+1;
nw=length(winstart);
if trialave==0; dS=zeros(length(phi),nw,Nf,Ch); else dS=zeros(length(phi),nw,Nf); end;
for n=1:nw;
   indx=winstart(n):winstart(n)+Nwin-1;
   datawin=data(indx,:);
   [ds,f]=mtdspectrumpb(datawin,phi,params);
   dS(:,n,:,:)=ds;
end;
sz=size(ds);
dS=squeeze(dS);
% if length(sz)==3;
%    dS=permute(dS,[2 1 3 4]);
% elseif length(phi)>1
%    dS=permute(dS,[2 1 3]);
% end;
winmid=winstart+round(Nwin/2);
t=winmid/Fs;


function [F,P] = spm_MH_reml(YY,X,Q,N,hE);
% Estimation of covariance components from y*y' using sampling
% FORMAT [F,P] = spm_MH_reml(YY,X,Q,N,[hE]);
%
% YY  - (m x m) sample covariance matrix Y*Y'  {Y = (m x N) data matrix}
% X   - (m x p) design matrix
% Q   - {1 x q} covariance components
% N   - number of samples
%
% hE  - prior expectation: log-normal hyper-parameterisation (with hyperpriors)
%
% F   - [-ve] free energy F = log evidence = p(Y|X,Q)
% P   - smaple of hyperparameters from thier posterioir p(h|YY,X,Q)
%--------------------------------------------------------------------------
%
% This routiens using MCMC sampling (reverible Metropolis-Hastings)
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_MH_reml.m 5033 2012-11-02 20:59:54Z karl $

% assume a single sample if not specified
%--------------------------------------------------------------------------
try
    N;
catch
    N  = 1;
end

% assume OPT = 0
%--------------------------------------------------------------------------
try
    hE;
    OPT = hE;
catch
    OPT = 0;
end

% ortho-normalise X
%--------------------------------------------------------------------------
if isempty(X)
    X = sparse(length(Q{1}),1);
else
    X = orth(full(X));
end

% remove fixed effects
%--------------------------------------------------------------------------
n     = length(Q{1});
m     = length(Q);
h     = zeros(m,1);
R     = speye(n,n) - X*X';
YY    = R*YY*R;

M.OPT = OPT;
M.Q   = Q;
M.N   = N;

% initialise and specify hyperpriors
%--------------------------------------------------------------------------
[C,h,Ph,Fr] = spm_reml(YY,X,Q,N,0,4,OPT);
if M.OPT
    M.hE  = h - 16;
    M.hP  = eye(m,m)/32;
else
    M.hE  = zeros(m,1);
    M.hP  = speye(m,m)/exp(32);
end

% sample
%--------------------------------------------------------------------------
[P,F] = spm_MH('spm_MH_reml_likelihood',h,YY,M);


% imbibition capillary pressure curve
% Written by Ali A. Eftekhari
function res=dpc_imb(sw, pce_w, pce_o, swc, sor, labda_w, labda_o, pc_max_w, pc_max_o)
  dpc1=dpc_drain(sw, pce_w, swc, labda_w, pc_max_w);
  dpc2=dpc_drain(1-sw, pce_o, sor, labda_o, pc_max_o);
  res=dpc1-dpc2;
end


function mu_all = calc_mu_all(mu_jk, K_all)
% mu_all is B by M by K1
[~,B] = size(mu_jk{1});
[K1,M] = size(K_all);

mu_all = zeros(B,M,K1);
for i = 1:K1
    for j = 1:M
        mu_all(:,j,i) = mu_jk{j}(K_all(i,j),:)';
    end
end

end


function deepLearningExamples(type)
%  deepLearningExamples(demo)
%------------------------------------------------------------------------------
%  A set of demos for the MEDAL toolbox
%------------------------------------------------------------------------------
% <demo> is a string indicating the demonstration type. Options for <demo> are:
%
%    'rbm'          -- Train a binary-input RBM on the MNIST dataset and use
%                      it to classify test cases
%
%    'grbm'         -- Train a gaussian-input RBM on a toy Gaussian Mixture
%                      dataset and use it to classify test cases
%
%    'mlnn'         -- Train single and ulti-layer Neural Networks on the
%                      MNIST dataset and use them to classify test cases
%
%    'dbn'          -- Train a Deep Belief Network on MNIST and use the
%                      top layer to classify test cases.
%
%    'ae'           -- Train sparse and denoising autoencoders on MNIST digits
%
%    'dae'          -- Train a deep autoencoder on MNIST and finetune
%                      the network to classify test cases.
%
%    'crbm'         -- Train a Convolutional RBM on the MNIST dataset.
%
%    'mlcnn'        -- Train a mult-layer Convolutional Neural Network
%                      on MNIST and use it to classify test cases
%
%    'drbm'         -- Train a dynamic RBM on a toy spatiotemporal dataset
%
%    'mcrbm'        -- Train a Mean-Covariance RBM on a color image patches
%
%    'all'          -- Run all demos in sequence
%------------------------------------------------------------------------------
% DES
% stan_s_bury@berkeley.edu

if notDefined('type'), type = 'all'; end

switch lower(type)

case {'binary rbm','rbm'}
% BERNOULLI-BERNOULLI RESTRICTED BOLZMANN MACHINES
clear all; close all; clc
fprintf('\nRunning Binary RBM demo for Classification (demoBinaryRBM_MNIST.m)\n')
demoBinaryRBM_MNIST
fprintf('\nRBM demo finished.\n')

case {'gaussian rbm','grbm'}
% GAUSSIAN-BERNOULLI RESTRICTED BOLZMANN MACHINE ON GMM DATASET
clear all; close all; clc
fprintf('\nRunning Gaussian-Bernoulli RBM demo (demoGaussianRBM_Classifer.m)\n')
demoGaussianRBM_GMM
fprintf('\nGaussian RBM demo finished.\n')

case {'mlnn'}
% MULTI-LAYER NEURAL NETWORK
clear all; close all; clc
fprintf('\nRunning Multi-layer Neural Net demo (demoMLNN.m)\n')
demoMLNN
fprintf('\nNeural Net demo finished\n')

case {'dbn'}
% DEEP BELIEF NETWORK FOR CLASSIFICATION
clear all; close all; clc
fprintf('\nRunning DBN for Classification demo (demoDBN.m)\n')
demoDBN
fprintf('\nDBN demo finished\n')

case {'autoencoder','ae'}
% DENOISING AUTOENCODER
clear all; close all; clc
fprintf('\nRunning Denoising and Sparse Autoencoder demo (demoAE.m)\n')
demoAE;
fprintf('\nAutoencoder demo finished.\n')

case {'deep autoencoder','dae'}
% DENOISING AUTOENCODER
clear all; close all; clc
fprintf('\nRunning Deep Autoencoder demo (demoDAE.m)\n')
demoDAE;
fprintf('\nDeep Autoencoder demo finished.\n')

case {'crbm','convolutional rbm'}
% CONVOLUTIONAL RBM
clear all; close all; clc
fprintf('\nRunning Convolutional RBM demo (demoBinaryCRBM)\n')
demoBinaryCRBM;
fprintf('\nConvolutional RBM demo finished.\n')

case {'mlcnn','cnn','convolutional neural net'}
% CONVOLUTIONAL NEURAL NETWORK
clear all; close all; clc
fprintf('\nRunning Convolutional Neural Net demo (demoMLCNN.m)\n')
demoMLCNN
fprintf('\nConvolutional Neural Net demo finished.\n')

case {'drbm','dynamic rbm'}
% DYNAMIC/CONDITIONAL RBM
clear all; close all; clc
fprintf('\nRunning Dynamic RBM demo (demoDRBM.m)\n')
demoDRBM
fprintf('\nDynamic RBM Demo finished.\n')

case {'mcrbm','mean covariance rbm'}
% MEAN-COVARIANCE RBM
clear all; close all; clc
fprintf('\nRunning Mean-Covariance RBM demo (demoMCRBM.m)\n')
demoMCRBM
fprintf('\nMean-Covariance RBM Demofinished.\n')

case 'all'
demos = {'rbm','grbm','mlnn','dbn','ae','dae','crbm','mlcnn','drbm','mcrbm'};
	for iD = 1:numel(demos)
		deepLearningExamples(demos{iD});
		fprintf('\nPress any key to resume');
		pause
	end
	clc; close all; drawnow; clear all;
end


function A = slaffinitymat(X, X2, nnparams, varargin)
%SLAFFINITYMAT Constructs an affinity matrix
%
% $ Syntax $
%   - A = slaffinitymat(X, [], nnparams, ...)
%   - A = slaffinitymat(X, X2, nnparams, ...)
%
% $ Arguments $
%   - X:        The sample matrix of the (source) nodes
%   - X2:       The sample matrix of the (target) nodes
%   - nnparams: The cell array of parameters for finding nearest neighbors
%               in the form of {method, ...}. Please refer to slfindnn
%               for details of specifying nnparams.
%   - A:        The constructed affinity matrix
%
% $ Description $
%   - A = slaffinitymat(X, X2, nnparams, ...) constructs an affinity
%     matrix to represent the pairwise affinity between neighboring
%     samples. The affinity between non-neighboring samples is set to
%     zero. You can indicate a self-affinity matrix (affinity among the
%     the set of samples) by setting X2 to [].
%     By default, the function uses heated kernel to compute the affinity
%     as explained below. In addition, you can use other formulas to
%     translate the distances to affinity by supplying your tfunctor in
%     the properties.
%     The following is a table of properties that you can specify:
%       \*
%       \t   The Properties of Affinity Matrix construction         \\
%       \h     name         &      description                      \\
%             'sparse'      & Whether to construct sparse matrix
%                             (default = true)                      \\
%             'kernel'      & The kernel to compute affinity         \\
%                             - 'heat': the heated kernel (default)
%                               it uses the following formula to translate
%                               the Euclidean distances into affinities:
%                                 a = exp(- d^2 / (2 *sigma^2))
%                               Here sigma^2 is set to
%                                 diffusion^2 * avg(d^2).
%                               you can set the value of diffusion in the
%                               properties.
%                             - 'simple':  the simple kernel
%                               just set the affinity of all neighboring
%                               samples to 1.
%             'diffusion'   & The diffusion distance relative to
%                             the average distance. (default = 1)    \\
%             'tfunctor'    & The function to transform the distance
%                             values to edge values. (default = [])  \\
%             'sym'         & whether to symmetrizes the graph
%                             (default = true)                       \\
%             'symmethod'   & The method used to symmetrization
%                             (default = [])                          \\
%             'excludeself' & Whether to exclude the edges connecting
%                             the same node. (default = false).
%       \*
%
% $ Arguments $
%   - The properties sym, symmethod and excludeself only take effect
%     when input X2 = [].
%
% $ Remarks $
%   - It wrapps slnngraph to provide a convenient way to compute
%     typical affinity matrix.
%
% $ History $
%   - Created by Dahua Lin, on Sep 12nd, 2006
%

%% parse input and prepare parameters

if nargin < 3
    raise_lackinput('slaffinitymat', 3);
end

opts.sparse = true;
opts.kernel = 'heat';
opts.diffusion = 1;
opts.tfunctor = [];
opts.sym = true;
opts.symmethod = [];
opts.excludeself = false;
opts = slparseprops(opts, varargin{:});

if isempty(X2)
    if opts.excludeself
        X2 = [];
    else
        X2 = X;
    end
else
    opts.sym = false;
end

if isempty(opts.tfunctor)
    switch opts.kernel
        case 'heat'
            tfunctor = {@internal_compaffinity, opts.diffusion};
        case 'simple'
            tfunctor = @(x) ones(size(x));
        otherwise
            error('sltoolbox:invalidarg', ...
                'Invalid kernel name: %s', opts.kernel);
    end
else
    tfunctor = opts.tfunctor;
end

%% main wrapper

A = slnngraph(X, X2, nnparams, ...
    'valtype', 'numeric', ...
    'sparse', opts.sparse, ...
    'tfunctor', tfunctor, ...
    'sym', opts.sym, ...
    'symmethod', opts.symmethod);

%% The internal function to compute affinity

function affvals = internal_compaffinity(dists, diffusion)

sqs = dists .* dists;
sqs = sqs(:);

avgsq = sum(sqs) / length(sqs);
s = (diffusion^2) * avgsq * 2;

affvals = exp(-sqs / s);


function [output] = mf(input)
% A wrapper of MF (Multi-deviation Fusion method)
%
% -------------------------------------------------------------------------
% @article{fu2016mf,
%   title={A fusion-based enhancing method for weakly illuminated images},
%   author={Fu, Xueyang and Zeng, Delu and Huang, Yue and Liao, Yinghao and Ding, Xinghao and Paisley, John},
%   journal={Signal Processing},
%   volume={129},
%   pages={82--96},
%   year={2016},
%   publisher={Elsevier}
% }
% -------------------------------------------------------------------------
%
% OpenCE https://github.com/baidut/OpenCE
% Author: Zhenqiang Ying
% 2017-5-12

if nargin == 0
   I = imload; % imread('yellowlily.jpg'); %
   J = mf(I);
   ezFig(I,J);
   return;
end

Require MF

if ~isfloat(input), input = im2double(input); end
if isfloat(input), input = (input)*255; end

output = multi_fusion(input);
end


% This file create a simple regression based network for speech
% dereverberation or enhancement
%
% Created by Xiong Xiao, Temasek Laboratories, NTU, Singapore.
% Last Modified: 08 Feb 2017
%
function layer = genNetworkSeparation_Masking(para)
para.freqBin = (0:1/para.fft_len:0.5)*2*pi; % w = 2*pi*f, where f is the normalized frequency k/N is from 0 to 0.5.
nFreqBin = length(para.freqBin);

% Part 1: generate the BF weight predicting subnet

if para.useWav  % input is row waveform
    layer{1}.name = 'Input';
    layer{end}.inputIdx = 1;
    layer{end}.dim = [1 1]*para.nCh;

    layer{end+1}.name = 'stft';
    layer{end}.prev = -length(layer)+1;
    layer{end}.fft_len = para.fft_len;
    layer{end}.frame_len = para.frame_len;
    layer{end}.frame_shift = para.frame_shift;
    layer{end}.removeDC = para.removeDC;
    layer{end}.win_type = para.win_type;
    layer{end}.dim = [(para.fft_len/2+1)*para.nCh layer{length(layer)+layer{end}.prev}.dim(1)];
    layer{end}.skipBP = 1;  % skip backpropagation

    layer{end+1}.name = 'Affine';       % scaling the Fourier transform
    layer{end}.prev = -1;
    layer{end}.W = [];
    layer{end}.b = [];
    layer{end}.dim = [1 1] * layer{length(layer)+layer{end}.prev}.dim(1);
    layer{end}.update = 0;
    layer{end}.skipBP = 1;  % skip backpropagation

    % extract a subset of dimensions for prediction. Not used currently, so we
    % will use all the dimensions.
    layer{end+1}.name = 'ExtractDims';
    layer{end}.prev = -1;
    layer{end}.dimIndex = 1:nFreqBin*para.nCh;
    layer{end}.dim = [length(layer{end}.dimIndex) layer{length(layer)+layer{end}.prev}.dim(1)];
    layer{end}.skipBP = 1;

    % get the log power spectrum and perform CMN
    layer{end+1}.name = 'Power';
    layer{end}.prev = -1;
    layer{end}.dim = [1 1] * layer{end-1}.dim(1);
    layer{end}.skipBP = 1;

    layer{end+1}.name = 'Log';
    layer{end}.const = 1e-2;
    layer{end}.prev = -1;
    layer{end}.dim = [1 1]*layer{end-1}.dim(1);
    layer{end}.skipBP = 1;
else    % input is log spectrogram
    layer{1}.name = 'Input';
    layer{end}.inputIdx = 1;
    layer{end}.dim = [1 1]*(para.fft_len/2+1)*para.nCh;
end

if para.useCMN
    layer{end+1}.name = 'CMN';
    layer{end}.prev = -1;
    layer{end}.dim = [1 1]*layer{end-1}.dim(1);
    layer{end}.skipBP = 1;
end

if strcmpi(para.DeltaGenerationType, 'DeltaByEqn')
    outputDim = nFreqBin;
else
    outputDim = nFreqBin*3;
end

switch para.NetType
    case 'DNN'
        layer{end+1}.name = 'Splice';
        layer{end}.prev = -1;
        layer{end}.context = para.contextSize;
        layer{end}.dim = [layer{end}.context 1]*layer{length(layer)+layer{end}.prev}.dim(1);
        layer{end}.skipBP = 1;

        layer{end+1}.name = 'Affine';       % scaling the Fourier transform
        layer{end}.prev = -1;
        layer{end}.W = [];
        layer{end}.b = [];
        layer{end}.dim = [1 1] * layer{length(layer)+layer{end}.prev}.dim(1);
        layer{end}.update = 0;

        layerRegression = genNetworkFeedForward_v2(layer{end}.dim(1), para.hiddenLayerSize, outputDim, 'mse', 'sigmoid');
    case 'LSTM'
        layer{end+1}.name = 'Delta';
        layer{end}.prev = -1;
        layer{end}.delta_order = 2;
        layer{end}.dim = [layer{end}.delta_order+1 1]*layer{length(layer)+layer{end}.prev}.dim(1);
        layer{end}.skipBP = 1;

        layer{end+1}.name = 'Affine';       % scaling the Fourier transform
        layer{end}.prev = -1;
        layer{end}.W = [];
        layer{end}.b = [];
        layer{end}.dim = [1 1] * layer{length(layer)+layer{end}.prev}.dim(1);
        layer{end}.update = 0;

        tmpTopology.inputDim = layer{end}.dim(1);
        tmpTopology.hiddenLayerSizeLSTM = para.hiddenLayerSize;
        tmpTopology.usePastState = zeros(1,length(para.hiddenLayerSize)); % do not use peeping hole
        tmpTopology.hiddenLayerSizeFF = [];
        tmpTopology.outputDim = outputDim;
        tmpTopology.costFn = 'mse';
        tmpTopology.LastActivation4MSE = 'sigmoid';
        layerRegression = genNetworkLSTM(tmpTopology);
end
layer = [layer layerRegression(2:end-2)];

if ~isempty(para.hiddenLayerSizeFF)
    layerFF = genNetworkFeedForward_v2(para.hiddenLayerSize(end), para.hiddenLayerSizeFF, outputDim, 'mse', 'sigmoid');
    layer = [layer(1:end-1) layerFF(2:end-2)];
end

layer = [layer layer(end-1:end)];
layer{end-1}.prev = -3;
mask_idx = [-2 0] + length(layer);

% apply the masking
if para.useWav  % input is row waveform
    power_idx = ReturnLayerIdxByName(layer, 'power');
else
    input_idx = ReturnLayerIdxByName(layer, 'input');
    layer{end+1}.name = 'exp';
    layer{end}.prev = input_idx(1)-length(layer);
    layer{end}.dim = [1 1]*layer{input_idx(1)}.dim(1);
    power_idx = length(layer);
end

MaskingLayer{1}.name = 'hadamard';
MaskingLayer{end}.dim = [1 1]*layer{end}.dim(1);
MaskingLayer{end}.prev = [mask_idx(1) power_idx(1)] - length(layer) -1;

MaskingLayer{end+1}.name = 'Log';
MaskingLayer{end}.const = 1e-2;
MaskingLayer{end}.prev = -1;
MaskingLayer{end}.dim = [1 1]*MaskingLayer{end-1}.dim(1);

if para.useCMN
    MaskingLayer{end+1}.name = 'CMN';
    MaskingLayer{end}.prev = -1;
    MaskingLayer{end}.dim = [1 1]*MaskingLayer{end-1}.dim(1);
end

if strcmpi(para.DeltaGenerationType, 'DeltaByEqn')
    MaskingLayer{end+1}.name = 'Delta';
    MaskingLayer{end}.prev = -1;
    MaskingLayer{end}.delta_order = 2;
    MaskingLayer{end}.dim = [MaskingLayer{end}.delta_order+1 1]*MaskingLayer{end-1}.dim(1);

    MaskingLayer{end+1}.name = 'Affine';       % scaling the contribution of output dimensions to MSE cost function.
    MaskingLayer{end}.prev = -1;
    MaskingLayer{end}.W = [];
    MaskingLayer{end}.b = [];
    MaskingLayer{end}.dim = [1 1] * MaskingLayer{end-1}.dim(1);
    MaskingLayer{end}.update = 0;
end

layer = [layer MaskingLayer];
output_idx(1) = length(layer);

MaskingLayer2 = MaskingLayer;
MaskingLayer2{1}.prev = [mask_idx(2) power_idx(1)] - length(layer) -1;

layer = [layer MaskingLayer2];
output_idx(2) = length(layer);

if para.useWav
    log_idx = ReturnLayerIdxByName(layer, 'log');
    if para.useCMN
        CleanLayer = layer(1:log_idx(1)+1);
    else
        CleanLayer = layer(1:log_idx(1));
    end
    CleanLayer{1}.inputIdx = 2;
    CleanLayer{1}.dim(:) = 1;
    CleanLayer{2}.dim(:) = CleanLayer{2}.dim(:)/para.nCh;
    CleanLayer{3}.dim(:) = CleanLayer{3}.dim(:)/para.nCh;
    CleanLayer(4) = [];
else
    CleanLayer{1}.name = 'Input';
    CleanLayer{end}.inputIdx = 2;
    CleanLayer{end}.dim = [1 1]*(para.fft_len/2+1);
end

CleanLayer{end+1}.name = 'Delta';
CleanLayer{end}.prev = -1;
CleanLayer{end}.delta_order = 2;
CleanLayer{end}.dim = [CleanLayer{end}.delta_order+1 1]*CleanLayer{length(CleanLayer)+CleanLayer{end}.prev}.dim(1);

CleanLayer{end+1}.name = 'Affine';       % scaling the contribution of output dimensions to MSE cost function.
CleanLayer{end}.prev = -1;
CleanLayer{end}.W = [];
CleanLayer{end}.b = [];
CleanLayer{end}.dim = [1 1] * CleanLayer{length(CleanLayer)+CleanLayer{end}.prev}.dim(1);
CleanLayer{end}.update = 0;
for i=1:length(CleanLayer)
    CleanLayer{i}.skipBP = 1;
end

layer = [layer CleanLayer];
clean1_idx = length(layer);
CleanLayer{1}.inputIdx = 3;
layer = [layer CleanLayer];
clean2_idx = length(layer);

layer{end+1}.name = 'mixture_MSE';
layer{end}.prev = [output_idx clean1_idx clean2_idx] - length(layer);
layer{end}.dim = [1 layer{length(layer)+layer{end}.prev(1)}.dim(1)];

layer = FinishLayer(layer);
end


function fxk = Rate_function(opt, varargin)
% USAGE:
%
%    Rate_function(opt, varargin)
%
% INPUTS:
%    xk:     current point;
%    opt:    structure includes required parameters;
%
%              * .FR - concatenation of forward and reverse stoichiometric matrix
%              * .A - Reduced forward stoichiometric matrix
%              * .B - Reduced reverse stoichiometric matrix
%              * .k - initial kinetic
%
% OUTPUT:
%    fxk:    the vector `f(xk)`

if nargin ~= 2
    error('The number of input arguments is not valid');
end

if nargout >= 2
    error('The number of output arguments is not valid');
end

FR    = opt.FR;
FR_RF = opt.FR_RF;
k     = opt.k;
xk    = varargin{1};

% ======================== Function evaluation =========================

fxk = FR_RF*exp(k+FR'*xk);

end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%% End of Rate_function.m %%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


function [grad_W_rnn, grad_W_emb, emb_indices] = srcCharLayerBackprop(W_rnn, charData, charGrad)
% Backprop for char layer from word gradients to chars.
% Input:
%   W_rnn: recurrent connections of multiple layers, e.g., W_rnn{ll}.
%
% Thang Luong @ 2015, <lmthang@stanford.edu>

  if charData.numRareWords == 0
    grad_W_rnn = [];
    grad_W_emb = [];
    emb_indices = [];
    return;
  end

  assert(length(charGrad.indices) == charData.numRareWords);

  params = charData.params;
  if params.assert
    assert(isequal(sort(charData.rareWordMap(charGrad.indices))', 1:charData.numRareWords));
  end

  topGrads = cell(charData.maxLen, 1);
  topGrads{end} = charGrad.embs(:, charData.rareWordMap(charGrad.indices));

  % init state
  zeroBatch = zeroMatrix([params.lstmSize, params.curBatchSize], params.isGPU, params.dataType);
  zeroState = cell(params.numLayers, 1);
  zeroGrad = cell(params.numLayers, 1);
  for ll=1:params.numLayers % layer
    zeroState{ll}.h_t = zeroBatch;
    zeroState{ll}.c_t = zeroBatch;
    zeroGrad{ll} = zeroBatch;
  end

  [~, ~, grad_W_rnn, grad_W_emb, emb_indices, ~, ~] = rnnLayerBackprop(W_rnn, charData.states, zeroState, ...
  topGrads, zeroGrad, zeroGrad, charData.batch, charData.mask, charData.params, charData.rnnFlags, [], [], [], []);
end