function [Rob,Sen] = installSensors(Rob,Sen)

% INSTALLSENSORS  Install sensors on robots.
%   [Rob, Sen] = INSTALLSENSORS(Rob, Sen) installs each sensor in Sen on
%   the robot Rob(rob), with rob = Sen(sen).robot. Installation is done
%   by augmenting the vector in field Rob(rob).sensors with the new sensor.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

for sen = 1:numel(Sen)

    rob = Sen(sen).robot;

    if rob > numel(Rob)

        error('Attempt to install sensor on inexistent robot.');

    else

        Rob(rob).sensors = [Rob(rob).sensors sen];

    end
end

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

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

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


function data = reshapeData(~, data, nVars)
%RESHAPEDATA   Extract half of the values since the values have been doubled-up
%with the DFS method.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Note: This is used at the end of the time-stepping in SPINOPERATOR/SOLVEPDE
% when constructing the SHPEREFUN output from the discrete values.

% Number of grid points in each direction:
N = length(data{end})/nVars;

% Loop over the entries of the CELL-ARRAY DATA:
for k = 1:length(data)
    % Extract half of the values and the real part since complex-valued
    % SPHEREFUN are not supported; do it for each variable:
    vals = [];
    for i = 1:nVars
        idx = (i-1)*N + 1;
        temp = data{k}(idx:idx+N-1, :);
        vals = [vals; real(temp([floor(N/2)+1:N 1], :))]; %#ok<*AGROW>
    end
    data{k} = vals;
end

end


%  This program is free software; you can redistribute it and/or modify
%  it under the terms of the GNU General Public License as published by
%  the Free Software Foundation; either version 2 of the License, or
%  (at your option) any later version.
%
%  This program is distributed in the hope that it will be useful,
%  but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%  GNU General Public License for more details.
%
%  You should have received a copy of the GNU General Public License
%  along with this program; if not, write to the Free Software
%  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
%function dopnoist
%DOPNOIST Unit test for the function DOPNOISE.

%	O. Lemoine - March 1996.

N=128; Fs=100; D=12;

% The only value we can test is iflaw since y is a random variable.

% Pure tone for a fixed target
F0=25; V=0;
[y,iflaw]=dopnoise(N,Fs,F0,D,V);
d=abs(iflaw-iflaw(1));
if sum(any(d>sqrt(eps)))~=0,
 error('dopnoise test 1 failed');
end;

% Null signal for a non-emitting target
F0=0; V=50;
[y,iflaw]=dopnoise(N,Fs,F0,D,V);
d=abs(iflaw-iflaw(1));
if sum(any(d>sqrt(eps)))~=0,
 error('dopnoise test 2 failed');
end;

N=111; Fs=51; D=9;

% The only value we can test is iflaw since y is a random variable.

% Pure tone for a fixed target
F0=12; V=0;
[y,iflaw]=dopnoise(N,Fs,F0,D,V);
d=abs(iflaw-iflaw(1));
if sum(any(d>sqrt(eps)))~=0,
 error('dopnoise test 3 failed');
end;

% Null signal for a non-emitting target
F0=0; V=51;
[y,iflaw]=dopnoise(N,Fs,F0,D,V);
d=abs(iflaw-iflaw(1));
if sum(any(d>sqrt(eps)))~=0,
 error('dopnoise test 4 failed');
end;


function test_suite = test_parcellfun
% tests for cosmo_cartprod
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #
    try % assignment of 'localfunctions' is necessary in Matlab >= 2016
        test_functions=localfunctions();
    catch % no problem; early Matlab versions can use initTestSuite fine
    end
    initTestSuite;

function test_parcellfun_single_proc()
    nproc=1;
    helper_test_parcellfun(nproc);

function test_cosmo_parallel_get_nproc_available()
    warning_state=cosmo_warning();
    cleaner=onCleanup(@()cosmo_warning(warning_state));
    cosmo_warning('reset');
    cosmo_warning('off');

    nproc=cosmo_parallel_get_nproc_available();
    assert(nproc>=1);

    % should not have shown any warnings
    w=cosmo_warning();
    assert(isempty(w.shown_warnings),sprintf('warning shown: %s',...
                                      w.shown_warnings{:}));

function test_parcellfun_multi_proc()
    nproc=cosmo_parallel_get_nproc_available();
    if nproc==1
        cosmo_notify_test_skipped('No parallel process available');
        return
    end

    helper_test_parcellfun(nproc);

function helper_test_parcellfun(nproc)
    warning_state=cosmo_warning();
    cleaner=onCleanup(@()cosmo_warning(warning_state));
    cosmo_warning('off');

    % try various functions
    funcs={@func_identity,...
            @func_reverse,...
            @numel,...
            @(x)numel(x)>0,...
            };

    % try with both uniform output and without
    arg_cell={{},...
                {'UniformOutput',false}};

    % various number of dimensions
    ndim={0,1,2,3,4}; % 0=empty

    combis=cosmo_cartprod({funcs,arg_cell,ndim});
    n=size(combis,1);

    for c_i=1:n
        combi=combis(c_i,:);
        func_arg=combi{1};
        other_arg=combi{2};
        rand_str_ndim=combi{3};

        rand_cellstr=generate_rand_cellstr(rand_str_ndim);
        func=@()cosmo_parcellfun(nproc,func_arg,rand_cellstr,...
                                other_arg{:});

        ref_func=@() cellfun(func_arg,rand_cellstr,other_arg{:});
        assert_equal_result_or_both_exception_thrown(func,ref_func);
    end

function assert_equal_result_or_both_exception_thrown(f, g)
    try
        f_result=f();
        f_exception=false;
    catch
        f_exception=lasterror();
    end

    try
        g_result=g();
        g_exception=false;
    catch
        g_exception=lasterror();
    end

    f_threw_exception=isstruct(f_exception);
    g_threw_exception=isstruct(g_exception);

    if f_threw_exception
        if ~g_threw_exception
            f_exception.message=sprintf('only f threw exception: %s',...
                                        f_exception.message);
            rethrow(f_exception);
        end
    else
        if g_threw_exception
            g_exception.message=sprintf('only g threw exception: %s',...
                                        g_exception.message);
            rethrow(g_exception);
        end

        assertEqual(f_result,g_result);
    end

function test_illegal_arguments
    warning_state=cosmo_warning();
    cleaner=onCleanup(@()cosmo_warning(warning_state));
    cosmo_warning('off');

    aet=@(varargin)assertExceptionThrown(@()...
                            cosmo_parcellfun(varargin{:}),'');

    % first argument is not scalar integer
    aet(0,@numel,{1,2});
    aet(1.5,@numel,{1,2});
    aet([2 3],@numel,{1,2});

    % second argument is not a function handle
    aet(2,'a',{1,2});
    aet(2,cell(0),{1,2});

    % third argument is not a cell
    aet(2,@numel,[1,2]);
    aet(2,@numel,struct);

    % no uniform output
    % (note: Octave accepts output when using
    %           @(x)[x x]
    %  This may be a bug)
    aet(1,@(x) repmat(x,1,x),{1;2});
    aet(2,@(x) repmat(x,1,x),{1;2});

function rand_cellstr=generate_rand_cellstr(ndim)
    switch ndim
        case 0
            sz=[0,0];

        case 1
            sz=[0,10];

        case 2
            sz=[1,1];

        otherwise
            sz=floor(rand(1,1+ndim)*4);
    end

    randstr=@(unused)char(rand(1,floor(rand()*10))*24+65);
    rand_cellstr=arrayfun(randstr,zeros(sz),'UniformOutput',false);

function y=func_identity(x)
    y=x;

function y=func_reverse(x)
    y=x;
    y(end:-1:1)=x(:);


function [ f ] = getEEF_Force( t )
%% This function is used to get the force acting at the endeffector of the KUKA iiwa 7 R 800.

%% Syntax:
% [ f ] = getEEF_Force( t )

%% About:
% This function is used to get the endeffector force of the KUKA iiwa 7 R 800.
% The force is measured at the media flange of the robot. The components of
% the force vector are described in the base refernce frame of the robot.

%% Arreguments:
% t: is the TCP/IP connection
% f: is 1x3 cell array. Representing the  X,Y and Z components of the force acting on the
% endeffector the forces are measured in (Newton).

% Copyright, Mohammad SAFEEA, 3rd of May 2017

theCommand='Eef_force';
fprintf(t, theCommand);
message=fgets(t);
%disp(message)
[P1,N]=getDoubleFromString(message);

for i=1:3
    f{i}=P1{i};
end

end

function [jPos,j]=getDoubleFromString(message)
n=max(max(size(message)));
j=0;
numString=[];
for i=1:n
    if message(i)=='_'
        j=j+1;
        jPos{j}=str2num(numString);
        numString=[];
    else
        numString=[numString,message(i)];
    end
end
end


function ops = buildRegOps(ops)

% number of channels in db.expts that aren't db.expred
ops.nchannels      = getOr(ops, 'nchannels', 1);
ops.nplanes        = getOr(ops, 'nplanes', 1);

% --- registration options --- %
ops.kriging         = getOr(ops, 'kriging', 1);  % kriging subpixel alignment
ops.PhaseCorrelation = getOr(ops, 'PhaseCorrelation', 1); % set to 0 for non-whitened cross-correlation
if ~ops.kriging
    ops.registrationUpsample = getOr(ops, {'registrationUpsample'}, 1);  % upsampling factor during registration
    % 1 for no upsampling is much faster, 2 may give better subpixel accuracy
end
ops.NimgFirstRegistration  = getOr(ops, 'NimgFirstRegistration', 500); % number of images to include in the first registration pass
ops.NiterPrealign   = getOr(ops, {'NiterPrealign'}, 10); % number of iterations for initial mean image
ops.showTargetRegistration = getOr(ops, 'showTargetRegistration', 1); % shows the image targets for all planes to be registered

% --- non-rigid registration splits FOV into multiple blocks, registers
% each block separately, and then smooths shifts over blocks --- %
% numBlocks = [y-blocks x-blocks]
if getOr(ops, 'nonrigid', 0)
    % default is 8 blocks in the Y direction (1/6 pixels each)
    % ops.numBlocks(1) = # of blocks in Y, ops.numBlocks(2) = # of blocks in X
    ops.numBlocks      = getOr(ops, {'numBlocks'}, [8 1]);
    disp('non-rigid registration chosen');
elseif isfield(ops, 'numBlocks') && ~isempty(ops.numBlocks)
    % if numBlocks is set to a value greater than 1, then run non-rigid
    if numel(ops.numBlocks) == 1
        ops.numBlocks = [ops.numBlocks 1];
    end
    if sum(ops.numBlocks) > 2
        ops.nonrigid               = 1;
        disp('non-rigid registration chosen');
    end
else
    ops.numBlocks = [1 1];
    ops.nonrigid = 0;
end

% --- keep frames at beginning and end of expts (to check for movement)
ops.nimgbegend     = getOr(ops, {'nimgbegend'}, 0);

% --- write tiffs to RegFileTiffLocation if field is not empty --- %
ops.RegFileTiffLocation = getOr(ops, {'RegFileTiffLocation'}, []);
% --- copy binary file to regfilebinlocation if field is not empty --- %
ops.RegFileBinLocation = getOr(ops, {'RegFileBinLocation'}, []);

% --- for aligning across planes --- %
ops.alignTargetImages  = getOr(ops, {'alignTargetImages'}, false); % if true, align target images to each other
ops.interpolateAcrossPlanes = getOr(ops, {'interpolateAcrossPlanes'}, false); %if true, similar looking planes will be averaged together to generate final movie
ops.planesToInterpolate = getOr(ops, {'planesToInterpolate'}, 1:ops.nplanes); % these planes will be considered for interpolation
ops.alignAcrossPlanes  = getOr(ops, {'alignAcrossPlanes'}, false); % at each time point, frame will be aligned to best matching target image (from different planes)

% --- for within plane splitting (if tiffs are too large in Y and X) --- %
ops.splitFOV           = getOr(ops, {'splitFOV'}, [1 1]); % split FOV into chunks if memory issue
% ops.splitFOV(1) = # of subsets in Y, ops.splitFOV(2) = # of subsets in X
ops.smooth_time_space  = getOr(ops, 'smooth_time_space', []);

% --- bidirectional phase offset computation --- %
% assumes same bidirectional offset for each plane
ops.dobidi             = getOr(ops, {'dobidi'}, 1); % compute bidiphase?
% if set to a value by user, do not recompute
if isfield(ops, 'BiDiPhase')
    ops.dobidi         = 0;
end
ops.BiDiPhase          = getOr(ops, {'BiDiPhase'}, 0); % set to default 0


function varargout = sccn_xdf(filename, hdr, begsample, endsample, chanindx)

% This is a wrapper to the reading function from the XDF MATLAB toolbox.
%
% Use as
%   hdr = sccn_xdf(filename);
%   dat = sccn_xdf(filename, hdr, begsample, endsample, chanindx);
%   evt = sccn_xdf(filename, hdr);
%
% See also FT_FILETYPE, FT_READ_HEADER, FT_READ_DATA, FT_READ_EVENT, XDF2FIELDTRIP

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

% ensure this is on the path
ft_hastoolbox('xdf', 1);

needhdr = (nargin==1);
needevt = (nargin==2);
needdat = (nargin==5);

streams = load_xdf(filename);

iscontinuous = false(size(streams));
% figure out which streams contain continuous/regular and discrete/irregular data
for i=1:numel(streams)
  iscontinuous(i) = isfield(streams{i}.info, 'effective_srate');
end

% determine the stream with the highest sampling rate
srate = nan(size(streams));
for i=1:numel(streams)
  if iscontinuous(i)
    srate(i) = streams{i}.info.effective_srate;
  end
end
[~, indx] = max(srate);

% only keep the stream with the maximum sampling rate
% this is probably the EEG stream
stream = streams{indx};

if needhdr
  % this section of code is shared with xdf2fieldtrip
  hdr             = [];
  hdr.Fs          = stream.info.effective_srate;
  hdr.nChans      = numel(stream.info.desc.channels.channel);
  hdr.nSamplesPre = 0;
  hdr.nSamples    = length(stream.time_stamps);
  hdr.nTrials     = 1;
  hdr.label       = cell(hdr.nChans, 1);
  hdr.chantype    = cell(hdr.nChans, 1);
  hdr.chanunit    = cell(hdr.nChans, 1);

  prefix = stream.info.name;
  for i=1:hdr.nChans
    hdr.label{i} = [prefix '_' stream.info.desc.channels.channel{i}.label];
    hdr.chantype{i} = stream.info.desc.channels.channel{i}.type;
    hdr.chanunit{i} = stream.info.desc.channels.channel{i}.unit;
  end

  hdr.FirstTimeStamp     = stream.time_stamps(1);
  hdr.TimeStampPerSample = (stream.time_stamps(end)-stream.time_stamps(1)) / (length(stream.time_stamps) - 1);

  % keep the original header details
  hdr.orig = stream.info;

  % return the header
  varargout = {hdr};

elseif needevt
  streams = streams(~iscontinuous);
  event = [];
  for i=1:numel(streams)
    for j=1:numel(streams{i}.time_series)

      % convert the timestamps to the corresponding sample in the selected data stream
      % the first sample in the data stream corresponds to 1
      timestamp = streams{i}.time_stamps(j);
      sample = round((timestamp - hdr.FirstTimeStamp)/hdr.TimeStampPerSample) + 1;

      event(end+1).type      = streams{i}.info.type;
      event(end  ).value     = streams{i}.time_series{j};
      event(end  ).timestamp = timestamp;
      event(end  ).sample    = sample;
    end
  end

  % return the events
  varargout = {event};

elseif needdat
  dat = stream.time_series(chanindx, begsample:endsample);

  % return the data
  varargout = {dat};
end


function [ readerobj ] = open_ctiff_reader_noxml( filename, symmetry )
%OPEN_CTIFF_READER Read a TIFF that uses a complex SampleFormat
%
% Unfortunately, we have to write our own code here since the TIFF library
% that MATLAB uses does not support a complex SampleFormat.  Actually, this
% reader works for other TIFFs as well, but for those we can use the
% builtin MATLAB functions.
%
% Written by: Wade Schwartzkopf, NGA/IDT
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

if nargin<2
    symmetry=[0 0 0];
end

%% Get TIFF metadata
tags = read_tiff_tags(filename);

%% Error check
% This function is intentionally only limited capability, purely to
% overcome the fact that the MATLAB TIFF reader doesn't handle complex data
% types.  None of TIFF files with complex data that we have ever seen have
% fallen into one of these cases checked for below.  If we find one, we may
% have to extend the reader to handle that case.  These checks will at
% least warn a user to explain why the reader is not working.
fixed_rowlength = all(tags{1}.StripByteCounts==tags{1}.StripByteCounts(1));
if isequal(class(tags{1}.StripOffsets), class(tags{1}.StripByteCounts))
    % Don't change if possible
    StripOffsets = tags{1}.StripOffsets;
    StripByteCounts = tags{1}.StripByteCounts;
else  % Sometimes come in different integer classes, so cast to common
    StripOffsets = uint64(tags{1}.StripOffsets);
    StripByteCounts = uint64(tags{1}.StripByteCounts);
end
contiguous = all((StripOffsets(1:(end-1)) + ...
    StripByteCounts(1:(end-1))) == StripOffsets(2:end));
if ~fixed_rowlength || ~contiguous
    error('OPEN_CTIFF_READER_NOXML:NONCONTIGUOUS_DATA','This TIFF reader only handles contiguous data.');
end
if isfield(tags{1},'Compression') && tags{1}.Compression~=1
    error('OPEN_CTIFF_READER_NOXML:COMPRESSED_DATA','This TIFF reader does not handle compressed data.');
end
if isfield(tags{1},'FillOrder') && tags{1}.FillOrder~=1
    error('OPEN_CTIFF_READER_NOXML:COMPRESSED_DATA','This TIFF reader does not handle bit-reversed data.');
end
% Reader currently only handle pixel-interleaved ("chunky") data
if isfield(tags{1},'PlanarConfiguration') && tags{1}.PlanarConfiguration~=1
    error('OPEN_CTIFF_READER_NOXML:COMPRESSED_DATA','This TIFF reader does not handle "planar" format (band-interleaved) data.');
end
if isfield(tags{1},'ExtraSamples') && ~isempty(tags{1}.ExtraSamples)
    error('OPEN_CTIFF_READER_NOXML:EXTRA_SAMPLES','This TIFF reader does not handle extra samples per pixel.');
end
if isfield(tags{1},'TileOffsets')
    error('OPEN_CTIFF_READER_NOXML:COMPRESSED_DATA','This TIFF reader does not handle tiled data.');
end

%% Testing pixel reading here
% For now, we just use first image.  Later if we run into TIFF files with
% more than one image, we will have to include all of them and return a
% cell array of reader objects.
image_n = 1;
% Setup SICD metadata stub
meta.native.tiff=tags{image_n};
if symmetry(3)
    meta.ImageData.NumCols=uint32(tags{image_n}.ImageLength);
    meta.ImageData.NumRows=uint32(tags{image_n}.ImageWidth);
else
    meta.ImageData.NumCols=uint32(tags{image_n}.ImageWidth);
    meta.ImageData.NumRows=uint32(tags{image_n}.ImageLength);
end
datasize=double([tags{image_n}.ImageWidth tags{image_n}.ImageLength]);
% Compute parameters necessary for reading pixel data
% Determine TIFF endianness
fid = fopen(filename,'r','b','US-ASCII');
endian = fread(fid,2,'uint8=>char').';
fclose(fid);
switch endian
    case 'II'
        endian = 'l';
    case 'MM'
        endian = 'b';
    % No need for otherwise since this would have already been checked in
    % the read_tiff_tags() call above.
end
if isfield(tags{image_n},'SampleFormat')
    switch tags{image_n}.SampleFormat(1) % Assumes same format for all bands
        case 1
            datatype = 'uint';
            complextype = 0;
        case 2
            datatype = 'int';
            complextype = 0;
        case 3
            datatype = 'float';
            complextype = 0;
        case 5
            datatype = 'int';
            complextype = 1;
        case 6
            datatype = 'float';
            complextype = 1;
        otherwise
            error('Unrecognized datatype.');
    end
else
    datatype = 'uint';
end
bits_per_sample = tags{image_n}.BitsPerSample(1) / (complextype+1); % Assumes same format for all bands
datatype = [datatype num2str(bits_per_sample)];
bands = double(tags{image_n}.SamplesPerPixel);
% Initialize reader object
readerobj=open_generic_reader(filename, datasize,...
    datatype, complextype, double(tags{image_n}.StripOffsets(1)), endian, symmetry, bands);
readerobj.get_meta=@() meta;

end

% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////


function class_info=gen_class_info_nyud()

class_info=[];

class_info.class_names={
    'wall'
    'floor'
    'cabinet'
    'bed'
    'chair'
    'sofa'
    'table'
    'door'
    'window'
    'bookshelf'
    'picture'
    'counter'
    'blinds'
    'desk'
    'shelves'
    'curtain'
    'dresser'
    'pillow'
    'mirror'
    'floor mat'
    'clothes'
    'ceiling'
    'books'
    'refridgerator'
    'television'
    'paper'
    'towel'
    'shower curtain'
    'box'
    'whiteboard'
    'person'
    'night stand'
    'toilet'
    'sink'
    'lamp'
    'bathtub'
    'bag'
    'otherstructure'
    'otherfurniture'
    'otherprop'
    'void'};

class_label_values=uint8([1:40 255]);
class_info.class_label_values=class_label_values;

class_info.background_label_value=uint8(1);
class_info.void_label_values=uint8(255);

class_info.mask_cmap = VOClabelcolormap(256);
class_info=process_class_info(class_info);

end


function [pathway, stats, sPtrNew] = mtrReadCaminoPathwayFromStream(rawPaths, sPtr, mode)

% Default mode is the overriden contrack way
if notDefined('mode'), mode = 1; end

if mode==0
    % Actual camino format
    numPoints = rawPaths(sPtr);
    seedID = rawPaths(sPtr+1);
    stats = seedID;
    pathway = [];
    %pathway = reshape(rawPaths(sPtr+2:sPtr+1+3*numPoints),3,numPoints);
    sPtrNew = sPtr+3*numPoints+2;
else
    % Lightweight Query format
    numStats = rawPaths(sPtr);
    numPoints = rawPaths(sPtr+1);
    stats = rawPaths(sPtr+2:sPtr+2+numStats-1);
    pathway = reshape(rawPaths(sPtr+numStats+2:sPtr+numStats+1+3*numPoints),3,numPoints);
    sPtrNew = sPtr+3*numPoints+numStats+2;
end

return;


function keys=hash_keys(hs)
% keys=hash_keys(hs)
%   Returns cell array of keys of the hash hs
%
%   Input:
%       hs  - hash clas
%
%   Output:
%       keys- cell array

% Dimitar Atanasov, 2010
% datanasov@nbu.bg

K = hs.keys;

keys = {};

for k=1:size(K,2)
    for k1 = K{k}
        keys = [keys k1];
    end;
end;


function varargout = hlp_nanocache(groupname,poolsize,func,varargin)
% Cache results of function calls.
% Results... = hlp_nanocache(Groupname,Poolsize,Function,Arguments...)
%
% The nanocache is useful when you want to cache the result of a computation for later reuse. This
% is done by comparing the given inputs with cached copies using isequal(), so you can only have a
% very small number of distinct inputs unless the inputs differ in their byte size (like data
% structures), in which case the nanocache is extremely efficient. You can also map them onto
% different groupnames (e.g., using a hash function), in which case the nanocache is also very
% efficient.
%
% In:
%   Groupname : A name that separates different groups of nanocache calls (e.g., name of the calling
%               function, or name of a key string in the Arguments). Can also be the same for every call.
%
%   Poolsize : Maximum number of entries to store per cache pool. Each group has one cache pool for
%              each Function and each length of Arguments (in bytes). The pool size limits how many
%              arguments of the same length the nanocache can hold for a given Function and Groupname.
%              Recommended number: 10.
%
%   Function : Function handle or name that should be called.
%
%   Arguments... : Arguments to pass to the function.
%
% Out:
%   Results... : Return values of the function for the given arguments, or cached copy.
%
% Limitations:
%   You cannot use the nanocache for functions whose output depends on anything other than the
%   Arguments (like global variables, files on disk, random numbers, and so on). However, you can make
%   each of these an extra argument to the function in order to use the nanocache.
%
%   If a function should give different results even through the arguments have the same value under
%   isequal, for instance when the type differs but the value is the same (like uint32(3) vs.
%   int32(3)), you need to make the type an extra argument to the function.
%
%   If the Arguments contain NaNs or anonymous functions the nanocache is not effective.
%
% Notes:
%   There is another function that supports more features to overcome most of the limitations of the
%   nanocache (but with extra overhead), called hlp_microcache.
%
%   To clear the nanocache, run the command "clear hlp_nanocache"
%
% Examples:
%   % if this line is executed for the first time, it is as slow as num2str(20.5)
%   str = hlp_nanocache('conversion',10,@num2str,20.5);
%
%   % if it is executed a second time, it is more than 60% faster than num2str(20.5)
%   str = hlp_nanocache('conversion',10,@num2str,20.5);
%
%                                   Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                   2013-10-16

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

    persistent cache;

    % get the pool id based on the call signature (combination of nargout and input size)
    varinfo = whos('varargin');
    poolid = [char('b'+nargout) sprintf('%u',varinfo.bytes)];

    try
        % retrieve the pool of size-equivalent objects
        pool = cache.(groupname).(char(func)).(poolid);
        % search for the key in the pool
        for k=1:length(pool.keys)
            if isequal(varargin,pool.keys{k})
                varargout = pool.values{k};
                return;
            end
        end
    catch %#ok<CTCH>
        % create new pool
        pool = struct('keys',{{}},'values',{{}});
    end

    % did not find the entry: compute it
    [varargout{1:nargout}] = feval(func,varargin{:});

    % add to pool (max size per pool is limited)
    idx = 1+mod(length(pool.keys),poolsize);
    pool.keys{idx} = varargin;
    pool.values{idx} = varargout;
    cache.(groupname).(char(func)).(poolid) = pool;
end


function mapcolormap

load climcm_2
colormap(map);


% testing split_sentence()

inputtext = 'Hi There. How Are you? Jane doesnt have a strange cup. Ms. Brown doesn''t own a little camera. She doesn''t have a light pencil.';

n = split_sentence(inputtext);

for i= 1:size(n,2)
    text = sprintf('%s\n', n{i});
    disp(text)

end

% Reading corpora text
addpath(genpath('corpora\'));
fid1 = fopen('declaration of independence.txt','r'); %# open csv file for reading

while ~feof(fid1)
    line = fgets(fid1); %# read line by line
    n = split_sentence(line);

    for i= 1:size(n,2)
        text = sprintf('%s\n', n{i});
        disp(text)

    end
end
fclose(fid1);


function asa144_test ( )

%*****************************************************************************80
%
%% ASA144_TEST tests ASA144.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 January 2008
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'ASA144_TEST\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the ASA144 library.\n' );

  asa144_test01 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'ASA144_TEST\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


function UFlists
%UFLISTS create the web pages for each matrix list (group, name, etc.)
% Places the web pages in the matrices/ subdirectory of the current directory.
%
% Example:
%   UFlists
%
% See also UFget, UFlist

% Copyright 2006-2007, Timothy A. Davis

% create all the web pages for the lists
UFlist ('group') ;
UFlist ('name') ;
UFlist ('id') ;
UFlist ('dimension') ;
UFlist ('nnz') ;
UFlist ('symmetry') ;
UFlist ('type') ;

% do all the group pages, and the list of groups
index = UFget ;
nmat = length (index.nrows) ;

[ignore, i] = sort (index.Group) ;
g = index.Group (i) ;

% create the primary directory
[url topdir] = UFlocation ;
matrices = [topdir 'matrices'] ;
if (~exist (matrices, 'dir'))
    mkdir (matrices) ;
end

% create the groups.html file
f = fopen ([matrices filesep 'groups.html'], 'w') ;
if (f < 0)
    error ('unable to create groups.html file\n') ;
end

% add the header
fprintf (f, ...
	'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n') ;
fprintf (f, '\n') ;
fprintf (f, '<meta http-equiv="content-type" content="text/html; charset=') ;
fprintf (f, 'iso-8859-1"><title>UF Sparse Matrix Collection: group list') ;
fprintf (f, '</title>\n') ;
fprintf (f, '\n') ;
fprintf (f, '
UF Sparse Matrix Collection\n') ;

fprintf (f, '
List of matrix groups in the UF Sparse Matrix Collection:\n') ;
fprintf (f, '

\n') ;
fprintf (f, 'Group	\n') ;
fprintf (f, '# matrices	\n') ;
fprintf (f, 'details	\n') ;
fprintf (f, 'description	\n') ;

% find all the groups
group = '' ;
ngroup = 0 ;
for i = 1:nmat
    if (strcmp (group, g {i}))
	continue
    end
    group = g {i} ;
    ngroup = ngroup + 1 ;
    groups {ngroup} = group ;						    %#ok
end

nmat = 0 ;
for i = 1:ngroup
    group = groups {i} ;
    UFlist ('group', group) ;
    fprintf (f, '
\n') ;

    % link to group
    fprintf (f, '%s	\n', group, group) ;

    % number of matrices
    d = dir ([topdir 'mat' filesep group filesep '*.mat']) ;
    nmat_group = size (d,1) ;
    fprintf (f, '%d	\n', nmat_group) ;
    nmat = nmat + nmat_group ;

    % link to README.txt file ("details")
    f2 = fopen ([topdir filesep 'mat' filesep group filesep 'README.txt'], 'r');
    if (f2 < 0)
	error (['no README file for group: ' group]) ;
    else
	s = fgets (f2) ;
	fprintf (f, ...
	    'details	\n', group) ;
    end

    % one-line description (first line of README.txt)
    fprintf (f, '%s	\n', s) ;
    fclose (f2);

    fprintf (f, '
\n') ;
end
fprintf (f, '
\n') ;

fprintf (f, '
Total number of matrices in UF Sparse Matrix Collection:') ;
fprintf (f, ' %d\n', nmat) ;
fprintf (f, '

Maintained by Tim Davis, last updated %s.', date) ;
fprintf (f, '
Matrix pictures by cspy, a MATLAB', ...
    url) ;
fprintf (f, ' function in the CSparse package.\n', ...
    url) ;
fprintf (f, '\n') ;
fprintf (f, '\n') ;
fclose (f) ;


function hole_num = p09_hole_num ( )

%*****************************************************************************80
%
%% P09_HOLE_NUM counts the holes in problem 09.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, integer HOLE_NUM, the number of holes.
%
  hole_num = 2;

  return
end


function [intracellRxnList] = findIntracellularRxns(model)
% This function finds all reactions that do not contain metabolites in [e] comparment.
%
% USAGE:
%
%    [intracellRxnList] = findIntracellularRxns(model)
%
% INPUT:
%    model:               Model structure
%
% OUTPUT:
%    intracellRxnList:    List of intracellular reactions in model
%
% .. Author: - Ines Thiele, July 2013, http://thielelab.eu.

intracellRxnList = zeros(length(model.rxns),1);

% exclude extracellular reactions
RL = printRxnFormula(model,model.rxns,false);
for i = 1 : length(RL)
    tmp = regexp(RL{i},'\[e\]');
    if isempty(tmp) % intracellular reaction
        intracellRxnList(i,1)=1;
    end
end
intracellRxnList = model.rxns(find(intracellRxnList));


setenv('MKL_NUM_THREADS','1')
setenv('MKL_SERIAL','YES')
setenv('MKL_DYNAMIC','NO')


function [engine, loglik] = enter_evidence(engine, evidence, varargin)
% ENTER_EVIDENCE Add the specified evidence to the network (jtree)
% [engine, loglik] = enter_evidence(engine, evidence, ...)
%
% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
%
% The following optional arguments can be specified in the form of name/value pairs:
% [default value in brackets]
%
% soft    - a cell array of soft/virtual evidence;
%           soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ]
%
% e.g., engine = enter_evidence(engine, ev, 'soft', soft_ev)

bnet = bnet_from_engine(engine);
ns = bnet.node_sizes(:);
N = length(bnet.dag);

engine.evidence = evidence; % store this for marginal_nodes with add_ev option
engine.maximize = 0;

% set default params
exclude = [];
soft_evidence = cell(1,N);

% parse optional params
args = varargin;
nargs = length(args);
for i=1:2:nargs
  switch args{i},
   case 'soft',    soft_evidence = args{i+1};
   case 'maximize', engine.maximize = args{i+1};
   otherwise,
    error(['invalid argument name ' args{i}]);
  end
end

onodes = find(~isemptycell(evidence));
hnodes = find(isemptycell(evidence));
pot_type = determine_pot_type(bnet, onodes);
 if strcmp(pot_type, 'cg')
  check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag);
end

if is_mnet(bnet)
  pot = engine.user_pot;
  clqs = engine.nums_ass_to_user_clqs;
else
  % Evaluate CPDs with evidence, and convert to potentials
  pot = cell(1, N);
  for n=1:N
    fam = family(bnet.dag, n);
    e = bnet.equiv_class(n);
    if isempty(bnet.CPD{e})
      error(['must define CPD ' num2str(e)])
    else
      pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), ...
                              evidence);
    end
  end
  clqs = engine.clq_ass_to_node(1:N);
end

% soft evidence
soft_nodes = find(~isemptycell(soft_evidence));
S = length(soft_nodes);
if S > 0
  assert(pot_type == 'd');
  assert(mysubset(soft_nodes, bnet.dnodes));
end
for i=1:S
    n = soft_nodes(i);
    % Modif RD - 2006/12/22
    % Why end+1 it doesn't work for me...
    % replace with n and it is ok
    pot{ n } = dpot( n, ns( n ), soft_evidence{ n } );
end
% Modif RD - 2006/12/22
% But now we have to comment this line to ensure dimension matching
%clqs = [clqs engine.clq_ass_to_node(soft_nodes)];

[clpot, seppot] = init_pot(engine, clqs, pot, pot_type, onodes);
[clpot, seppot] = collect_evidence(engine, clpot, seppot);
[clpot, seppot] = distribute_evidence(engine, clpot, seppot);

C = length(clpot);
ll = zeros(1, C);
for i=1:C
  [clpot{i}, ll(i)] = normalize_pot(clpot{i});
end
loglik = ll(1); % we can extract the likelihood from any clique

engine.clpot = clpot;


function varargout = kj_analyze(varargin)
% KJ_ANALYZE Application M-file for kj_analyze.fig
%    FIG = KJ_ANALYZE launch kj_analyze GUI.
%    KJ_ANALYZE('callback_name', ...) invoke the named callback.

% Last Modified by GUIDE v2.0 25-Oct-2001 09:38:02

if (nargin == 2) & ~ischar(varargin{1})  % LAUNCH GUI

  fig = openfig(mfilename,'reuse');

  % Use system color scheme for figure:
  set(fig,'Color',get(groot,'defaultUicontrolBackgroundColor'));

  % Generate a structure of handles to pass to callbacks, and store it.
  handles = guihandles(fig);
  % Store the data
  handles.params = varargin{1};
  handles.hParentFigure = varargin{2};

  % Set the used splitting time if available
  try
    fSplit = handles.params.fSplitTime;
  catch
    fSplit = ((max(handles.params.mCatalog.Date) - min(handles.params.mCatalog.Date)) / 2) + min(handles.params.mCatalog.Date);
  end
  set(handles.txtSplit, 'String', num2str(fSplit, 6));

  % Set the length of the learning period if available
  try
    set(handles.txtFirst, 'String', num2str(handles.params.fLearning));
  catch
    set(handles.txtFirst, 'String', '1');
  end

  % Set the length of the forecasting period if available
  try
    set(handles.txtSecond, 'String', num2str(handles.params.fForecast));
  catch
    set(handles.txtSecond, 'String', '1');
  end

  plotit(handles);

  guidata(fig, handles);

  if nargout > 0
    varargout{1} = fig;
  end

elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK

  try
    [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
  catch ME
    disp(ME.message);
  end

end

% --------------------------------------------------------------------
function plotit(handles)

% Plot the frequency magnitude distribution
if get(handles.radEntireCatalog, 'Value') == 1
  mPlotCatalog = handles.params.mCatalog;
else
  mPlotCatalog = handles.mNodeCatalog;
end

axes(handles.axsFMD);
set(handles.axsFMD, 'NextPlot', 'replace');
set(handles.axsTimePlot, 'NextPlot', 'replace');
if get(handles.radEntireTime, 'Value') == 1
  % Plot the frequency magnitude distribution
  [fBValue, fAValue, fStdDev] = plot_FMD(mPlotCatalog,...
    'Axes',handles.axsFMD, 'CalcMc', handles.params.nCalculateMC, 'MarkerSize', 10);
  set(handles.lblBValue1, 'String', num2str(fBValue, 3));
  set(handles.lblAValue1, 'String', num2str(fAValue, 3));
  set(handles.lblStdValue1, 'String', num2str(fStdDev, 3));
  set(handles.lblBValue2, 'String', '');
  set(handles.lblAValue2, 'String', '');
  set(handles.lblStdValue2, 'String', '');
  % Plot the cumulative number
  [~, vIndices] = sort(mPlotCatalog(:,3));
  mSortedCatalog = mPlotCatalog(vIndices(:,1),:) ;
  axes(handles.axsTimePlot)
  plot(mSortedCatalog(:,3),(1:length(mSortedCatalog(:,3))),'k-');
else
  % Split the catalog
  fFirst = str2double(get(handles.txtFirst, 'String'));
  fSecond = str2double(get(handles.txtSecond, 'String'));
  fSplit = str2double(get(handles.txtSplit, 'String'));
  [mFirst, mSecond] = ex_SplitCatalog(mPlotCatalog, fSplit, 1, fFirst, 1, fSecond);
  % Plot the frequency magnitude distribution for the first period
  [fBValue, fAValue, fStdDev] = plot_FMD(mFirst, 'Axes', handles.axsFMD, ...
      'CalcMethod',handles.params.nCalculateMC, 'MarkerSize', 3);
  set(handles.lblBValue1, 'String', num2str(fBValue, 3));
  set(handles.lblAValue1, 'String', num2str(fAValue, 3));
  set(handles.lblStdValue1, 'String', num2str(fStdDev, 3));
  % Plot the frequency magnitude distribution for the second period
  set(handles.axsFMD, 'NextPlot', 'add');
  [fBValue, fAValue, fStdDev] = plot_FMD(mSecond, 'Axes', handles.axsFMD,...
      'Marker','^', 'Color','r', 'CalcMethod', handles.params.nCalculateMC,'MarkerSize',3);
  set(handles.lblBValue2, 'String', num2str(fBValue, 3));
  set(handles.lblAValue2, 'String', num2str(fAValue, 3));
  set(handles.lblStdValue2, 'String', num2str(fStdDev, 3));

  % Plot the Kagan & Jackson test
  plot_FMD(mSecond, 'ShowCumulative', false, 'Axes', handles.axsTest, 'Marker','o', 'Color', 'b', 'MarkerSize', 4);
  set(handles.axsTest, 'NextPlot', 'add');
  % Calculate Mc
  fMc = calc_Mc(mPlotCatalog, handles.params.nCalculateMC);
  if isnan(fMc)
    fMc = handles.params.fMcOverall;
  elseif isempty(fMc)
    fMc = handles.params.fMcOverall;
  end
  % Define magnitude range for testing
  if handles.params.bMinMagMc
    fMinMag = fMc;
  else
    fMinMag = handles.params.fMinMag;
  end
  % Perform the test
  [fDeltaProbability, fProbabilityK, fProbabilityO, fWeightK, fWeightO, fBValueO, vProbK, vProbO, mPredictionFMD] ...
    = kj_poissonian(mFirst, handles.params.fLearning, mSecond, handles.params.fForecast, handles.params.nTestMethod, ...
    handles.params.nMinimumNumber, fMc, handles.params.fBValueOverall, handles.params.fStdDevOverall, ...
    fMinMag, handles.params.fMaxMag, 1);
  set(handles.txtProbK, 'String', num2str(fProbabilityK));
  set(handles.txtProbO, 'String', num2str(fProbabilityO));
  set(handles.txtProbDiff, 'String', num2str(fDeltaProbability));
  % Plot the results
  vX = (fMinMag:0.1:handles.params.fMaxMag)';
  semilogy(vX, mPredictionFMD(:,1), 'r');
  semilogy(vX, mPredictionFMD(:,2), 'k');
  set(handles.axsTest, 'NextPlot', 'replace');
  axes(handles.axsLikelihood);
  pl1 = plot(vX,cumsum((vProbK)),'k','LineWidth',2.0);
  set(handles.axsLikelihood, 'NextPlot', 'add');
  pl1 = plot(vX,cumsum((vProbO)),'r','LineWidth',2.0);
  set(handles.axsLikelihood, 'NextPlot', 'replace');
  vXLim = get(handles.axsTest, 'XLim');
  set(handles.axsLikelihood, 'XLim', vXLim);

  % Normalize the two subcatalogs in time
  fMinTime = min(mFirst(:,3));
  mFirst(:,3) = mFirst(:,3) - fMinTime;
  fMinTime = min(mSecond(:,3));
  mSecond(:,3) = mSecond(:,3) - fMinTime;
  % Plot the cumulative number for the first period
  [~, vIndices] = sort(mFirst(:,3));
  mSortedCatalog = mFirst(vIndices(:,1),:) ;
  axes(handles.axsTimePlot)
  plot(mSortedCatalog(:,3),(1:length(mSortedCatalog(:,3))),'k-');
  % Plot the cumulative number for the second period
  [~, vIndices] = sort(mSecond(:,3));
  mSortedCatalog = mSecond(vIndices(:,1),:) ;
  axes(handles.axsTimePlot)
  set(handles.axsTimePlot, 'NextPlot', 'add');
  plot(mSortedCatalog(:,3),(1:length(mSortedCatalog(:,3))),'r:');
end

% --------------------------------------------------------------------
function varargout = radEntireCatalog_Callback(h, eventdata, handles, varargin)

if get(handles.radEntireCatalog, 'Value') == 1
  set(handles.radPickLocations, 'Value', 0);
  set(handles.btnPick, 'Enable', 'off');
else
  set(handles.radPickLocations, 'Value', 1);
  set(handles.btnPick, 'Enable', 'on');
end

% --------------------------------------------------------------------
function varargout = radPickLocations_Callback(h, eventdata, handles, varargin)

if get(handles.radPickLocations, 'Value') == 1
  set(handles.radEntireCatalog, 'Value', 0);
  set(handles.btnPick, 'Enable', 'on');
else
  set(handles.radEntireCatalog, 'Value', 1);
  set(handles.btnPick, 'Enable', 'off');
end

% --------------------------------------------------------------------
function varargout = radEntireTime_Callback(h, eventdata, handles, varargin)

if get(handles.radEntireTime, 'Value') == 1
  set(handles.radSplitPeriods, 'Value', 0);
  set(handles.txtFirst, 'Enable', 'off');
  set(handles.txtSecond, 'Enable', 'off');
  set(handles.txtSplit, 'Enable', 'off');
else
  set(handles.radSplitPeriods, 'Value', 1);
  set(handles.txtFirst, 'Enable', 'on');
  set(handles.txtSecond, 'Enable', 'on');
  set(handles.txtSplit, 'Enable', 'on');
end

% --------------------------------------------------------------------
function varargout = radSplitPeriods_Callback(h, eventdata, handles, varargin)

if get(handles.radSplitPeriods, 'Value') == 1
  set(handles.radEntireTime, 'Value', 0);
  set(handles.txtFirst, 'Enable', 'on');
  set(handles.txtSecond, 'Enable', 'on');
  set(handles.txtSplit, 'Enable', 'on');
else
  set(handles.radEntireTime, 'Value', 1);
  set(handles.txtFirst, 'Enable', 'off');
  set(handles.txtSecond, 'Enable', 'off');
  set(handles.txtSplit, 'Enable', 'off');
end

% --------------------------------------------------------------------
function varargout = btnRePlot_Callback(h, eventdata, handles, varargin)

plotit(handles);

% --------------------------------------------------------------------
function varargout = btnClose_Callback(h, eventdata, handles, varargin)

% Close the dialog
delete(handles.dlgAnalyze);

% --------------------------------------------------------------------
function varargout = btnPick_Callback(h, eventdata, handles, varargin)

% Get the axes handle of the plotwindow
axes(kj_result('GetAxesHandle', handles.hParentFigure, [], guidata(handles.hParentFigure)));

% Select a point in the plot window with the mouse
[fX, fY] = ginput(1);

% Prepare the data
% If cross-section calculate the lenght along cross-section
if ~handles.params.bMap
  [nRow, nColumn] = size(handles.params.mCatalog);
  xsecx2 = handles.params.mCatalog(:,nColumn);  % length along x-section
  xsecy2 = handles.params.mCatalog.Depth;        % depth of hypocenters
end

% Calculate distance from center point and sort with distance
if handles.params.bMap
  vDistances = sqrt(((handles.params.mCatalog.Longitude-fX)*cosd(fY)*111).^2 + ((handles.params.mCatalog.Latitude-fY)*111).^2);
else
  vDistances = sqrt(((xsecx2 - fX)).^2 + ((xsecy2 + fY)).^2);
end

% Create the subcatalog
if handles.params.bNumber
  % Use first nNumberEvents events
  [vTmp, vIndices] = sort(vDistances);
  mNodeCatalog = handles.params.mCatalog.subset(vIndices);
  mNodeCatalog = mNodeCatalog(1:handles.params.nNumberEvents);
else
  % Use all events within fRadius
  vSelection = (vDistances <= handles.params.fRadius);
  mNodeCatalog = handles.params.mCatalog.subset(vSelection);
end

% Store the subcatalog for later use
handles.mNodeCatalog = mNodeCatalog;
guidata(handles.dlgAnalyze, handles);

% Replot the frequency magnitude distribution and cumulative number
plotit(handles);


function [varargout]=febStruct2febFile(FEBioInputStruct)

% function [varargout]=febStruct2febFile(FEBioInputStruct)
% ------------------------------------------------------------------------
%
% This function uses the input FEBioInputStruct to generate an FEBio .feb file.
%
%
%
% Kevin Mattheus Moerman
% gibbon.toolbox@gmail.com
%
% 2014/05/27: Updated for GIBBON
% 2015/05/09: Added biphasic capabilities
% 2015/05/10: Added traction load capabilities
% 2017/08/18: Adding support to allow incomplete feb file creation (only
% write fields provided).
% 2018/01/17: Added support for febiospec 2.5 and made it default
% 2018/01/18: Decided to make 2.5 available in new seperate system
%------------------------------------------------------------------------

%%

warning('febStruct2febFile is depricated and will be removed in future releases. Update your codes to use febioStruct2xml, see HELP_febioStruct2xml (furthermore febio_spec version 2.5 is recommended)');

%%

dispStartTitleGibbonCode('Writing FEBio XML object');

%% Set default display setting if missing
if ~isfield(FEBioInputStruct,'disp_opt')
    FEBioInputStruct.disp_opt=0;
end

%% Initialize docNode object
domNode = com.mathworks.xml.XMLUtils.createDocument('febio_spec'); %Create the overall febio_spec field

febioSpecVersion='2.0';

%Set febio_spec
febio_spec = domNode.getDocumentElement;
if ~isfield(FEBioInputStruct,'febio_spec')
    FEBioInputStruct.febio_spec.version=febioSpecVersion;
elseif ~isfield(FEBioInputStruct.febio_spec,'version')
    FEBioInputStruct.febio_spec.version=febioSpecVersion;
end
febio_spec.setAttribute('version',FEBioInputStruct.febio_spec.version); %Adding version attribute

disp(['Using febio_spec: ',FEBioInputStruct.febio_spec.version]);

%% Add comment if present
if isfield(FEBioInputStruct,'commentField')
    commentString = FEBioInputStruct.commentField;
else %Default comment
    commentString = ['Created using GIBBON, ',datestr(now)];
end
commentNode = domNode.createComment(commentString);
febio_spec.appendChild(commentNode);

%% DEFINING MODULE LEVEL
if ~isfield(FEBioInputStruct,'Module')
    FEBioInputStruct.Module.Type='solid'; %Use solid as default module
end
domNode=addModuleLevel_FEB(domNode,FEBioInputStruct);

%% DEFINE CONTROL SECTION
if isfield(FEBioInputStruct,'Control')
    domNode=addControlLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINING GLOBALS LEVEL
if isfield(FEBioInputStruct,'Globals')
    domNode=addGlobalsLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINING MATERIAL LEVEL
if isfield(FEBioInputStruct,'Materials')
    domNode=addMaterialLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINING GEOMETRY LEVEL

if isfield(FEBioInputStruct,'Geometry')
    writeMethod=1; %Use to switch between text mode (1) or XML model (2)
    switch writeMethod
        case 1 % TEXT FILE PARSING (faster for large models)
            domNode=addGeometryLevel_TXT(domNode,FEBioInputStruct);
        case 2 %XML PARSING
            domNode=addGeometryLevel_FEB(domNode,FEBioInputStruct);
    end
end

%% DEFINE BOUNDARY CONDITIONS LEVEL AND LOADS LEVEL
if isfield(FEBioInputStruct,'Boundary')
    [domNode]=addBoundaryLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINE LOAD LEVEL
if isfield(FEBioInputStruct,'Loads')
    [domNode]=addLoadsLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINE CONTACT
if isfield(FEBioInputStruct,'Contact')
    [domNode]=addContactLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINE CONSTRAINTS LEVEL
if isfield(FEBioInputStruct,'Constraints')
    [domNode]=addConstraintsLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINE LOADDATA LEVEL
if isfield(FEBioInputStruct,'LoadData')
    [domNode]=addLoadDataLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINE STEP LEVEL
if isfield(FEBioInputStruct,'Step')
    [domNode]=addStepLevel_FEB(domNode,FEBioInputStruct);
end

%% DEFINE OUTPUT LEVEL
domNode=addOutputLevel_FEB(domNode,FEBioInputStruct);

%% CREATE OUTPUT OR EXPORT XML FILE

switch nargout
    case 0
        disp('Writing .feb file');
        xmlwrite_xerces(FEBioInputStruct.run_filename,domNode); %Custom XML write function
%         if isfield(FEBioInputStruct,'topCommentLine')
%             exportFEB_XML(FEBioInputStruct.run_filename,domNode,FEBioInputStruct.topCommentLine); % Saving XML file
%         else
%             exportFEB_XML(FEBioInputStruct.run_filename,domNode); % Saving XML file
%         end
    case 1
        varargout{1}=domNode;
end
dispDoneGibbonCode;

end

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function Timefreq = in_bst_timefreq(TimefreqFile, LoadFull, varargin)
% IN_TIMEFREQ_BST: Read a sources file in Brainstorm format.
%
% USAGE:  Timefreq = in_bst_timefreq(TimefreqFile, LoadFull=1, FieldsList=All)
%
% INPUT:
%    - TimefreqFile : Absolute or relative path to the file to read
%    - LoadFull     : If 1, and if file is a "Kernel only" file, load the data, compute Kernel*Data to get the full sources time series
%    - FieldsList   : List of fields to read from the file
% OUTPUT:
%    - Timefreq     : Brainstorm timefreq file structure

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2010-2019

%% ===== PARSE INPUTS =====
% Get protocol folders
ProtocolInfo = bst_get('ProtocolInfo');
% Filename: Relative / absolute
if ~file_exist(TimefreqFile)
    TimefreqFile = bst_fullfile(ProtocolInfo.STUDIES, TimefreqFile);
    if ~file_exist(TimefreqFile)
        error('Timefreq file not found.');
    end
end
% Load full?
if (nargin < 2) || isempty(LoadFull)
    LoadFull = 1;
end
isKernel = ~isempty(strfind(TimefreqFile, '_KERNEL_'));
% Specific fields
if (nargin < 3)
    % Read all fields
    Timefreq = load(TimefreqFile);
    % Get all the fields
    FieldsToRead = fieldnames(Timefreq);
    FieldsToRead{end+1} = 'ZScore';
else
    % Get fields to read
    FieldsToRead = varargin;
    % Add some conditional fields
    if ismember('TF', FieldsToRead)
        FieldsToRead{end+1} = 'Measure';
        FieldsToRead{end+1} = 'ZScore';
        if LoadFull && isKernel
            FieldsToRead{end+1} = 'DataFile';
        end
    end
    % When reading Leff, make sure nAvg is read as well
    if ismember('Leff', FieldsToRead) && ~ismember('nAvg', FieldsToRead)
        FieldsToRead{end+1} = 'nAvg';
    end
    % Read each field only once
    FieldsToRead = unique(FieldsToRead);
    % Read specified files only
    warning off MATLAB:load:variableNotFound
    Timefreq = load(TimefreqFile, FieldsToRead{:});
    warning on MATLAB:load:variableNotFound
end

%% ===== FILL OTHER MISSING FIELDS =====
for i = 1:length(FieldsToRead)
    if ~isfield(Timefreq, FieldsToRead{i}) || isempty(Timefreq.(FieldsToRead{i}))
        switch(FieldsToRead{i})
            case 'Measure'
                Timefreq.(FieldsToRead{i}) = 'none';
            case 'nAvg'
                Timefreq.(FieldsToRead{i}) = 1;
            case 'Leff'
                if isfield(Timefreq, 'nAvg') && ~isempty(Timefreq.nAvg)
                    Timefreq.Leff = Timefreq.nAvg;
                else
                    Timefreq.Leff = 1;
                end
            case 'Method'
                if ~isempty(strfind(TimefreqFile, '_psd'))
                    Timefreq.(FieldsToRead{i}) = 'psd';
                elseif ~isempty(strfind(TimefreqFile, '_fft'))
                    Timefreq.(FieldsToRead{i}) = 'fft';
                elseif ~isempty(strfind(TimefreqFile, '_hilbert'))
                    Timefreq.(FieldsToRead{i}) = 'hilbert';
                elseif ~isempty(strfind(TimefreqFile, '_mtmconvol'))
                    Timefreq.(FieldsToRead{i}) = 'mtmconvol';
                else
                    Timefreq.(FieldsToRead{i}) = 'morlet';
                end
            otherwise
                Timefreq.(FieldsToRead{i}) = [];
        end
    end
end

%% ===== FILL EMPTY FIELDS =====
if isfield(Timefreq, 'Measure') && isempty(Timefreq.Measure)
    Timefreq.Measure = 'none';
elseif isfield(Timefreq, 'Measure')
    Timefreq.Measure = lower(Timefreq.Measure);
end

%% ===== FIX OLD TIME/FREQUENCY BANDS =====
% Old structure:  {name, fstart, fend}
% New structure:  {name, 'expression', 'stat')
if isfield(Timefreq, 'Freqs') && iscell(Timefreq.Freqs) && ~isempty(Timefreq.Freqs) && ~ischar(Timefreq.Freqs{1,2})
    for iBand = 1:size(Timefreq.Freqs,1)
        Timefreq.Freqs{iBand, 2} = [num2str(Timefreq.Freqs{iBand, 2}), ', ', num2str(Timefreq.Freqs{iBand, 3})];
        Timefreq.Freqs{iBand, 3} = 'mean';
    end
end
if isfield(Timefreq, 'TimeBands') && ~isempty(Timefreq.TimeBands) && ~ischar(Timefreq.TimeBands{1,2})
    for iBand = 1:size(Timefreq.TimeBands,1)
        Timefreq.TimeBands{iBand, 2} = [num2str(Timefreq.TimeBands{iBand, 2}), ', ', num2str(Timefreq.TimeBands{iBand, 3})];
        Timefreq.TimeBands{iBand, 3} = 'mean';
    end
end

%% ===== REBUILD FULL SOURCES =====
if ismember('TF', FieldsToRead) && LoadFull && isKernel && ismember(file_gettype(Timefreq.DataFile), {'link', 'results'})
    % Get imaging kernel
    ResultsMat = in_bst_results(Timefreq.DataFile, 0, 'ImagingKernel');
    % Initialize full matrix
    TFfull = zeros(size(ResultsMat.ImagingKernel,1), size(Timefreq.TF,2), size(Timefreq.TF,3));
    % Multiply the TF values
    for i = 1:size(Timefreq.TF,3)
        TFfull(:,:,i) = ResultsMat.ImagingKernel * Timefreq.TF(:,:,i);
    end
    Timefreq.TF = TFfull;
end

%% ===== APPLY DYNAMIC ZSCORE =====
% DEPRECATED
% Check for structure integrity
if ismember('ZScore', FieldsToRead) && ~isempty(Timefreq.ZScore) && (~isfield(Timefreq.ZScore, 'mean') || ~isfield(Timefreq.ZScore, 'std') || ~isfield(Timefreq.ZScore, 'abs') || ~isfield(Timefreq.ZScore, 'baseline') || isempty(Timefreq.ZScore.abs))
    Timefreq.ZScore = [];
end
% Apply to file values
if ismember('ZScore', FieldsToRead) && ismember('TF', FieldsToRead) && ~isempty(Timefreq.ZScore) && ~isempty(Timefreq.TF)
    % Error in the case of source-based sources
    if isKernel && ~LoadFull
        error('Unsupported operation.');
    end
    Timefreq.TF = process_zscore_dynamic('Compute', Timefreq.TF, Timefreq.ZScore);
    Timefreq = rmfield(Timefreq, 'ZScore');
end

% ===== FIX TRANSPOSED TIME VECTOR =====
if isfield(Timefreq, 'Time') && (size(Timefreq.Time,1) > 1)
    Timefreq.Time = Timefreq.Time';
end

% ===== FIX TRANSPOSED ROWNAMES =====
if isfield(Timefreq, 'RowNames') && (size(Timefreq.RowNames,1) > 1)
    Timefreq.RowNames = Timefreq.RowNames';
end
if isfield(Timefreq, 'RefRowNames') && (size(Timefreq.RefRowNames,1) > 1)
    Timefreq.RefRowNames = Timefreq.RefRowNames';
end


% The COBRA Toolbox: testextractConditionSpecificModel.m
%
% Purpose:
%     - test the extractConditionSpecificModel function
%
% Authors:
%     - Loic Marx, December 2018

% save the current path
currentDir = pwd;

% initialize the test
fileDir = fileparts(which(mfilename));
cd(fileDir);

% define the solver packages to be used to run this test, can't use
% dqq/Minos for the parallel part.
solverPkgs = prepareTest('needsLP', true, 'excludeSolvers', {'dqqMinos', 'quadMinos'});

% load reference data
load('refData_extractConditionSpecificModel.mat')

% load model
model = createToyModelForLifting(true);

% create a parallel pool
try
    minWorkers = 2;
    myCluster = parcluster(parallel.defaultClusterProfile);
    % no parallel pool
    if myCluster.NumWorkers >= minWorkers
        poolobj = gcp('nocreate');  % if no pool, do not create new one.
        if isempty(poolobj)
            parpool(minWorkers);  % launch minWorkers workers
        end
    end
catch
    % No Parallel pool.
end

% Define input
threshold = 1e-6;

% generate data
modelPruned = extractConditionSpecificModel(model, threshold);

% comparison between refData and generated data
assert(isequal(modelPruned_ref, modelPruned))

% change back to the current directory
cd(currentDir);


% -  Unary minus.
%    -A negates the elements of A.
%
%    B = UMINUS(A) is called for the syntax '-A' when A is an object.
%
%    Reference page in Doc Center
%       doc uminus
%
%    Other functions named uminus
%
%       calendarDuration/uminus    fints/uminus       sym/uminus
%       codistributed/uminus       gpuArray/uminus    ts/uminus
%       duration/uminus
%


function grad = B_repmat(future_layers, curr_layer)
future_grad = GetFutureGrad(future_layers, curr_layer);

sourceDims = curr_layer.sourceDims;
% targetDims = curr_layer.targetDims;

if length(sourceDims)==1
    grad = sum(future_grad,2);
else
    % to be implemented
end

end


function diffOddEven = compute_diff_odd_even(this, varargin)
% computes difference image between first and last volume of time series
% NOTE: short-cut for compute_stat_image('diff_last_first')
%
%   Y = MrImage()
%   diffOddEven = Y.compute_diff_odd_even('PropertyName', PropertyValue)
%
% This is a method of class MrImage.
%
% IN
%   'PropertyName'
%               'selectedVolumes'       [1,nVols] vector of selected
%                                       volumes for statistical calculation
% OUT
%   diffOddEven               MrImage holding difference image between
%                               odd and even
%                               time series volume, characterizing "image
%                               noise" as in FBIRN paper (Friedman and
%                               Glover, JMRI 2006)
% EXAMPLE
%   Y = MrImage()
%   diffOddEven = Y.compute_diff_odd_even('selectedVolumes', [6:100])
%
%   See also MrImage compute_stat_image

% Author:   Saskia Bollmann & Lars Kasper
% Created:  2020-09-23
% Copyright (C) 2020 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC Toolbox, which is released
% under the terms of the GNU General Public Licence (GPL), version 3.
% You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version).
% For further details, see the file COPYING or
%  <http://www.gnu.org/licenses/>.

diffOddEven = this.compute_stat_image('diff_last_first', varargin{:});


function s = s_blank_delete ( s )

%*****************************************************************************80
%
%% S_BLANK_DELETE removes blanks from a string, left justifying the remainder.
%
%  Discussion:
%
%    All TAB characters are also removed.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 March 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string to be transformed.
%
%    Output, string S, the transformed string.
%
  TAB = 9;

  s_len = length ( s );
  s2 = '';

  put = 0;

  for get = 1 : s_len

    if ( s(get) ~= ' ' && s(get) ~= TAB )
      put = put + 1;
      s2(put) = s(get);
    end

  end

  s = s2;

  return
end


function [HDR]=bni2hdr(arg1,arg3,arg4,arg5,arg6)
% BNI2HDR converts BNI header information into BioSig Header information
%	HDR = BNI2HDR(HDR)
%
% INPUT:
%   HDR.H1 contains ascii header
%
% OUTPUT:
%   HDR.Label
%   HDR.T0
%       ...
%
% see also: SOPEN

%	$Id$
%	Copyright (c) 2007,2008 by Alois Schloegl <a.schloegl@ieee.org>
%    	This is part of the BIOSIG-toolbox http://biosig.sf.net/

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

if isstruct(arg1),
	HDR=arg1;
elseif exist(arg1,'file');
	HDR.FileName = arg1;
	[HDR.FILE.Path,HDR.FILE.Name,HDR.FILE.Ext]=fileparts(arg1);
end;
if ~isfield(HDR,'H1')
	fid = fopen(fullfile(HDR.FILE.Path,HDR.FILE.Name,'.bni'),'rt');
	HDR.H1 = char(fread(fid,[1,inf],'uint8'));
	fclose(fid);
end;

s = HDR.H1;
if ~strcmp(s(1:28),'FileFormat = BNI-1-BALTIMORE')
	fprintf(HDR.FILE.stderr,'WARNING BNI2HDR: Header information is not Nicolet BNI format.\n');
end;

while ~isempty(s),
	[t,s]=strtok(s,[10,13]);
	[t1,t2]=strtok(t,' =');
	[t2,t3]=strtok(t2,' =');
	if strcmp(t1,'PatientId')
		HDR.Patient.Id = t2;
	elseif strcmpi(t1,'Sex')
		HDR.Patient.Sex = t2; % strncmpi(t2,'m',1)+2*strncmpi(t2,'f',1);
	elseif strncmpi(t1,'medication',10)
		HDR.Patient.Medication = t2;
	elseif strncmpi(t1,'diagnosis',10)
		HDR.Patient.Diagnosis = t2;
	elseif strcmpi(t1,'MontageRaw')
		[tmp1,tmp2,HDR.Label] = str2double(t2,',');
	elseif strcmpi(t1,'Age')
		HDR.Patient.Age = str2double(t2);
	elseif strcmp(t1,'Date')
		if any(t2=='/')
			t2(t2=='/')=' ';
			HDR.T0([2,3,1])=str2double(t2);
		end;
	elseif strcmp(t1,'Time')
		t2(t2==':') = ' ';
		HDR.T0(4:6) = str2double(t2);
	elseif strcmp(t1,'Rate')
		HDR.SampleRate = str2double(t2);
	elseif strcmp(t1,'NchanFile')
		HDR.NS = str2double(t2);
	elseif strcmp(t1,'UvPerBit')
		HDR.Cal = str2double(t2);
	elseif strcmp(t1,'[Events]')
		% not supported yet
		s = [];
	end;
end;


function [Gamma,Gammasum,Xi,LL] = hsinference(data,T,hmm,residuals,options,XX,Gamma0,Xi0,cv)
%
% inference engine for HMMs.
%
% INPUT
%
% data      Observations - a struct with X (time series) and C (classes)
% T         Number of time points for each time series
% hmm       hmm data structure
% residuals in case we train on residuals, the value of those.
% XX        optionally, XX, as computed by setxx.m, can be supplied
% Gamma0    initial Gamma (only used for ehmm model)
% cv        is this called from a CV routine?
%
% OUTPUT
%
% Gamma     Probability of hidden state given the data
% Gammasum  sum of Gamma over t
% Xi        joint Prob. of child and parent states given the data
% LL        Log-likelihood, summed across time points
%
% Author: Diego Vidaurre, OHBA, University of Oxford

if length(hmm.train.embeddedlags_batched) > 1
    [Gamma,Gammasum,Xi,LL] = hsinference_batched(T,hmm,residuals,XX);
    return
end

N = length(T);
K = hmm.K;
p = hmm.train.lowrank; do_HMM_pca = (p > 0);
if nargin < 7, Gamma0 = []; end
if nargin < 8, Xi0 = []; end
if nargin < 9, cv = 0; end
if ~isfield(hmm,'train')
    if nargin<5 || isempty(options)
        error('You must specify the field options if hmm.train is missing');
    end
    hmm.train = checkoptions(options,data.X,T,0);
end
mixture_model = isfield(hmm.train,'id_mixture') && hmm.train.id_mixture;
if isfield(hmm.train,'episodic'), episodic = hmm.train.episodic;
else, episodic = 0;
end
if episodic, rangeK = 1:K+1; else, rangeK = 1:K; end
order = hmm.train.maxorder;

if iscell(data)
    data = cell2mat(data);
end
if ~isstruct(data)
    data = struct('X',data);
    data.C = NaN(size(data.X,1)-order*length(T),K);
end

if do_HMM_pca
    ndim = size(data.X,2);
elseif nargin<4 || isempty(residuals)
    ndim = size(data.X,2);
    if ~isfield(hmm.train,'Sind')
        orders = formorders(hmm.train.order,hmm.train.orderoffset,hmm.train.timelag,hmm.train.exptimelag);
        hmm.train.Sind = formindexes(orders,hmm.train.S) == 1;
        if ~hmm.train.zeromean, hmm.train.Sind = [true(1,ndim); hmm.train.Sind]; end
    end
    residuals =  getresiduals(data.X,T,hmm.train.S,hmm.train.maxorder,hmm.train.order,...
        hmm.train.orderoffset,hmm.train.timelag,hmm.train.exptimelag,hmm.train.zeromean);
else
    ndim = size(residuals,2);
end

if (episodic && ~isfield(hmm.state(1),'P')) || (~episodic && ~isfield(hmm,'P'))
    hmm = hmmhsinit(hmm);
end

if nargin<6 || isempty(XX)
    setxx;
end

if ~hmm.train.acrosstrial_constrained
    Gamma = cell(N,1);
    LL = cell(N,1);
end
Gammasum = zeros(N,K);
if ~mixture_model
    Xi = cell(N,1);
else
    Xi = [];
end

setstateoptions;
% Cache shared results for use in obslike
for k = rangeK
    %hmm.cache = struct();
    hmm.cache.train{k} = train;
    %hmm.cache.order{k} = order;
    %hmm.cache.orders{k} = orders;
    %hmm.cache.Sind{k} = Sind;
    %hmm.cache.S{k} = S;
    if do_HMM_pca
        W = hmm.state(k).W.Mu_W;
        v = hmm.Omega.Gam_rate / hmm.Omega.Gam_shape;
        C = W * W' + v * eye(ndim);
        ldetWishB = 0.5*logdet(C); PsiWish_alphasum = 0;
    elseif k == 1 && strcmp(train.covtype,'uniquediag') || strcmp(train.covtype,'shareddiag')
        ldetWishB = 0;
        PsiWish_alphasum = 0;
        for n = 1:ndim
            if ~regressed(n), continue; end
            ldetWishB = ldetWishB+0.5*log(hmm.Omega.Gam_rate(n));
            PsiWish_alphasum = PsiWish_alphasum+0.5*psi(hmm.Omega.Gam_shape);
        end
        C = hmm.Omega.Gam_shape ./ hmm.Omega.Gam_rate;
    elseif k == 1 && strcmp(train.covtype,'uniquefull') || strcmp(train.covtype,'sharedfull')
        ldetWishB = 0.5*logdet(hmm.Omega.Gam_rate(regressed,regressed));
        PsiWish_alphasum = 0;
        for n = 1:sum(regressed)
            PsiWish_alphasum = PsiWish_alphasum+psi(hmm.Omega.Gam_shape/2+0.5-n/2);
        end
        PsiWish_alphasum=PsiWish_alphasum*0.5;
        C = hmm.Omega.Gam_shape * hmm.Omega.Gam_irate;
        for kk = rangeK
            [hmm.cache.WishTrace{kk},hmm.cache.codevals] = computeWishTrace(hmm,regressed,XX,C,kk);
        end
    elseif strcmp(train.covtype,'diag')
        ldetWishB=0;
        PsiWish_alphasum = 0;
        for n = 1:ndim
            if ~regressed(n), continue; end
            ldetWishB = ldetWishB+0.5*log(hmm.state(k).Omega.Gam_rate(n));
            PsiWish_alphasum = PsiWish_alphasum+0.5*psi(hmm.state(k).Omega.Gam_shape);
        end
        C = hmm.state(k).Omega.Gam_shape ./ hmm.state(k).Omega.Gam_rate;
        if episodic, iC = hmm.state(k).Omega.Gam_rate / hmm.state(k).Omega.Gam_shape; end
    elseif strcmp(train.covtype,'full')
        ldetWishB = 0.5*logdet(hmm.state(k).Omega.Gam_rate(regressed,regressed));
        PsiWish_alphasum = 0;
        for n = 1:sum(regressed)
            PsiWish_alphasum = PsiWish_alphasum+0.5*psi(hmm.state(k).Omega.Gam_shape/2+0.5-n/2);
        end
        C = hmm.state(k).Omega.Gam_shape * hmm.state(k).Omega.Gam_irate;
        if episodic, iC = hmm.state(k).Omega.Gam_rate / hmm.state(k).Omega.Gam_shape; end
        [hmm.cache.WishTrace{k},hmm.cache.codevals] = computeWishTrace(hmm,regressed,XX,C,k);
    end
    % Set up cache
    if ~isfield(train,'distribution') || strcmp(train.distribution,'Gaussian')
        hmm.cache.ldetWishB{k} = ldetWishB;
        hmm.cache.PsiWish_alphasum{k} = PsiWish_alphasum;
        hmm.cache.C{k} = C;
        if episodic && (strcmp(train.covtype,'diag') || strcmp(train.covtype,'full'))
            hmm.cache.iC{k} = iC;
        end
    end
end

if hmm.train.acrosstrial_constrained % state probabilities are shared across trials

    ttrial = T(1)-order; L = zeros(N*ttrial,K);
    if episodic
        [Gammastar,Xistar,LL] = fb_Gamma_inference_ehmm(XX,hmm,residuals,Gamma0,Xi0,T);
    else
        for j = 1:N
            t = (1:ttrial) + (j-1)*ttrial;
            t2 = (1:ttrial+order) + (j-1)*(ttrial+order);
            try
                L(t2,:) = obslike([],hmm,residuals(t,:),XX(t,:),hmm.cache,cv);
            catch
                error('obslike function is giving trouble - Out of precision?')
            end
        end
        L = squeeze(sum(reshape(L,[ttrial+order,N,K]),2));
        if mixture_model
            Gammastar = id_Gamma_inference(L,hmm.Pi,order); Xistar = [];
        else
            [Gammastar,Xistar,LL] = fb_Gamma_inference_sub(L,hmm.P,hmm.Pi,T(1),...
                order,hmm.train.Gamma_constraint);
        end
    end
    Gamma = zeros(ttrial,N,K);
    if episodic
        Xi = zeros(ttrial-1,N,K,4);
    elseif mixture_model
        Xi = zeros(ttrial-1,N,K,K);
    end
    for t = 1:ttrial
        Gamma(t,:,:) = repmat(Gammastar(t,:),N,1);
        if t==ttrial, break; end
        if episodic
            Xi(t,:,:,:) = reshape(repmat(Xistar(t,:,:),N,1),[1,N,K,4]);
        elseif mixture_model
            Xi(t,:,:,:) = reshape(repmat(Xistar(t,:,:),N,1),[1,N,K,K]);
        end
    end
    Gamma = reshape(Gamma,ttrial*N,K);
    if episodic
        Xi = reshape(Xi,(ttrial-1)*N,K,2,2);
    elseif mixture_model
        Xi = reshape(Xi,(ttrial-1)*N,K,K);
    end

elseif hmm.train.useParallel==1 && N>1

    % to duplicate this code is really ugly but there doesn't seem to be
    % any other way - more Matlab's fault than mine

    % to avoid the entire data being copied entirely in each parfor loop
    XX_copy = cell(N,1); residuals_copy = cell(N,1);
    Gamma0_copy = cell(N,1); Xi0_copy = cell(N,1);
    C_copy = cell(N,1);
    for j = 1:N
        t0 = sum(T(1:j-1)); s0 = t0 - order*(j-1); s02 = t0 - (order+1)*(j-1);
        XX_copy{j} = XX(s0+1:s0+T(j)-order,:);
        if ~do_HMM_pca
            residuals_copy{j} = residuals(s0+1:s0+T(j)-order,:);
        end
        if isfield(data,'C')
            C_copy{j} = data.C(s0+1:s0+T(j)-order,:);
        end
        if ~isempty(Gamma0)
            Gamma0_copy{j} = Gamma0(s0+1:s0+T(j)-order,:);
        end
        if ~isempty(Xi0)
            Xi0_copy{j} = Xi(s02+1:s02+T(j)-order-1,:,:,:);
        end
    end; clear data; clear Gamma0; clear Xi0; clear XX; clear residuals

    parfor j = 1:N
        xit = []; llt = [];
        if order>0
            R = [zeros(order,size(residuals_copy{j},2)); residuals_copy{j}];
            if ~isempty(C_copy{j})
                C = [zeros(order,K); C_copy{j}];
            else
                C = NaN(size(R,1),K);
            end
        else
            if do_HMM_pca
                R = XX_copy{j};
            else
                R = residuals_copy{j};
            end
            if ~isempty(C_copy{j})
                C = C_copy{j};
            else
                C = NaN(size(R,1),K);
            end
        end
        % we jump over the fixed parts of the chain
        t = order+1;
        nsegments = computeNoSegments(T(j),t,C);
        xi = cell(nsegments,1); gamma = cell(nsegments,1);
        ll = cell(nsegments,1); ns = 1;
        while t <= T(j)
            if isnan(C(t,1)), no_c = find(~isnan(C(t:T(j),1)));
            else, no_c = find(isnan(C(t:T(j),1)));
            end
            if t>order+1
                if isempty(no_c), slicer = (t-1):T(j); %slice = (t-order-1):T(in);
                else, slicer = (t-1):(no_c(1)+t-2); %slice = (t-order-1):(no_c(1)+t-2);
                end
            else
                if isempty(no_c), slicer = t:T(j); %slice = (t-order):T(in);
                else, slicer = t:(no_c(1)+t-2); %slice = (t-order):(no_c(1)+t-2);
                end
            end
            slicepoints = slicer - order;
            XXt = XX_copy{j}(slicepoints,:);
            if isnan(C(t,1))
                if episodic
                    slicer2 = slicer(1:end-1);
                    Gamma0t = Gamma0_copy{j}(slicer,:);
                    Xi0t = []; if ~isempty(Xi0_copy{j}), Xi0t = Xi0_copy{j}(slicer2,:); end
                    [gammat,xit,llt] = fb_Gamma_inference_ehmm(XXt,hmm,R(slicer,:),Gamma0t,Xi0t);
                else
                    [gammat,xit,llt] = ...
                        fb_Gamma_inference(XXt,hmm,R(slicer,:),slicepoints,hmm.train.Gamma_constraint,cv);
                end
            else
                gammat = zeros(length(slicer),K);
                if t==order+1, gammat(1,:) = C(slicer(1),:); end
                if ~mixture_model
                    if episodic, xit = zeros(length(slicer)-1, K, 4);
                    else, xit = zeros(length(slicer)-1, K^2);
                    end
                end
                for i = 2:length(slicer)
                    gammat(i,:) = C(slicer(i),:);
                    if ~mixture_model
                        if episodic
                            for k = 1:K
                                gg = [gammat(i-1,k) (1-gammat(i-1,k))];
                                xitr = gg' * gg;
                                xit(i-1,k,:) = xitr(:)';
                            end
                        else
                            xitr = gammat(i-1,:)' * gammat(i,:) ;
                            xit(i-1,:) = xitr(:)';
                        end
                    end
                end
            end
            if t>order+1
                gammat = gammat(2:end,:);
            end
            if ~mixture_model
                xi{ns} = xit;
            end
            gamma{ns} = gammat;
            ll{ns} = llt;
            ns = ns + 1;
            if isempty(no_c), break;
            else, t = no_c(1)+t-1;
            end
        end
        Gamma{j} = cell2mat(gamma);
        Gammasum(j,:) = sum(Gamma{j});
        LL{j} = cell2mat(ll);
        if ~mixture_model
            if episodic
                Xi{j} = reshape(cell2mat(xi),T(j)-order-1,K,2,2);
            else
                Xi{j} = reshape(cell2mat(xi),T(j)-order-1,K,K);
            end
        end
    end

else

    for j = 1:N % this is exactly the same than the code above but changing parfor by for

        t0 = sum(T(1:j-1)); s0 = t0 - order*(j-1); s02 = t0 - (order+1)*(j-1);
        if order > 0
            R = [zeros(order,size(residuals,2)); residuals(s0+1:s0+T(j)-order,:)];
            if isfield(data,'C')
                C = [zeros(order,K); data.C(s0+1:s0+T(j)-order,:)];
            else
                C = NaN(size(R,1),K);
            end
        else %s0==t0
            if do_HMM_pca
                R = XX(s0+1:s0+T(j),:);
            else
                R = residuals(s0+1:s0+T(j),:);
            end
            if isfield(data,'C')
                C = data.C(s0+1:s0+T(j),:);
            else
                C = NaN(size(R,1),K);
            end
        end
        % we jump over the fixed parts of the chain
        t = order+1;
        nsegments = computeNoSegments(T(j),t,C);
        xi = cell(nsegments,1); gamma = cell(nsegments,1);
        ll = cell(nsegments,1); ns = 1;
        while t <= T(j)
            if isnan(C(t,1)), no_c = find(~isnan(C(t:T(j),1)));
            else, no_c = find(isnan(C(t:T(j),1)));
            end
            if t > order+1
                if isempty(no_c), slicer = (t-1):T(j); %slice = (t-order-1):T(in);
                else, slicer = (t-1):(no_c(1)+t-2); %slice = (t-order-1):(no_c(1)+t-2);
                end
            else
                if isempty(no_c), slicer = t:T(j); %slice = (t-order):T(in);
                else, slicer = t:(no_c(1)+t-2); %slice = (t-order):(no_c(1)+t-2);
                end
            end
            slicepoints = slicer + s0 - order;
            XXt = XX(slicepoints,:);
            if isnan(C(t,1))
                if episodic
                    slicepoints2 = slicer(1:end-1) + s02 - order;
                    Gamma0t = Gamma0(slicepoints,:);
                    Xi0t = []; if ~isempty(Xi0), Xi0t = Xi0(slicepoints2,:,:,:); end
                    [gammat,xit,llt] = ...
                        fb_Gamma_inference_ehmm(XXt,hmm,R(slicer,:),Gamma0t,Xi0t);
                else
                    [gammat,xit,llt] = ...
                        fb_Gamma_inference(XXt,hmm,R(slicer,:),slicepoints,hmm.train.Gamma_constraint,cv);
                end
                if any(isnan(gammat(:))) % this will never come up - we treat it within fb_Gamma_inference
                    error(['State time course inference returned NaN (out of precision). ' ...
                        'There are probably extreme events in the data'])
                end
            else
                gammat = zeros(length(slicer),K);
                llt = NaN(length(slicer),1);
                if t==order+1, gammat(1,:) = C(slicer(1),:); end
                if ~mixture_model
                    if episodic, xit = zeros(length(slicer)-1, K, 4);
                    else, xit = zeros(length(slicer)-1, K^2);
                    end
                end
                for i = 2:length(slicer)
                    gammat(i,:) = C(slicer(i),:);
                    if ~mixture_model
                        if episodic
                            for k = 1:K
                                gg = [gammat(i-1,k) (1-gammat(i-1,k))];
                                xitr = gg' * gg;
                                xit(i-1,k,:) = xitr(:)';
                            end
                        else
                            xitr = gammat(i-1,:)' * gammat(i,:) ;
                            xit(i-1,:) = xitr(:)';
                        end
                    end
                end
            end
            if t > order+1
                gammat = gammat(2:end,:);
            end
            if ~mixture_model
                xi{ns} = xit;
            end
            gamma{ns} = gammat;
            ll{ns} = llt;
            ns = ns + 1;
            if isempty(no_c), break;
            else, t = no_c(1)+t-1;
            end
        end
        Gamma{j} = cell2mat(gamma);
        Gammasum(j,:) = sum(Gamma{j});
        LL{j} = cell2mat(ll);
        if ~mixture_model
            if episodic
                Xi{j} = reshape(cell2mat(xi),T(j)-order-1,K,2,2);
            else
                Xi{j} = reshape(cell2mat(xi),T(j)-order-1,K,K);
            end
        end
    end

end

% join
if ~hmm.train.acrosstrial_constrained
    Gamma = cell2mat(Gamma);
    LL = cell2mat(LL);
    if ~mixture_model, Xi = cell2mat(Xi); end
end

% orthogonalise = 1;
% Gamma0 = Gamma;
% if orthogonalise && hmm.train.tuda
%     T = length(Gamma) / length(T) * ones(length(T),1);
%     Gamma = reshape(Gamma,[T(1) length(T) size(Gamma,2) ]);
%     Y = reshape(residuals(:,end),[T(1) length(T)]);
%     for t = 1:T(1)
%        y = Y(t,:)';
%        for k = 1:size(Gamma,3)
%            x = Gamma(t,:,k)';
%            b = y \ x;
%            Gamma(t,:,k) = Gamma(t,:,k) - (y * b)';
%        end
%     end
%     Gamma = reshape(Gamma,[T(1)*length(T) size(Gamma,3) ]);
%     Gamma = rdiv(Gamma,sum(Gamma,2));
%     Gamma = Gamma - min(Gamma(:));
%     Gamma = rdiv(Gamma,sum(Gamma,2));
% end

end

function nsegments = computeNoSegments(Tj,t0,C)
t = t0; nsegments = 0;
while t <= Tj
    if isnan(C(t,1)), no_c = find(~isnan(C(t:Tj,1)));
    else, no_c = find(isnan(C(t:Tj,1)));
    end
    nsegments = nsegments + 1;
    if isempty(no_c), break;
    else, t = no_c(1)+t-1;
    end
end
end


function varargout = parsef(input, format)
%parsef   parse string value using FORTRAN formatting codes
%   [val1,val2,...valn] = parsef(input, format)
%   input is string input value
%   format is cell array of format codes

global input_
input_ = input;
varargout = getvals(1, format, 1);
clear global input_
return

% this function does the work. you probably don't want to go here
function [output, idx] = getvals(idx, format, reps)
global input_
count = 1;
output = {};
for k = 1:reps
	odx = 1;
	for i = 1:length(format)
		fmt = format{i};
		switch class(fmt)
		case 'double'
			count = fmt;
		case 'char'
			type = fmt(1);
			if type == 'X'
				idx = idx+count;
			else
				[len,cnt] = sscanf(fmt,'%*c%d',1);
				if cnt ~= 1
					error(['Invalid format specifier: ''',fmt,'''']);
				end
				switch type
				case {'I','i'}
					for j = 1:count
						[val,cnt] = sscanf(input_(idx:min(idx+len-1,end)),'%d',1);
						if cnt == 1
							output{odx}(j,k) = val;
						else
							output{odx}(j,k) = NaN;
						end
						idx = idx+len;
					end
				case {'F','f'}
					for j = 1:count
						[val,cnt] = sscanf(input_(idx:min(idx+len-1,end)),'%f',1);
						if cnt == 1
							output{odx}(j,k) = val;
						else
							output{odx}(j,k) = NaN;
						end
						idx = idx+len;
					end
				case {'E','D','G'}
					for j = 1:count
						[val,cnt] = sscanf(input_(idx:min(idx+len-1,end)),'%f%*1[DdEe]%f',2);
						if cnt == 2
							output{odx}(j,k) = val(1) * 10^val(2); %#ok<AGROW>
						elseif cnt == 1
							output{odx}(j,k) = val;
						else
							output{odx}(j,k) = NaN;
						end
						idx = idx+len;
					end
				case 'A'
					for j = 1:count
						output{odx}{j,k} = input_(idx:min(idx+len-1,end));
						idx = idx+len;
					end
				otherwise
					error(['Invalid format specifier: ''',fmt,'''']);
				end
				odx = odx+1;
			end
			count = 1;
		case 'cell'
 			[val, idx] = getvals(idx, fmt, count);
			if length(val) == 1
				output(odx) = val;
			else
				output{odx} = val;
			end
			odx = odx+1;
			count = 1;
		end
	end
end
return


function tid = timerinit(par1,par2)
%TIMERINIT Initialize a new timer.
%   TID = TIMERINIT() initializes a new timer for counting elapsed time,
%   and returns its id.
%
%   TID = TIMERINIT('TIMERNAME') sets the timer name to the specified
%   string for display purposes.
%
%   TID = TIMERINIT(ITERNUM) initializes a new ETA timer for a process with
%   ITERNUM iterations. An ETA timer can be used for both counting elapsed
%   time and estimating remaining time.
%
%   TID = TIMERINIT('TIMERNAME',ITERNUM) sets the ETA timer name to the
%   specified string for display purposes.
%
%   Example:
%
%     tid = timerinit(100);
%     for i = 1:100
%       pause(0.07);
%       timereta(tid,i,1);
%     end
%     timereta(tid,i);
%
%   See also TIMERETA, TIMERCLEAR.

%  Ron Rubinstein
%  Computer Science Department
%  Technion, Haifa 32000 Israel
%  ronrubin@cs
%
%  June 2008

global utiltbx_timer_start_times    % start times
global utiltbx_time_lastdisp        % last display times
global utiltbx_timer_iternums       % iteration numbers
global utiltbx_timer_lastiter       % last queried iteration numbers
global utiltbx_timer_name           % timer names
global utiltbx_timer_callfun        % timer calling functions

% parse function arguments %

if (nargin==0)

  iternum = -1;
  timername = '';

elseif (nargin==1)

  if (ischar(par1))
    iternum = -1;
    timername = par1;

  elseif (isnumeric(par1) && numel(par1)==1 && par1>0)
    iternum = par1;
    timername = '';

  else
    error('Invalid number of iterations');
  end

elseif (nargin==2)

  if (ischar(par1) && isnumeric(par2))
    if (numel(par2)==1 && par2>0)
      timername = par1;
      iternum = par2;
    else
      error('Invalid number of iterations');
    end
  else
    error('Invalid function syntax');
  end

else
  error('Too many function parameters');
end

% register the timer %

if (isempty(utiltbx_timer_start_times))
  utiltbx_timer_start_times = clock;
  utiltbx_time_lastdisp = utiltbx_timer_start_times;
  utiltbx_timer_iternums = double(iternum);
  utiltbx_timer_lastiter = 0;
  utiltbx_timer_name = { timername };
  utiltbx_timer_callfun = {};
  tid = 1;
else
  utiltbx_timer_start_times(end+1,:) = clock;
  utiltbx_time_lastdisp(end+1,:) = utiltbx_timer_start_times(end,:);
  utiltbx_timer_iternums(end+1) = double(iternum);
  utiltbx_timer_lastiter(end+1) = 0;
  utiltbx_timer_name{end+1} = timername;
  tid = size(utiltbx_timer_start_times,1);
end

% detect timer calling function %

st = dbstack;
if (length(dbstack) >= 2)
  utiltbx_timer_callfun{end+1} = st(2).name;
else
  utiltbx_timer_callfun{end+1} = '';
end


function [] = exportInputsMustToGAMS(model, minFluxesW, maxFluxesW, constrOpt, inputFolder)
% This function export all the inputs needed to run the GAMS functions to
% find first order Must Sets (`MustU`, `MustL`). The inputs will
% be stored in inputFolder. Some inputs will be exported using GDXMRW and
% others will be exported as simple .txt files.
%
% USAGE:
%
%         exportInputsMustToGAMS(model, minFluxesW, maxFluxesW, constrOpt, inputFolder)
%
% INPUTS:
%    model:             (structure) a metabolic model with at least the
%                       following fields:
%
%                         * .rxns - Reaction IDs in the model
%                         * .mets - Metabolite IDs in the model
%                         * .S -    Stoichiometric matrix (sparse)
%                         * .b -    RHS of `Sv = b` (usually zeros)
%                         * .c -    Objective coefficients
%                         * .lb -   Lower bounds for fluxes
%                         * .ub -   Upper bounds for fluxes
%    minFluxesW:        (double array of size `n_rxns x 1`) minimum fluxes
%                       for each reaction in the model for wild-type
%                       strain. This can be obtained by running the
%                       function `FVAOptForce`. E.g.: `minFluxesW = [-90; -56];`
%    maxFluxesW:        (double array of size `n_rxns x 1`) maximum fluxes
%                       for each reaction in the model for wild-type
%                       strain. This can be obtained by running the
%                       function `FVAOptForce`. E.g.: `maxFluxesW = [90; 56];`
%    constrOpt:         (structure) structure containing additional
%                       contraints. Include here only reactions whose flux
%                       is fixed, i.e., reactions whose lower and upper
%                       bounds have the same value. Do not include here
%                       reactions whose lower and upper bounds have
%                       different values. Such contraints should be defined
%                       in the lower and upper bounds of the model. The
%                       structure has the following fields:
%
%                         * .rxnList - Reaction list (cell array)
%                         * .values -  Values for constrained reactions
%                           (double array). E.g.: `struct('rxnList', {{'EX_gluc', 'R75', 'EX_suc'}}, 'values', [-100, 0, 155.5]');`
%    inputFolder:       (string) Folder where inputs for GAMS function
%                       will be stored
%
% OUTPUTS:
%    Reactions.txt:     (file) File containing the identifiers for
%                       reactions
%    Metabolites.txt:   (file) File containing the identifiers for
%                       metabolites
%    Constrains.txt:    (file) File containing the identifiers for
%                       constrained reactions
%    MtoG.gdx:          (file) File containing the parameters which
%                       will be read by GAMS (lower bounds, upper bounds,
%                       stoichiometrix matrix `S`, minimum and maximun fluxes
%                       for each reaction in the previous step of FVA, and
%                       the values for contrained reactions)
%
% .. Author: - Sebastian Mendoza, May 30th 2017, Center for Mathematical Modeling, University of Chile, snmendoz@uc.cl

if nargin < 6 %input handling
    error('OptForce: All inputs must be specified when running exportInputsMustToGAMS')
end

%Create a temporaty folder for inputs
if ~exist(inputFolder, 'dir')
   mkdir(inputFolder);
end
current = pwd;
cd(inputFolder);

%Export Sets
exportSetToGAMS(model.rxns, 'Reactions.txt')
exportSetToGAMS(model.mets, 'Metabolites.txt')
exportSetToGAMS(constrOpt.rxnList, 'Constraints.txt')

%Export parameters
s.name = 's';
s.val = full(model.S);
s.type = 'parameter';
s.form = 'full';
s.uels = {model.mets',model.rxns'};

basemin.name = 'basemin';
basemin.val = minFluxesW;
basemin.type = 'parameter';
basemin.form = 'full';
basemin.uels = model.rxns';

basemax.name = 'basemax';
basemax.val = maxFluxesW;
basemax.type = 'parameter';
basemax.form = 'full';
basemax.uels = model.rxns';

lb.name = 'lb';
lb.val = model.lb';
lb.type = 'parameter';
lb.form = 'full';
lb.uels = model.rxns';

ub.name = 'ub';
ub.val = model.ub';
ub.type = 'parameter';
ub.form = 'full';
ub.uels = model.rxns';

b.name = 'b';
b.val = constrOpt.values;
b.type = 'parameter';
b.form = 'full';
b.uels = {'EX_gluc','R75','EX_suc'};

%Using GDXMRW to export inputs
fileName = ['MtoG' setType];
wgdx(fileName, s, basemin, basemax, lb, ub, b)

cd(current);

end


function V = volt(k, d, varargin)
%VOLT      Volterra integral operator.
%   This function is deprecated. Use OPERATORBLOCK.VOLT.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

V = linop( operatorBlock.volt(k, double(d), varargin{:}) );

end