%kkbitrshift 'Bitwise RIGHT SHIFT of Input 1 by (Input 2 or Constant) Bits'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros kbitrshift.pane file
%
% Parameters:
% InputFile: i1 'Input 1', required: 'First input data object'
% OutputFile: o 'Output', required: 'Resulting output data object'
% InputFile: i2 'Input 2', optional: 'Second input data object'
% Integer: real 'Constant', default: 0: 'Constant value'
%
% Example: o = kkbitrshift({i1, i2}, {'i1','';'o','';'i2','';'real',0})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% kbitrshift - Bitwise RIGHT SHIFT of Input 1 by (Input 2 or Constant) Bits
%
%  DESCRIPTION
% The \fBRight Shift" operator performs a bitwise right shift on each point in
% \fBInput 1" by the number of bits defined by either the corresponding
% point in \fBInput 2" or the \fBConstant\fP value, which
% ever is specified by the user.
% Zero's are shifted into the
% most significant bits, and, in effect, each data value is divided by two and the
% remainder is discarded.
%
%  "Data Type - Single Input" 5
% .cI $DATAMANIP/repos/shared/man/sections/value_type_1input
%
%  "Data Type - Two Input Objects" 5
% .cI $DATAMANIP/repos/shared/man/sections/value_type_2input
% The bitwise operators will not operate on float or complex data types.
%
%  "Map Data" 5
% The bitwise operations have not been written to be fully polymorphic yet.
% They does not
% check for map data, and will therefore always operate on the value data,
% even if a map exists.  This will most likely corrupt indexing into the map.
% In the case of a single input, it is recommended to use the "Copy to
% Value" (kcptoval) segment operator to temporarily move the map data into
% the value segment, run the bitwise operation on the data, then move it
% back to the map with the "Copy from Value" (kcpfromval) operator.
% When operating with two input objects, where at least one of the objects
% contains map data, data should be mapped prior to running the bitwise
% operator.  The "Map Data" operator (kmapdata) can be used to perform
% the mapping operation.
%
%  "Validity Mask - Single Input" 5
% .cI $DATAMANIP/repos/shared/man/sections/mask_1input
%
%  "Validity Mask - Two Input Objects" 5
% Masking has not been implemented yet for the bitwise operators.  Therefore,
% only the mask from the first input object will be transferred to the output.
%
%  "Input Objects of Different Sizes" 5
% .cI $DATAMANIP/repos/shared/man/sections/resize_2input
% The value used to pad the data when the input files are not the same size is
% zero.
%
%  "Explicit Location and Time Data - Single Input" 5
% .cI $DATAMANIP/repos/shared/man/sections/loc_and_time_1input
%
%  "Explicit Location and Time Data - Two Input Objects" 5
% The bitwise operations have not been extended to understand location and
% time data.  Therefore, only location and time data present in the first input
% object will be transferred to the output.
%
% Executing \fBRight Shift" runs the program "kbitwise\fP with the -rs flag.
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
% DATAMANIP::kbitwise
%
%  RESTRICTIONS
%
% THIS ROUTINE is still under development, and has not been modified to fully
% support the polymorphic data model.  See paragraphs above for discussions
% concerning the polymorphic data segments.
%
% All processing is currently performed as UNSIGNED long, so the operations
% may not work properly on negative values.
%
% The bitwise operators will not operate on float or complex data types.
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kkbitrshift(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kkbitrshift(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i1', '__input';'o', '__output';'i2', '__input';'real', 0};
maxval={0,0,1,0};
minval={0,0,1,0};
istoggle=[0,0,1,1];
was_set=istoggle * 0;
paramtype={'InputFile','OutputFile','InputFile','Integer'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'kbitwise"  -rs'],Inputs,narglist);


function [d,a] =  training(a,d)

  for i=1:length(a.child)
    [d a.child{i}]=train(a.child{i},d);
    if i<length(a.child) & (isa(a.child{i},'group') | isa(a.child{i},'param'))
      a.child{i}.group='one_for_each';
    end;
   end


% This script compiles Matlab's MEX interfaces for LIBQP solvers.
%

mex libqp_splx_mex.c -largeArrayDims ../lib/libqp_splx.c
mex libqp_gsmo_mex.c -largeArrayDims ../lib/libqp_gsmo.c


function [  ] = convert2vid( vid_data, varargin )
%convert2vid - converts the video structure, as created by sie2mat.exe,
%and converts it to a video.
% Program is not optimised, but requires no video processing toolbox
%   Syntax
%       convert2vid( vid_data )  - returns a SIE_DATA structure with data from
%                               the sie file as defined in sie_flnme
%       convert2vid( vid_data, 'path', path_str )  -  path_str defines
%                               the location where the video is saved.
%                               Default - current folder
%       convert2vid( vid_data, 'video_name', video_name_str )  -  video_name
%                               changes the name of the output video
%                               Default - 'SIE_VIDEO'
%       convert2vid( vid_data, 'profile', profile_str )  -  profile
%                               String enclosed in single quotation marks that describes
%                               the type of file to create. Specifying a profile sets default
%                               values for video properties such as VideoCompressionMethod.
%                               Possible values:
%                                     'Archival' - Motion JPEG 2000 file with lossless compression
%                                     'Motion JPEG AVI' - Compressed AVI file using Motion JPEG codec
%                                     'Motion JPEG 2000' - Compressed Motion JPEG 2000 file
%                                     'MPEG-4' - Compressed MPEG-4 file with H.264 encoding (Windows 7 systems only)
%                                     'Uncompressed AVI' - Uncompressed AVI file with RGB24 video
%                               Default: 'Motion JPEG AVI'
%       convert2vid( vid_data, 'framerate', FrameRate_int )  - FrameRate
%                               Rate of playback for the video in frames per second.
%                               Default: 30
%
% convert2vid.m
% Created by: MJ Stallmann
% Last modified: 02/08/2013

%% Start sie2mat
% get options
[options] = parseOptions( varargin{:});
[pathstr, name, ext] = fileparts(options.video_name) ;
vid_name=fullfile(options.path,name,'.avi');
writerObj = VideoWriter(vid_name,options.profile);
writerObj.FrameRate=options.framerate;
open(writerObj);
nframes=length(vid_data);
disp('Processing frames.... Please wait...')
for k = 1:nframes
    fid = fopen('temp.jpg', 'w');
    fwrite(fid, vid_data(k).Video_data, 'uint8');
    fclose(fid);
    frame = imread('temp.jpg');
    writeVideo(writerObj,frame);
end

close(writerObj);
delete('temp.jpg');
end

%% Set options
function options = parseOptions(varargin)
IP = inputParser;
IP.addParamValue('path', pwd, @ischar)
IP.addParamValue('video_name','SIE_VIDEO', @ischar)
IP.addParamValue('profile','Motion JPEG AVI', @ischar)
IP.addParamValue('framerate',30, @isnumeric)
IP.parse(varargin{:});
options = IP.Results;
end


function wms=links2wms(links);
% LINKS2WMS extract WMS Data URLs from OpenSearch links
% Usage: wms=links2wms(links);
%    [links,struc]=opensearch(q);
%    wms=links2wms(links);
% Example WMS GetCapabilities request:
%    url=[wms{i} '?service=WMS&version=1.3.0&request=GetCapabilities'];
% Rich Signell (rsignell@usgs.gov)
k=0;
wms=[];
for i=1:length(links)
    s=char(links{i});
    if ~isempty(regexpi(s,'wms')),
        k=k+1;
        wms{k}=s;
    end
end


function r = parse_formula(varargin)

% PARSE_FORMULA Parses a chemical formula to form an atomic representation.
%
% SYNTAX
%
% r = parse_formula(str)
% r = parse_formula({str1,str2,str3, ...})
%
%   Parses chemical formulas and returns a structure array holding the an
%   atomic representation of the chemical forulas. The input is a string or
%   a cell array of strings.
%
%
% EXAMPLES
%
%   1. Chemical formulas of varying complexity
%
%       parse_formula('H2O');            % Water
%       parse_formula('NaHCO3');         % Sodium Bicarbonate
%       parse_formula('(CH4)8(H2O)46');  % Methane Clathrate
%       parse_formula('CH3COOCH2CH3');   % Ethyl Acetate
%       parse_formula('MnO4-');          % Negative Charge Ion
%
%       parse_formula('dCH4');           % Returns error message
%
%   2. Create an structure array of atomic representations for a set of
%      compounds
%
%       r = parse_formula({'CH4','O2','CO2','H2O'});
%
%
% USAGE NOTES
%
%   1. Formulas are made of up of sequences of elements followed by
%      integers  indicating the number of included atoms. Omitted integers
%      are assumed to be one.
%
%   2. Elements are the conventional one or two character abbreviations.
%      The character is captialized. If present, the second character is
%      lower case. In addition to the standard elements, the parser allows
%      for
%
%       Symbol  Entity                 Interpretation
%          e    electron               like an element with MW = 0
%          D    deuterium              an element
%          T    tritium                an element
%          M    any metal              like an element, mw = NaN
%          X    any halogen            like an element, mw = NaN
%          Me   methyl group (CH3)     CH3 substituted for Me
%          Et   ethyl group (C2H5)     C2H5 substituted for Et
%          Bu   butyl group (C4H9)     C4H9 substituted for Bu
%          Ph   phenol group (C6H5)    C6H5 substituted for Ph
%
%   3. Subgroups may be included between parenthesis or brackets followed
%      by an integer indicating number of repetitions. Two levels of
%      subgrouping are allowed.
%
%   4. A terminal lower case suffix denoting phases will be correctly
%      parsed. The phase must be one of (aq), (l), (g), or (s).
%
%   5. The charge on an ionic species is appended as a + or - followed by
%      an optional integer.  Examples are H+, OH-, or Ca+2.
%
%   6. The bare electron e- is used in balancing chemical half reactions.
%
%   7. Error messages are generated for invalid fomulas
%      Change for use with the cobra toolbox
%      A is accepted as the symbol for an element that could
%      represent an R group in an atom mapping scenario for an incompletely
%      defined metabolite.
%
%   8. str can be a cell array of chemical formula. The results is a
%      structure array. The elements of the output structure array are in
%      one-to-one correspondence with elements of the cell array. For
%      example
%
%          r = parse_formula({'CH4','CH3OH','CHOOH'})
%
%      r(1) holds the atomic formula for CH4, r(2) for CH3OH, and r(3) for
%      CHOOH.

% AUTHOR
%
%   Jeff Kantor
%   December 18, 2010

    assert(nargin > 0, 'parse_formula:input', ['No input. Expects a  ', ...
                        'string or cell array of chemical formulas.']);
    assert(nargin < 2, 'stoich:input', 'Unexpected extra inputs.');

    switch class(varargin{1})
        case 'char'                      % Single formula
            str = varargin;

        case 'cell'                      % Cell array of formulas
            str = varargin{1};

        otherwise
            error('parse_formula:input',['requires cell array of  ',...
              'chemical formulas.']);
    end

    assert(iscellstr(str), 'parse_formula:input', ...
        'Formulas must be strings.');

    % Trim any whitespace at front or back

    str = strtrim(str);

    % Remove phase information. This information is currently neglected. In
    % a later version we may wish to incorporate phase into a more complete
    % data structure for representing chemical formula.

    prex = '|\((aq|g|l|s)\)$';
    str = regexprep(str,prex,'');

    % Substitute for some common chemical abbreviations

    str = regexprep(str,'Bu','C4H9');    % Butyl
    str = regexprep(str,'Et','C2H5');    % Ethyl
    str = regexprep(str,'Me','CH3');     % Methyl
    str = regexprep(str,'Ph','C6H5');    % Phenol

    % Apply the main parser to every element of str

    q = cellfun(@(s)parse_formula_(s,3),str,'Uniform',false);

    % Union of all atomic species

    atoms = {};
    for i = 1:length(q(:))
        atoms = union(atoms, fields(q{i}));
    end

    % Add all atomic species to all structures.

    for i = 1:length(q(:))
        for j = 1:length(atoms)
            if ~ismember(atoms{j},fields(q{i}))
                q{i}.(atoms{j}) = 0;
            end
        end
    end

    % Form the structure array to have the same shape as str

    r = reshape([q{:}],size(str));

end % parse_formula

function r = parse_formula_(str,kdepth)

    assert(kdepth > 0, 'parse_formula_:Recursion', ...
        'Reached maximum recursion depth');

    r = struct([]);

    % Regular expression returning tokens for element and number
    % sexpr matches single elements followed by a digit, or a +/-
    % followed by a digit to denote charge

    persistent srex;  % Regexp pattern to match elements and charges
    persistent grex;  % Regexp pattern to match groups

    if isempty(srex) || isempty(grex)
        %this was the original line
        %srex = ['(A[lrsgutcm]|B[eraik]?|C[laroudsemf]?|D[y]?|E[urs]|',...
        srex = ['(A[lrsgutcm]?|B[eraik]?|C[laroudsemf]?|D[y]?|E[urs]|', ...
                'F[erm]?|G[aed]|H[eofgas]?|I[nr]?|Kr?|L[iaur]|', ...
                'M[gnodt]?|N[eaibdpos]?|Os?|P[drmtboau]?|R[buhenaf]|', ...
                'S[icernbmg]?|T[icebmalh]?|U|V|W|X[e]?|Yb?|Z[nr])', ...
                '(\d*\.\d+|\d*)', ...
                '|(e|+|-)(\d*)'];
        grex = '|\(([^\)]*)\)(\d*\.\d+|\d*)|\[([^\]]*)\](\d*\.\d+|\d*)';
    end

    % Parse formula for chemical groups. This picks out anything that looks
    % an element followed by a number, or a subgroup within parentheses.
    % The tokens are returned in the cell array u. Each u{k} has two
    % elements, the first is a string denoting the group, and the second is
    % number string of repetitions.

    [u,s,e] = regexp(str,[srex,grex],'tokens','start','end');

    % Report any parsing errors. A parse error occurs if there are any
    % characters not matched as tokens. We scan the start and end positions
    % of the tokens to determine if there are any gaps.

    g(1:length(str)) = '^';
    for i = 1:length(s);
        g(s(i):e(i)) = ' ';
    end

    assert(all(g ~= '^'), 'parse_formula:ParseError', ...
        'Could not parse formula:\n    %s\n    %s\n', str, char(g));

    % Extract atom tokens from the first part of each token

    tok = cellfun(@(v)v{1},u,'Uni',false);

    % Extract counts from the second part of each token, convert to
    % doubles, empty counts set to 1

    cnt = cellfun(@(v)v{2},u,'Uni',false);
    cnt = str2double(cnt);
    cnt(isnan(cnt)) = 1;

    % Loop over tokens

    for j = 1:length(u)

        % See if token matches an element

        if strcmp(tok{j},regexp(tok{j},srex,'match'))

            % The token exactly matches an element.
            % Change + or - tokens to 'Q'.

            tok{j} = regexprep(tok{j},'+','Q');

            if strcmp(tok{j}, '-')
                tok{j} = 'Q';
                cnt(j) = -cnt(j);
            end

            % Update atomic representation, adding a field if needed.

            if isfield(r,tok{j})
                r.(tok{j}) = r.(tok{j}) + cnt(j);
            else
                r(1).(tok{j}) = cnt(j);
            end

        else

            % The token must be a group, so do a recursion to find
            % an atomic represenation of the group.

            q = parse_formula_(tok{j},kdepth-1);

            % Updatethe  atomic representation to include the group.
            % Add fields if needed. Multiply by number of groups in the
            % formula we're parsing.

            f = fields(q);

            for k = 1:length(f)

                if isfield(r,f{k})
                    r.(f{k}) = r.(f{k}) + cnt(j)*q.(f{k});
                else
                    r(1).(f{k}) = cnt(j)*q.(f{k});
                end

            end
        end
    end

end % parse_formula_


function test_fileformat_asa

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY ft_read_sens ft_read_headmodel ft_read_headshape ft_read_mri read_asa read_asa_dip	read_asa_mri read_asa_vol read_asa_bnd read_asa_elc read_asa_msr

elcfile  = dccnpath('/home/common/matlab/fieldtrip/data/test/original/electrodes/asa/standard_primed.elc');
volfile  = dccnpath('/home/common/matlab/fieldtrip/data/test/original/headmodel/asa/standard.vol');
skinfile = dccnpath('/home/common/matlab/fieldtrip/data/test/original/headshape/asa/standard_skin_14038.vol');
mrifile  = dccnpath('/home/common/matlab/fieldtrip/data/test/original/mri/asa/standard.mri');

elec = ft_read_sens(elcfile);
vol  = ft_read_headmodel(volfile);
skin = ft_read_headshape(skinfile);
mri  = ft_read_mri(mrifile);


function conf = SFS_config()
%SFS_CONFIG returns a struct with the default configuration settings
%
%   Usage: conf = SFS_config
%
%   Output parameters:
%       conf    - struct containing all configuration variables
%
%   SFS_CONFIG() creates the struct conf containing the default
%   configuration values. If you want to create other entries, please set
%   them in your script (e.g. conf.fs = 48000) and pass the conf struct to
%   the desired function as last input (e.g. tapering_window(x0,conf)).
%
%   Please don't edit this function to change your configuration settings!
%
%   See also: SFS_start

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Checking of input  parameters ===================================
nargmin = 0;
nargmax = 0;
narginchk(nargmin,nargmax);

%% ===== Table of Contents ===============================================
%
% - Misc
% - Audio
% - Delayline
% - Sound Field Synthesis (SFS)
%   * Dimensionality
%   * Driving functions
%   * Impulse responses
%   * 2.5D
%   * Tapering
% - Sound Field Simulations
% - Secondary Sources
% - Wave Field Synthesis (WFS)
%   * Pre-equalization
% - Spectral Division Method (SDM)
% - Near-Field Compensated Higher Order Ambisonics (NFC-HOA)
% - Local Sound Field Synthesis (LSFS)
% - Binaural Reproduction
%   * Headphone compensation
%   * SoundScape Renderer
% - Plotting
% - References

%% ===== Misc ============================================================
conf.tmpdir = '/tmp/sfs'; % string
% Debugging level. We are supporting two levels:
%   0 - normal mode
%   1 - debug modus, showing interim results and plots
conf.debug = 0; % 0 or 1
% Show a progress bar in selected loops (for example sound_field_mono). This can
% be useful, if you are using a high number of secondary sources.
conf.showprogress = false; % boolean

%% ===== Audio ===========================================================
% Audio and signal processing settings
%
% Samplingrate
conf.fs = 44100; % / Hz
% Speed of sound
conf.c = 343; % / m/s

%% ===== Delayline =======================================================
% Delaying of time signals. This can be critical as very often the wanted delays
% are given as fractions of samples. This configuration section handles how
% those delays should be handled. Beside choosing the actual delayline filter,
% the signal can also be resampled before delaying. As the default setting,
% integer only delays are used by rounding to the next larger integer delay.
% If you want to use a fractional delayline, a setting with a high accuracy is:
%   conf.delayline.resampling = 'pm';
%   conf.delayline.resamplingfactor = 8;
%   conf.delayline.resamplingorder = 64;
%   conf.delayline.filter = 'lagrange';
%   conf.delayline.filterorder = 9;
% Note, that the necessary interpolation accuracy highly depends on the
% actual use case and parametrisation, compare Winter and Spors (2016).
%
% Delayline filter
%   'integer'       - round to nearest integer delay (default)
%   'zoh'           - round to next larger integer delay
%   'lagrange'      - lagrange interpolator (FIR Filter)
%   'least_squares' - least squares FIR interpolation filter
%   'thiran'        - Thiran's allpass IIR filter
%   'farrow'        - use the Farrow structure (to be implemented)
conf.delayline.filter = 'integer';  % string
% Resample signal
%   'none'   - no resampling (default)
%   'matlab' - use matlab's resample() function
%   'pm'     - use Parks-McClellan-Method to compute resample filter (firpm)
conf.delayline.resampling = 'none'; % / string
% Oversamplingfactor factor >= 1
% This should be in the order of (1/stepsize of fractional delays)
conf.delayline.resamplingfactor = 100; % / 1
% Order of Parks-McClellan resample filter (only for 'pm')
% This results in a filter length of resamplingfactor*resamplingorder
conf.delayline.resamplingorder = 64;
% Order of delayline filter (only for Lagrange, Least-Squares & Thiran)
conf.delayline.filterorder = 0;  % / 1
% Number of parallel filters in Farrow structure
% (only for 'farrow');
conf.delayline.filternumber = 1; % / 1

%% ===== Sound Field Synthesis (SFS) =====================================
% Common sound field synthesis settings
%
% === Dimensionality ===
% Dimensionality of the secondary sources and the sound field synthesis driving
% functions:
% '2D'    - line sources as secondary sources, arranged in a circle, line, ...
% '2.5D'  - point sources as secondary sources, arranged in a circle, line, ...
% '3D'    - point sources as secondary sources, arranged in a sphere, plane, ...
conf.dimension = '2.5D'; % string
%
% === Driving functions ===
% Implementation of driving functions. For the default ones use 'default'. These
% functions are described at https://sfs.readthedocs.io/. For possible other
% flags have a look into the driving functions as they can be quite specific.
% Most users can safely use the 'default' flag here.
conf.driving_functions = 'default'; % string
%
% === Impulse responses ===
% Length of impulse responses used in the time domain driving functions
% and for the creation of the binaural simulations.
% Don't worry, SFS checks for you if conf.N is large enough.
conf.N = 2048; % samples
%
% === 2.5D ===
% The amplitude will be correct at the point xref for 2.5D
% synthesis.
conf.xref = [0 0 0]; % / m
%
% === Tapering ===
% The truncation of the loudspeaker array leads to diffraction of the
% synthesized sound field. It has been shown that the truncation can be
% described by cylindrical waves originating from the edges of the array, see
% Sect. 8.3.2 in Born, Wolf (1999) for the general principle and Sect. 3.2 in
% Wierstorf (2014) for how it relates to WFS. Therefore a good method to reduce
% artifacts due to the diffraction edge waves is to fade out the amplitude of
% the driving function at the edges of the array. This method is called tapering
% and implemented using a Hann window in the SFS Toolbox.
conf.usetapwin = true; % boolean
% Size of the tapering window
conf.tapwinlen = 0.3; % / percent of array length, 0..1
%
% === Time Domain Implementation ===
% Adjust the starting time in time domain driving functions.
% This can be set to
%   'system'   - the first secondary source will be active at t=0
%   'source'   - the virtual source will be active at t=0
% Setting it to 'system' is most convenient when simulating single sources as
% you will always see activity in the sound field for t>0. Setting it to
% 'source' helps you to simulate different sources as you can time align them
% easily. Note, that for virtual sources outside of the array this can mean you
% will see no activity inside the listening area until the time has passed, that
% the virtual source needs from its position until the nearest secondary source.
% Also note, using 'source' for systems with unbounded listening areas -- e.g.
% linear arrays -- focussed virtual sources may not be placed arbitrarily
% far from the secondary sources.
conf.t0 = 'system'; % string
% Bandpass filter applied in sound_field_imp()
conf.usebandpass = false; % boolean
conf.bandpassflow = 10; % / Hz
conf.bandpassfhigh = 20000; % / Hz
%
% === Modal Weighting ===
% Additional weighting of the modal coefficients by window function used
% for Near-Field Compensated Higher Order Ambisonics (NFC-HOA) and Local Sound
% Field Synthesis using Spatial Bandwidth Limitation (LSFS-SBL).
%
% Window type. Available windows are:
%   'rect'                     - all coefficients are weighted by 1.0
%   'max-rE'                   - 2D max-rE weighting
%   'kaiser', 'kaiser-bessel'  - Kaiser aka. Kaiser-Bessel window
%   'tukey'                    - modified Tukey (tapered cosine) window
conf.modal_window = 'rect';  % string
% Scalar parameter for window, if applicable. Effect for distinct window:
%   'rect'    - no effect
%   'max-rE'  - no effect
%   'kaiser'  - [0,inf]. trade-off between main-lobe width and side-lobe levels.
%               0.0 results in the rectangular window and the smallest main-lobe
%               width. infinity results in a dirac impulse.
%   'tukey'   - [0,1]. width of cosine tapering relative to the modal order.
%               0.0 results in the rectangular window, 1.0 results in a modified
%               Hann-window
conf.modal_window_parameter = 0.0;  % float

%% ===== Sound Field Simulations =========================================
% Simulations of monochromatic or time domain sound field
%
% xyz-resolution for sound field simulations, this value is applied along every
% desired dimension, except if only one point is desired
conf.resolution = 300; % / samples
% Phase of omega of sound field (change this value to create monochromatic sound
% fields with different phases, for example this can be useful to create a movie)
conf.phase = 0; % / rad

% ===== Secondary Sources ================================================
% Settings of the used loudspeaker array
%
% Number of secondary sources
conf.secondary_sources.number = 64; % integer
% Diameter/Length of secondary source array
conf.secondary_sources.size = 3; % / m
% Center of array, X0
conf.secondary_sources.center = [0 0 0]; % / m
% Array geometry
% Possible values are: 'line', 'box', 'rounded-box', 'circle', 'sphere', 'custom'
conf.secondary_sources.geometry = 'circle'; % string
% Exclusive for 'rounded-box' array geometry. Defines the bending radius for
% the corners of the smoothed box
conf.secondary_sources.corner_radius = 0.0; % / m
% Vector containing custom secondary source positions and directions.
% This is used if geometry = 'custom' is specified.
% conf.secondary_sources.x0 = [x0; y0; z0; nx0; ny0; nz0; weight];
% Or it could also be a SOFA struct or file name, in this case the positions are
% extracted from the provided SOFA file.
conf.secondary_sources.x0 = []; % / m
% For spherical arrays, available grids are:
%   'equally_spaced_points' - Sphere with equal distance between grid points
%   'gauss'                 - Gauss grid
%   'fabian'                - grid of 3D HRTF measurement, available at
%                             https://doi.org/10.14279/depositonce-5718
%
% Note, that 'equally_spaced_points' and 'fabian' are precomputed grids that
% will be automatically downloaded and cached on your disk. All available number
% of secondary sources for those grids can be seen at:
% https://github.com/sfstoolbox/data/tree/master/spherical_grids
% An exception are Gauss grids, which are available via 'gauss' and will be
% calculated on the fly allowing very high number of secondary sources.
conf.secondary_sources.grid = 'equally_spaced_points'; % string
% Grid for linear arrays: Allows for logarithmically spaced arrays. It defines
% the ratio of the spacing of the loudspeakers at the extremities of the array
% and the spacing of the loudspeakers at the center of the array. 1.0 for
% equi-distant sampling.
conf.secondary_sources.logspread = 1.0; % float

%% ===== Wave Field Synthesis (WFS) ======================================
% Settings for WFS, see Spors et al. (2008) for an introduction
%
% === Pre-Equalization ===
% WFS can be implemented very efficiently using a delay-line with different
% amplitudes and convolving the whole signal once with the so called
% pre-equalization filter, see Spors and Ahrens (2010a).
% Use WFS preequalization-filter
conf.wfs.usehpre = true; % boolean
% FIR or IIR pre-equalization filter
% NOTE: only FIR is working under octave at the moment
conf.wfs.hpretype = 'FIR'; % 'FIR' or 'IIR'
% Lower frequency limit of preequalization filter
% If we have a finite length (<10m) of the secondary source distribution we
% will have a 3dB increase at the very low frequencies and the pre-equalization
% filter should only start above those frequencies, see Sect. 7.2 in Spors and
% Ahrens (2010b).
conf.wfs.hpreflow = 50; % / Hz
% Upper frequency limit of preequalization filter
% If we have aliasing in our system we only want to use
% the pre-equalization filter until the aliasing frequency, because of the
% energy the aliasing is adding to the spectrum above this frequency, see
% Sect. 6.3 in Spors and Ahrens (2010a).
conf.wfs.hprefhigh = 1200; % / Hz
% IIR bandwidth for the Lagrange interpolation region
conf.wfs.hpreBandwidth_in_Oct = 2; % / octaves
% desired IIR filter order
conf.wfs.hpreIIRorder = 4; % integer
% desired FIR filter order, results in N+1 taps
conf.wfs.hpreFIRorder = 128; % even integer

%% ===== Spectral Division Method (SDM) ==================================
% Settings for SDM, see Ahrens and Spors (2010) for an introduction
%
% Use the evanescent part of the driving function for SDM
conf.sdm.withev = true; % boolean

%% ===== Near-Field Compensated Higher Order Ambisonics (NFC-HOA) ========
% Settings for NFC-HOA, see Ahrens (2012) for an introduction
%
% Highest order used with NFC-HOA. If this is set to [], band-limited NFC-HOA is
% used and the order is set by nfchoa_order() which returns the highest order
% for which no aliasing occurs.
conf.nfchoa.order = []; % integer

%% ===== Local Wave Field Synthesis (LWFS) ===============================
% Settings for Local WFS
%
% === Local Wave Field Synthesis using Virtual Secondary Sources (LWFS-VSS)
% See Spors and Ahrens (2010b) for an introduction.
%
% Method the virtual secondary sources should be driven
conf.localwfs_vss.method = 'wfs'; % 'wfs' or 'nfchoa'
% WFS settings for virtual secondary sources
conf.localwfs_vss.wfs = conf.wfs;
% Tapering of virtual secondary sources (only applied for WFS)
conf.localwfs_vss.usetapwin = false; % boolean
conf.localwfs_vss.tapwinlen = 0.5; % 0..1
% NFC-HOA settings for virtual secondary sources
conf.localwfs_vss.nfchoa = conf.nfchoa;
% Virtual secondary sources (see also: conf.secondary_sources)
conf.localwfs_vss.size = 0.4; % / m
conf.localwfs_vss.center = [0, 0, 0]; % / m
conf.localwfs_vss.geometry = 'circular'; % string
conf.localwfs_vss.number = 56; % integer
conf.localwfs_vss.grid = 'equally_spaced_points'; % string
% Driving function for virtual secondary sources
conf.localwfs_vss.driving_functions = 'default'; % string
% Linear VSS distribution: rotate the distribution orthogonal to the progation
% direction of the desired sound source.
% Circular VSS distribution: truncate the distribution to a circular arc
% which satisfies the secondary source selection criterions (source normal
% aligns with propagation directions of desired sound source).
conf.localwfs_vss.consider_target_field = true; % boolean
% VSS distribution is further truncated if parts of it cannot be correctly
% reproduced, because they lie outside the area which is surrounded by the real
% loudspeakers (secondary sources)
conf.localwfs_vss.consider_secondary_sources = true; % boolean
%
% === Local Wave Field Synthesis using Spatial Bandwidth Limitation (LWFS-SBL)
% See Hahn et al. (2016) for an introduction.
% The centre of the local synthesis region is set by conf.xref
%
% Maximum modal order aka. spatial bandwidth of desired sound field. If left
% empty, the value is set by nfchoa_order(), which may suboptimal depending on
% the geometry, e.g. number of secondary sources and shape of the secondary
% source distribution.
conf.localwfs_sbl.order = []; % integer
% Due to stability issues for the time-domain implementation of synthesis
% of a point source, conventional WFS has to be used for the low frequencies.
% fc defines the crossover frequency between the WFS and LWFS-SBL. If left
% empty, this frequency is estimated by aliasing_frequency().
conf.localwfs_sbl.fc = []; % float
% The spatially bandwidth-limited sound field is converted into plane wave
% decomposition which is then synthesised using conventional WFS for each
% individual plane wave. Npw defines the number of plane waves with their
% directions distributed equi-angularly on the unit circle. If left empty,
% it is estimated based on the sampling frequency and size of the secondary
% source distribution.
conf.localwfs_sbl.Npw = []; % integer

%% ===== Binaural reproduction ===========================================
% Settings regarding all the stuff with impulse responses from the SFS_ir and
% SFS_binaural_synthesis folders
%
% Use interpolation to get the desired HRTF or BRIR for binaural simulation.
% If this is disabled, the HRTF/BRIR returned by a nearest neighbour search is
% used instead.
conf.ir.useinterpolation = true; % boolean
% You can choose the way the points for interpolation are selected. Depending on
% the geometry of the measured HRTF/BRIR data set and the interpolation method,
% a different number of HRTFs are selected for interpolation. See validation
% script test_interpolation_point_selection.m for examples. Available methods:
%   'nearestneighbour'  - Interpolation between nearest neighbours. This only
%                         works for interpolation points on a circle in the
%                         horizontal plane.
%   'delaunay'          - Interpolation between surrounding points according to
%                         Delaunay triangulation. This only works for
%                         interpolation points on a sphere.
%   'voronoi'           - For spherical Voronoi interpolation, all coordinates
%                         are projected on the unit sphere. Voronoi regions
%                         (including their area) on the sphere are calculated
%                         for all measured positions included in the HRTF/BRIR
%                         data set. The query position is added to the point
%                         cloud and the regions are calculated, again.
%                         The weights result from the area "stolen" by the query
%                         position from each of the other coordinates
conf.ir.interpolationpointselection = 'nearestneighbour';
% You can choose between the following interpolation methods:
%   'simple'      - Interpolation in the time domain performed samplewise. This
%                   does not heed the times of arrival of the impulse responses.
%   'freqdomain'  - Interpolation in the frequency domain performed separately
%                   for magnitude and phase.
%                   This method cannot work properly if there is too much noise in
%                   the phase information at low frequencies which is often the
%                   case for measured HRTFs. Low frequencies can be corrected
%                   according to theory, see e.g. the corrected KEMAR HRTFs published
%                   at https://github.com/spatialaudio/lf-corrected-kemar-hrtfs.
%                   The implementation of this method suffers from circular shifting,
%                   see test_interpolation_methods.m in the validation folder. For
%                   typical HRIRs with leading and trailing zeros, the error is
%                   negligible.
%   'timedomain'  - Interpolation in the time domain with cross-correlation for
%                   estimation of time of arrival (TOA) differences.
conf.ir.interpolationmethod = 'simple';
%
% If you have HRIRs in the form of the SimpleFreeFieldHRIR SOFA convention, zeros
% are padded at the beginning of every impulse response corresponding to their
% measurement distance. If you know that your measured HRIRs already have a
% given pre-delay, add the pre-delay here and accordingly less zero padding will
% be applied. In this case you can lose samples from the beginning of the
% impulse response. If you are not sure, choose a value of 0.
conf.ir.hrirpredelay = 0; % / samples
%
% === Headphone compensation ===
% Headphone compensation
conf.ir.usehcomp = false; % boolean
% Headphone compensation file for left and right ear.
conf.ir.hcompfile = 'data/headphone_compensation/QU_KEMAR_AKGK601_hcomp.wav'; % string
%
% === SoundScape Renderer ===
% To use a dynamic binaural simulation together with the SoundScape Renderer
% (SSR) and a headtracker, brs sets can be created. If these sets should be
% used in BRS mode of the SSR, the angles have to be:
% conf.ir.brsangles = 0:1:359;
% If the brs set should be used as IRs for the SSR, the angles have to be:
% conf.ir.brsangles = 360:-1:1;
conf.ir.brsangles = 0:1:359; % / degree

%% ===== Plotting ========================================================
% Plot the results (sound fields etc.) directly
conf.plot.useplot = false; % boolean
% Normalize the sound field for plotting
conf.plot.usenormalisation = true; % boolean
% Normalisation method. Available methods are:
%   'auto'      - 'center' if center of sound field > 0.3, otherwise 'max'
%   'center'    - center of sound field == 1
%   'max'       - max of sound field == 1
conf.plot.normalisation = 'auto'; % string
% Plot mode (uses the GraphDefaults function). Available modes are:
%   'monitor'   - displays the plot on the monitor
%   'paper'     - eps output in conf.plot.outfile
%   'png'       - png output in conf.plot.outfile
conf.plot.mode = 'monitor'; % string
% Plot amplitudes in dB (e.g. sound field plots)
conf.plot.usedb = false; % boolean
% caxis settings (leave blank, if you would use the default values of the given
% plot function)
conf.plot.caxis = []; % [min max]
% Default colormap to use
% The Toolbox comes with two own color maps, if you set 'default' or 'moreland'
% you will get a blue/red-colormap after
% http://www.kennethmoreland.com/color-advice/
% If you set 'gray' or 'grey' you will get a colormap ranging from white to
% black. In addition you can add every other map you can specify in
% Matlab/Octave. For example to get the Matlab default colormap set 'parula'.
conf.plot.colormap = 'default'; % string
% Plot loudspeakers in the sound field plots
conf.plot.loudspeakers = true; % boolean
% Use real loudspeakers symbols (otherwise crosses are used)
conf.plot.realloudspeakers = false; % boolean
% Size of the loudspeaker
conf.plot.lssize = 0.16; % m
% Size of the plot
conf.plot.size_unit = 'px'; % 'px','cm','inches'
conf.plot.size = [540 404]; % [xsize ysize]
% Resolution of plot in dpi
conf.plot.resolution = 150; % integer
% Additional plot command
conf.plot.cmd = ''; % string
% output of plot (file or screen)
conf.plot.usefile = false; % boolean
% File name, if this is provided with as *.png or *.eps file, the figure is
% plotted to the regarding file
conf.plot.file = ''; % string

%% ===== References ======================================================
%
% Ahrens (2012) - "Analytic Methods of Sound Field Synthesis", Springer,
% https://doi.org/10.1007/978-3-642-25743-8
%
% Ahrens and Spors (2010) - "Sound Field Reproduction Using Planar and Linear
% Arrays of Loudspeakers", Transactions on Audio, Speech, and Language
% Processing, vol. 18, no. 8, pp. 2038-2050,
% https://doi.org/10.1109/TASL.2010.2041106
%
% Born and Wolf (1999) - "Principles of Optics", Cambridge University Press,
% 7th edition, ISBN 9780521642224
%
% Hahn, Winter, Spors (2016) - "Local Wave Field Synthesis by Spatial
% Band-limitation in the Circular/Spherical Harmonics Domain", 140th
% Convention of the Audio Engineering Society, Paper 9596,
% http://www.aes.org/e-lib/browse.cfm?elib=18294
%
% Spors and Ahrens (2010a) - "Analysis and Improvement of Pre-Equalization in
% 2.5-Dimensional Wave Field Synthesis", 128th Convention of the Audio
% Engineering Society, Paper 8121,
% http://www.aes.org/e-lib/browse.cfm?elib=15418
%
% Spors and Ahrens (2010b) - "Local Sound Field Synthesis by Virtual Secondary
% Sources", 40th Conference of the Audio Engineering Society, Paper 6-3,
% http://www.aes.org/e-lib/browse.cfm?elib=15561
%
% Spors, Rabenstein, Ahrens (2008) - "The Theory of Wave Field Synthesis
% Revisited," 124th Convention of the Audio Engineering Society, Paper 7358,
% http://www.aes.org/e-lib/browse.cfm?elib=14488
%
% Wierstorf (2014) - "Perceptual Assessment of Sound Field Synthesis",
% TU Berlin, https://doi.org/10.14279/depositonce-4310
%
% Winter and Spors (2016) - "On fractional delay interpolation for local wave
% field synthesis", 24th European Signal Processing Conference (EUSIPCO),
% pp. 2415-2419, https://doi.org/10.1109/EUSIPCO.2016.7760682


function event = read_serial_event(filename)

% READ_SERIAL_EVENT
%
% changed A.Hadjipapas 2010
%
% The only thing transmitted is the event.value (no info about sample) but it works

% Copyright (C) 2007, Christian Hesse
%
% 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$

%% serial port on windows or linux platform
[port, opt] = filetype_check_uri(filename);
% determine whether any serial port objects are already associated with the
% target serial port
temp = instrfind;
if isempty(temp)||~any(strcmpi(temp.Port,port))
  s=serial(port);
  s.Baudrate =str2double(opt{2});
  fopen(s);
end

%% try to read a message from the serial port
if ~isempty(s.BytesAvailable) && s.BytesAvailable~=0
  %% NOTE: Here I only use fread,which delivers numerical outputs. I
  %% then check whether the message is longer than 3 and if it is
  %% I assume it was a string to begin with and then deocde it
  %% back to char
  msg = fread(s,s.BytesAvailable);
  if length(msg)>3

    msg=char(msg');
    event.type='char';
  else
    event.type='uint';
  end
  %% The only thing transmitted is the event.value
  event.value=msg;
  %% FIX THIS: here sample is always at a fixed value (i.e true sample (e.g. write_event) is not
  %% transmitted)
  event.sample=1;
  event.duration=[];
end

%% this is the old code
%
%     % serial port on windows or linux platform
%     [port, opt] = filetype_check_uri(filename);
%     % determine whether any serial port objects are already associated with the
%     % target serial port
%     s = [];
%     temp = instrfind;
%     if isa(temp,'instrument')
%       % find all serial ports
%       i1 = strcmpi({temp(:).Type},'serial');
%       if any(i1)
%         % find all serial ports whose name matches that of the specified port
%         i2 = strmatch(lower(port),lower({temp(find(i1)).Name}));
%         % set s to the (first) matching port if present (and open if necessary)
%         if ~isempty(i2)
%           s = temp(i2(1));
%           if ~strcmp(s.Status,'open'), fopen(s); end
%         end
%       end
%     end
%     % create, configure a serial port object if necessary and open the port
%     if ~isa(s,'serial')
%       s = serial(port);
%       if ~isempty(opt) && iscell(opt), s = set(s,opt); end
%       fopen(s);
%     end
%     % try to read a message from the serial port
%     msg = [];
%     % FIXME: this currently assumes that all messages are terminated by the
%     % "newline" character (ascii character 10)
%     try
%       msg = fscanf(s,'%s\n');
%     end
%     % convert message to event structure
%     event = msg2struct(msg);


classdef StageTankInitMassOptimVar < AbstractOptimizationVariable
    %StageTankInitMassOptimVar Summary of this class goes here
    %   Detailed explanation goes here

    properties
        tank LaunchVehicleTank

        lwrBnd(1,1) double = 0;
        uprBnd(1,1) double = 0;

        useTf(1,1) = false;
    end

    methods
        function obj = StageTankInitMassOptimVar(tank)
            obj.tank = tank;
            obj.tank.optVar = obj;

            obj.id = rand();
        end

        function x = getXsForVariable(obj)
            x = [];

            if(obj.useTf)
                x = obj.tank.initialMass;
            end
        end

        function [lb, ub] = getBndsForVariable(obj)
            lb = obj.lwrBnd(obj.useTf);
            ub = obj.uprBnd(obj.useTf);
        end

        function [lb, ub] = getAllBndsForVariable(obj)
            lb = obj.lwrBnd;
            ub = obj.uprBnd;
        end

        function setBndsForVariable(obj, lb, ub)
            obj.lwrBnd = lb;
            obj.uprBnd = ub;
        end

        function useTf = getUseTfForVariable(obj)
            useTf = obj.useTf;
        end

        function setUseTfForVariable(obj, useTf)
            obj.useTf = useTf;
        end

        function updateObjWithVarValue(obj, x)
            obj.tank.initialMass = x;
        end

        function nameStrs = getStrNamesOfVars(obj, evtNum, varLocType)
            if(evtNum > 0)
                subStr = sprintf('Event %i',evtNum);
            else
                subStr = varLocType;
            end

            tankName = obj.tank.name;
            if(isempty(tankName))
                tankName = 'Untitled Tank';
            end

            nameStrs = {sprintf('%s Tank "%s" Initial Mass', subStr, tankName)};
        end
    end
end


function m_ungrid(goptn)
% M_UNGRID Removes a grid;
%          M_UNGRID deletes a map grid, but leaves any plotted
%          data.
%
%          M_UNGRID XXX
%          or
%          M_UNGRID('XXX')
%
%          can be used to remove other parameters plotted using an
%          M_XXX command (e.g. M_UNGRID COAST).

% Rich Pawlowicz (rich@ocgy.ubc.ca) 4/Apr/97
%
% 14/11/98 - Added possible option to remove other tagged items.
%
% This software is provided "as is" without warranty of any kind. But
% it's mine, so you can't sell it.

if nargin==0
  mstr='m_grid_';
else
  mstr=['m_' lower(goptn)];
end

hh=get(gca,'children');

things=get(hh,'tag');

for i=1:length(hh)
  if ~isempty(things{i})  &&  strmatch(mstr,things{i})
   delete(hh(i));
 end
end

if strmatch('m_grid',mstr)
  set(gca,'visible','on');
end


function [data_sets] = fiff_find_evoked(fname)
%
% [data_sets] = fiff_find_evoked(fname)
%
% Find all evoked data sets in a fif file and create a list of descriptors
%

%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%

global FIFF;
if isempty(FIFF)
    FIFF = fiff_define_constants();
end

me = 'MNE:fiff_find_evoked';

%
%   Open the file
%
[ fid, tree ] = fiff_open(fname);
data_sets = struct('comment',{},'aspect_kind',{},'aspect_name',{});
%
%   Find all evoked data sets
%
evoked = fiff_dir_tree_find(tree, FIFF.FIFFB_EVOKED);
if length(evoked) == 0
    fclose(fid);
    return
end
%
%   Identify the aspects
%
naspect = 0;
for k = 1:length(evoked)
    sets(k).aspects  = fiff_dir_tree_find(evoked(k), FIFF.FIFFB_ASPECT);
    sets(k).naspect = length(sets(k).aspects);
    naspect = naspect + sets(k).naspect;
end
%
%   Collect the desired information
%
count = 1;
for k = 1:length(evoked)
    evoked_comment = find_tag(evoked(k), FIFF.FIFF_COMMENT);
    for a = 1:sets(k).naspect
        aspect_comment = find_tag(sets(k).aspects(a), FIFF.FIFF_COMMENT);
        aspect_kind    = find_tag(sets(k).aspects(a), FIFF.FIFF_ASPECT_KIND);
        if ~isempty(aspect_comment)
            data_sets(count).comment = aspect_comment.data;
        elseif ~isempty(evoked_comment)
            data_sets(count).comment = evoked_comment.data;
        else
            data_sets(count).comment = 'No comment';
        end
        if ~isempty(aspect_kind)
            data_sets(count).aspect_kind = aspect_kind.data;
        else
            data_sets(count).aspect_kind = -1;
        end
        switch data_sets(count).aspect_kind
        case FIFF.FIFFV_ASPECT_AVERAGE
            data_sets(count).aspect_name = 'Average';
        case FIFF.FIFFV_ASPECT_STD_ERR
            data_sets(count).aspect_name = 'Standard error';
        case FIFF.FIFFV_ASPECT_SINGLE
            data_sets(count).aspect_name = 'Single';
        case FIFF.FIFFV_ASPECT_SUBAVERAGE
            data_sets(count).aspect_name = 'Subaverage';
        case FIFF.FIFFV_ASPECT_ALTAVERAGE
            data_sets(count).aspect_name = 'Alt. subaverage';
        case FIFF.FIFFV_ASPECT_SAMPLE
            data_sets(count).aspect_name = 'Sample';
        case FIFF.FIFFV_ASPECT_POWER_DENSITY
            data_sets(count).aspect_name = 'Power density spectrum';
        case FIFF.FIFFV_ASPECT_DIPOLE_WAVE
            data_sets(count).aspect_name = 'Dipole source waveform';
            otherwise
            data_sets(count).aspect_name = 'Unknown';
        end
        count = count + 1;
    end
end

fclose(fid);

return

function [tag] = find_tag(node, findkind)

for p = 1:node.nent
    kind = node.dir(p).kind;
    pos  = node.dir(p).pos;
    if kind == findkind
        tag = fiff_read_tag(fid, pos);
        return
    end
end
tag = [];
return
end

end


function engine = bk_inf_engine(bnet, varargin)
% BK_INF_ENGINE Boyen-Koller approximate inference algorithm for DBNs.
%
% In the BK algorithm, the belief state is represented as a product of marginals,
% even though the factors may not be independent.
%
% engine = bk_inf_engine(bnet, ...)
%
% The following optional arguments can be specified in the form of name/value pairs:
% [default value in brackets]
%
% clusters - if a cell array, clusters{i} specifies the terms in the i'th factor.
%          - 'exact' means create one cluster that contains all the nodes in a slice [exact]
%          - 'ff' means create one cluster per node (ff = fully factorised).
%
%
% For details, see
% - "Tractable Inference for Complex Stochastic Processes", X. Boyen and D. Koller, UAI 98.
% - "Approximate learning of dynamic models",  X. Boyen and D. Koller, NIPS 98.
% (The UAI98 paper discusses filtering and theory, and the NIPS98 paper discusses smoothing.)

ss = length(bnet.intra);
% set default params
clusters = 'exact';

if nargin >= 2
  args = varargin;
  nargs = length(args);
  for i=1:2:nargs
    switch args{i},
     case 'clusters',  clusters = args{i+1};
     otherwise, error(['unrecognized argument ' args{i}])
    end
  end
end

if strcmp(clusters, 'exact')
  %clusters = { compute_interface_nodes(bnet.intra, bnet.inter) };
  clusters = { 1:ss };
elseif strcmp(clusters, 'ff')
  clusters = num2cell(1:ss);
end

% We need to insert the prior on the clusters in slice 1,
% and extract the posterior on the clusters in slice 2.
C = length(clusters);
clusters2 = cell(1,2*C);
clusters2(1:C) = clusters;
for c=1:C
  clusters2{c+C} = clusters{c} + ss;
end

onodes = bnet.observed;
obs_nodes = [onodes(:) onodes(:)+ss];
engine.sub_engine = jtree_inf_engine(bnet, 'clusters', clusters2);

engine.clq_ass_to_cluster = zeros(C, 2);
for c=1:C
  engine.clq_ass_to_cluster(c,1) = clq_containing_nodes(engine.sub_engine, clusters{c});
  engine.clq_ass_to_cluster(c,2) = clq_containing_nodes(engine.sub_engine, clusters{c}+ss);
end
engine.clusters = clusters;

engine.clq_ass_to_node = zeros(ss, 2);
for i=1:ss
  engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.sub_engine, i);
  engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.sub_engine, i+ss);
end

% Also create an engine just for slice 1
bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes, 1:ss), ...
		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
for i=1:max(bnet1.equiv_class)
  bnet1.CPD{i} = bnet.CPD{i};
end

engine.sub_engine1 = jtree_inf_engine(bnet1, 'clusters', clusters);

engine.clq_ass_to_cluster1 = zeros(1,C);
for c=1:C
  engine.clq_ass_to_cluster1(c) = clq_containing_nodes(engine.sub_engine1, clusters{c});
end

engine.clq_ass_to_node1 = zeros(1, ss);
for i=1:ss
  engine.clq_ass_to_node1(i) = clq_containing_nodes(engine.sub_engine1, i);
end

engine.clpot = []; % this is where we store the results between enter_evidence and marginal_nodes
engine.filter = [];
engine.maximize = [];
engine.T = [];

engine.bel = [];
engine.bel_clpot = [];
engine.slice1 = [];
%engine.pot_type = 'cg';
% hack for online inference so we can cope with hidden Gaussians and discrete
% it will not affect the pot type used in enter_evidence
engine.pot_type = determine_pot_type(bnet, onodes);

engine = class(engine, 'bk_inf_engine', inf_engine(bnet));


%VL_IMREADJPEG Load and transform images asynchronously
%   IMAGES = VL_IMREADJPEG(FILES) reads the specified cell array
%   FILES of JPEG files and returns at cell array of images IMAGES.
%
%   IMAGES = VL_IMREADJPEG(FILES, 'NumThreads', T) uses T parallel
%   threads to accelerate the operation. Note that this is independent
%   of the number of computational threads used by MATLAB.
%
%   VL_IMREADJPEG(FILES, 'Prefetch') starts reading the specified
%   images but returns immediately to MATLAB. Reading happens
%   concurrently with MATLAB in one or more separated threads.  A
%   subsequent call IMAGES=VL_IMREADJPEG(FILES) *specifying exactly
%   the same files in the same order* will then return the loaded
%   images. This can be sued to quickly load a batch of JPEG images as
%   MATLAB is busy doing something else.
%
%   The function can transforms the images on the fly in various
%   ways. Transformatiosn are applied as follows:
%
%   1) An (H,W) image is loaded from disk.
%
%   2) A rectangular subset of the image is cropped and resized. The
%      geometry of the crop is determined as follows:
%
%      1) First, the shape (Ho,Wo) of the output image (i.e. the
%         resized crop) is determined. This, as determined by the
%         `Resize` option, can be either the same as the input image
%         (H,W) or one or both of height and witdth can be set to an
%         arbitrary value.
%

%      2) Given the output shape (Ho,Wo) of the crop, the shape
%         (Hi,Wi) and location of the crop in the input image is
%         determined.  First, an anisotropy ratio (change in aspect
%         ratio) is selected according to `CropAnisotropy`. Given
%         that, the input crop rectangle is scaled to fill a certain
%         percentage of the input image according to `CropSize`.
%         Finally, the crop is extracted either from the middle of the
%         input image or at a random location according to
%         `CropLocation`.
%
%   3) The cropedd and resized image undergoes color post
%      post-processing, including mean subtraction
%      (`SubtractAverage`), random color shift (`Brightness`), and
%      random changes in saturation (`Saturation`), and contrats
%      (`Contrast`).
%
%   The function takes the following options:
%
%   `Prefetch`:: not specified
%     If specified, run without blocking (see above).
%
%   `Verbose`:: not specified
%     If specified, increase the verbosity level.
%
%   `Pack`:: not specified
%     If specified, pack all K images in a single H x W x 3 x K
%     array. This requires using the option `'Resize',[H W]` in order
%     to set the output size to be the same for all images. Note
%     furthermore that gray-scale images are automatically extended to
%     three color channels.
%
%   `GPU`:: not specified
%     If specified, return GPU arrays instead of standard arrays. Note
%     that, using the `Prefetch` option, the data is copied to the GPU
%     in parallel with computations.
%
%   `NumThreads`:: `1`
%     Specify the number of threads used to read images. This number
%     must be at least 1. Note that it does not make sense to specify
%     a number larger than the number of available CPU cores, and
%     often fewer threads are sufficient as reading images is memory
%     access bound rather than CPU bound.
%
%   `Resize`:: not specified
%     If specified, turn on image resizing. The argument can either
%     specify the desired height and width `[H, W]` or be simply a
%     scalar `S`. In the latter case, the image is resized
%     isotropically so that the shorter side is equal to `S`.
%
%     Resizing uses bilinear interpolation. When shrinking, a simple
%     form of antialiasing is used by stretching the bilinear filter
%     over several input pixels to average them. The method is the
%     same as MATLAB `imresize` function (the two functions are
%     numerically equivalent).
%
%   `CropAnisotropy`:: `[1 1]`
%     Specify the minimum and maximum value of the anisotropy ratio
%     for the selected crops. The default value [1 1] means that the
%     crops are extracted isotropically, i.e. with the same amount of
%     stretch along horizontal and vertical directions. A value of `[0
%     0]` stretches the crop to fit the input image. A value `[A1 A2]`
%     means that an anisotropy ratio A = Wcrop/Hcrop is sampled
%     uniformly at random for each image from the specified interval.
%
%   `CropSize`:: `[1 1]`
%     Specifies the maximum and minimum size of a crop, as a
%     percentage of the maximum size it can take to fill the input
%     image (the latter is determined *after* fixing the
%     anisotropy). Using `[1 1]` means that the crop is always sized
%     to fill up as much area as possible.
%
%   `CropLocation`:: `'center'`
%     If set to `'random'`, the crop location in the input image is
%     sampled uniformly at random among all possible shifts such that
%     the crop is fully contained in the image.
%
%   `Flip`:: not specified
%     If specified, randomly flips a crop horizontally with 50%
%     probability.
%
%   `SubtractAverage`:: `[0 0 0]`
%     Subtract the specified RGB triplet from each pixel.
%
%   `Brightness`:: `zeros(3)`
%     Standard deviation `B` of the brightness shift. Each image is
%     modified by adding the color shift `B*w`, where `w` is a 3D
%     vector sampled from the standard Normal distribution.
%
%   `Contrast`:: `0`
%     Deviation `C` of the contrast shift. It must be between 0 and
%     1. A value of 0 amounts to no contrast shift. Otherwise, a
%     contrast shift is sampled at random, using `C` as an upper
%     bound.
%
%   `Saturation`:: `0`
%     The same as `Contrast`, but for saturation.
%
%   `Interpolation`:: `'bilinear'`
%     The interpolation method; one of `box`, `bilinear`, `bicubic`,
%     `lanczos2`, and `lanczos3`. The function uses interpolators
%     equivalent to MATLAB's `imresize`.
%
%   Further details on the processing performed by the function can be
%   found in the PDF manual.

% Copyright (C) 2014-16 Andrea Vedaldi.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).


function [sizeArray, planC] = getUniformizedSize(planC)
%"getUniformizedSize"
%   Return the size of the uniformized dataset ([x y z]) and store it in
%   planC{indexS.scan}.uniformScanInfo.size for future reference.
%
%   If the uniformized data does not exist, returns and stores [0 0 0].
%
% JRA 11/14/03
%
% Usage: [sizeArray, planC] = getUniformizedSize(planC)

indexS = planC{end};

try
	uniformScanInfo = planC{indexS.scan}(1).uniformScanInfo;
	scanInfo = planC{indexS.scan}(1).scanInfo(1);

	%Find number of slices in whole uniformized set.
	nCTSlices = abs(uniformScanInfo.sliceNumSup - uniformScanInfo.sliceNumInf) + 1;
	nSupSlices = size(planC{indexS.scan}(1).scanArraySuperior, 3);
	if isempty(planC{indexS.scan}(1).scanArraySuperior), nSupSlices = 0;, end
	nInfSlices = size(planC{indexS.scan}(1).scanArrayInferior, 3);
	if isempty(planC{indexS.scan}(1).scanArrayInferior), nInfSlices = 0;, end
	zSize = nCTSlices + nSupSlices + nInfSlices;
	xSize = scanInfo(1).sizeOfDimension2;
	ySize = scanInfo(1).sizeOfDimension1;

    uniformScanInfo.size = [xSize ySize zSize];
    planC{indexS.scan}(1).uniformScanInfo = uniformScanInfo;
catch
    planC{indexS.scan}(1).uniformScanInfo.size = [0 0 0];
end

sizeArray = planC{indexS.scan}(1).uniformScanInfo.size;


function b = strstartswith(s, pat)
%STRSTARTSWITH Determines whether a string starts with a specified pattern
%
%   b = strstartswith(s, pat);
%       returns whether the string s starts with a sub-string pat.
%

%   History
%   -------
%       - Created by Dahua Lin, on Oct 9, 2008
%

%% main

sl = length(s);
pl = length(pat);

b = (sl >= pl && strcmp(s(1:pl), pat)) || isempty(pat);