function obj = subsasgn(obj,subs,dat)
% Overloaded subsasgn function for file_array objects.
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id$

if isempty(subs)
    return;
end;
if ~strcmp(subs(1).type,'()'),
    if strcmp(subs(1).type,'.'),
        %error('Attempt to reference field of non-structure array.');
        if numel(struct(obj))~=1,
            error('Can only change the fields of simple file_array objects.');
        end;
        switch(subs(1).subs)
        case 'fname',      obj = asgn(obj,@fname,     subs(2:end),dat); %fname(obj,dat);
        case 'dtype',      obj = asgn(obj,@dtype,     subs(2:end),dat); %dtype(obj,dat);
        case 'offset',     obj = asgn(obj,@offset,    subs(2:end),dat); %offset(obj,dat);
        case 'dim',        obj = asgn(obj,@dim,       subs(2:end),dat); %obj = dim(obj,dat);
        case 'scl_slope',  obj = asgn(obj,@scl_slope, subs(2:end),dat); %scl_slope(obj,dat);
        case 'scl_inter',  obj = asgn(obj,@scl_inter, subs(2:end),dat); %scl_inter(obj,dat);
        case 'permission', obj = asgn(obj,@permission,subs(2:end),dat); %permission(obj,dat);
        otherwise, error(['Reference to non-existent field "' subs.subs '".']);
        end;
        return;
    end;
    if strcmp(subs(1).type,'{}'), error('Cell contents reference from a non-cell array object.'); end;
end;

if numel(subs)~=1, error('Expression too complicated');end;
dm   = size(obj);
sobj = struct(obj);

if length(subs.subs) < length(dm),
    l   = length(subs.subs);
    dm  = [dm(1:(l-1)) prod(dm(l:end))];
    if numel(sobj) ~= 1,
        error('Can only reshape simple file_array objects.');
    end;
    if numel(sobj.scl_slope)>1 || numel(sobj.scl_inter)>1,
        error('Can not reshape file_array objects with multiple slopes and intercepts.');
    end;
end;

dm   = [dm ones(1,16)];
do   = ones(1,16);
args = {};
for i=1:length(subs.subs),
    if ischar(subs.subs{i}),
        if ~strcmp(subs.subs{i},':'), error('This shouldn''t happen....'); end;
        args{i} = int32(1:dm(i));
    else
        args{i} = int32(subs.subs{i});
    end;
    do(i) = length(args{i});
end;
for j=1:length(sobj),
    if strcmp(sobj(j).permission,'ro'),
        error('Array is read-only.');
    end
end

if length(sobj)==1
    sobj.dim = dm;
    if numel(dat)~=1,
        subfun(sobj,double(dat),args{:});
    else
        dat1 = double(dat) + zeros(do);
        subfun(sobj,dat1,args{:});
    end;
else
    for j=1:length(sobj),
        ps  = [sobj(j).pos ones(1,length(args))];
        dm  = [sobj(j).dim ones(1,length(args))];
        siz = ones(1,16);
        for i=1:length(args),
            msk      = args{i}>=ps(i) & args{i}<(ps(i)+dm(i));
            args2{i} = find(msk);
            args3{i} = int32(double(args{i}(msk))-ps(i)+1);
            siz(i)   = numel(args2{i});
        end;
        if numel(dat)~=1,
            dat1 = double(subsref(dat,struct('type','()','subs',{args2})));
        else
            dat1 = double(dat) + zeros(siz);
        end;
        subfun(sobj(j),dat1,args3{:});
    end
end
return

function sobj = subfun(sobj,dat,varargin)
va = varargin;

dt  = datatypes;
ind = find(cat(1,dt.code)==sobj.dtype);
if isempty(ind), error('Unknown datatype'); end;
if dt(ind).isint, dat(~isfinite(dat)) = 0; end;

if ~isempty(sobj.scl_inter),
    inter = sobj.scl_inter;
    if numel(inter)>1,
        inter = resize_scales(inter,sobj.dim,varargin);
    end;
    dat = double(dat) - inter;
end;

if ~isempty(sobj.scl_slope),
    slope = sobj.scl_slope;
    if numel(slope)>1,
        slope = resize_scales(slope,sobj.dim,varargin);
        dat   = double(dat)./slope;
    else
        dat   = double(dat)/slope;
    end;
end;

if dt(ind).isint, dat = round(dat); end;

% Avoid warning messages in R14 SP3
wrn = warning;
warning('off');
dat   = feval(dt(ind).conv,dat);
warning(wrn);

nelem = dt(ind).nelem;
if nelem==1,
    mat2file(sobj,dat,va{:});
elseif nelem==2,
    sobj1       = sobj;
    sobj1.dim   = [2 sobj.dim];
    sobj1.dtype = dt(find(strcmp(dt(ind).prec,{dt.prec}) & (cat(2,dt.nelem)==1))).code;
    dat         = reshape(dat,[1 size(dat)]);
    dat         = [real(dat) ; imag(dat)];
    mat2file(sobj1,dat,int32([1 2]),va{:});
else
    error('Inappropriate number of elements per voxel.');
end;
return

function obj = asgn(obj,fun,subs,dat)
if ~isempty(subs),
    tmp = feval(fun,obj);
    tmp = subsasgn(tmp,subs,dat);
    obj = feval(fun,obj,tmp);
else
    obj = feval(fun,obj,dat);
end;


classdef MapNested < containers.Map & handle

    % A nested map container
    %
    % A MapNested object implements nested maps (map of maps).
    %
    % MapN is a handle class.
    % Since MapNested is a subclass from containers.Map, all functions from
    % containers.Map will be inherited (eg. keys, values, ...)
    %
    % Description - basic outline
    % ---------------------------
    %
    % A MapNested object is constructed like this:
    %
    %   M = MapNested();
    %
    % Values are stored using M(key1, key2, ...) = value, for example:
    %
    %   M(1, 'a')     = 'a string value';
    %   M(1, 'b')     = 287.2;
    %   M(2)          = [1 2 3; 4 5 6];
    %
    % Attention: you can not assign cell-arrays in this implementation:
    %   M(2, 'x', pi) = {'a' 'cell' 'array'}; %throws error
    %
    % another possibility is to define the keys as cell-array like:
    %   M({key1, key2, key3}) = value;
    %
    %
    % Values are retrieved using M(key1, key2, ...), for example
    %
    %   v = M(1, 'b');
    %   u = M(2);
    %
    % or with using cell-arrays for the keys
    %   v = M({key1, key2, key3});
    %
    % Set and get - methods
    % -----------------------------
    %
    % for setting and retrieving values there are also two methods
    % implemented, for setting a value:
    %
    %   MapObj = setValueNested(MapObj, {key1, key2, key3, ...}, value);
    %
    %   here the second input parameter has to be a cell-array with the
    %   keys.
    %
    % For retrieving values one can use:
    %   value = getValueNested(MapObj, {key1, key2, key3,...});
    %
    %   here the second input parameter has to be a cell-array with the
    %   keys.
    %
    %
    % Updating and removing entries
    % -----------------------------
    %
    % The value for a given key list is updated using the usual assignment;
    % the previous value is overwritten.
    %
    %   M(pi, 'x') = 1;     % 1 is current value
    %   M(pi, 'x') = 2;     % 2 replaces 1 as the value for this key list
    %
    %   NMapobj('Key') = []; %removes the key
    %   remove(NMapobj, 'Key'); %also removes the key
    %
    % check if is a specific key in the map
    % -------------------------------------
    %   M.isKey(keyList) %keyList is a cell array of the nested keys
    %   M.isKey(Key1, Key2, Key3,..) %Key1, Key2, Key3 are the nested keys
    %   isKey(M, keyList) %keyList is a cell array of the nested keys
    %   isKey(M, Key1, Key2, Key3,..) %Key1, Key2, Key3 are the nested keys
    %
    %
    % Methods and properties
    % ----------------------
    %
    % MapN methods:
    %   MapNested        - constructor for MapNested objects
    %   subsref     - implements value = Mobj(keylist)
    %   subsasgn    - implements M(keylist) = value
    %   setValueNested  - implements Mobj = setValueNested(Mobj, keyList,
    %   value)
    %   getValueNested  - implements value = getValueNested(Mobj, keyList);
    %   isKey - implements Mobj.iskey(keyList);
    %
    % See also: containers.Map

    % (c) 2017, Roland Ritt
    methods
        function obj = MapNested(varargin)
            % constructor, calls Superclass-constructor with varargin;
            obj = obj@containers.Map(varargin{:});

        end

        function obj = setValueNested(obj, keyList, value)
            % method which recursively constructs a map of maps and add
            % a a value at the specified keys
            %
            % Implements the syntax
            %
            %   MapNestedObj = setValueNested(MapNestedObj, keyList,
            %   value);
            %       (keyList is of type 'CellArray')
            %
            % See also: MapNested, MapNested/setValueNested
            if ~iscell(keyList)
                %check if the keyList is a cell array
                error('second input (keylist) is no cellArray');
            end

            KeyType = class(keyList{1});
            %find the class-type of first key
            if length(keyList)==1
                % check if the object is defined
                if isempty(obj)
                    %if the object does not exist...
                    obj = MapNested('KeyType', KeyType,'ValueType', 'any');
                    % generate a new MapNested-object with the specified
                    % key-Type, and default ValueType set to 'any'

                end

                if isempty(value)
                    remove(obj, keyList{1});
                else
                obj = [obj;MapNested(keyList{1},value)];
                end

                return
            else
                % if more than one key
                if obj.isKey(keyList{1})
                    % check if the key is in the map
                    temp = values(obj, keyList(1));
                    temp = temp{1};
                    % retrieve the MapNested-object from the map
                    if ~isa(temp ,'containers.Map')
                        % if the value is not a MapObject, generate a new
                        % one
                        temp = MapNested('KeyType', KeyType,'ValueType', 'any');
                    end

                else
                    % if the key does not exist, generate a new
                    % MapNested-object
                    temp = MapNested('KeyType', KeyType,'ValueType', 'any');

                end
                temp = setValueNested(temp, keyList(2:end), value);
                % set the value in the MapNested-object (recursive call)

                if isempty(obj)
                    %if obj is empty, generate a new MapNested-object
                    obj = MapNested(keyList{1}, temp);
                else
                    %if obj exists, concatenate the new entry
                    obj = [obj;MapNested(keyList{1}, temp)];
                end

            end

        end

        function value = getValueNested(obj, keyList)
            % method for retrieving values from a MapNested object by
            % recursively calls to this method
            %
            % Implements the syntax
            %
            %   value = getValueNested(MapNestedObj, keyList, value);
            %       (keyList is of type 'CellArray')
            %
            % See also: MapNested, MapNested/setValueNested
            if ~iscell(keyList)
                %check if the keyList is a cellArray
                error('second input is no cellArray');
            end

            if ~obj.isKey(keyList{1})
                %check if the first key is in the list, if not, throw an
                %error (maybe should be changed to empty object)
                error(['key ''', keyList{1}, ''' is not a key'] );
            end
            if length(keyList)==1
                % if the keyList is only of length 1, return the value of
                % this list
                value = values(obj, {keyList{1}});
                % call the method from the superclass
                value=value{1}; %retrieve the value
                return
            else
                % if there are more than one keys Left in the keyList
                temp = values(obj, {keyList{1}});
                % retrieve the MapNested object (key1)
                temp = temp{1};
                if ~isa(temp ,'containers.Map')
                    % if the retrieved value is not a Map, the
                    % MapNested object was misused --> throw error message
                    error(['key ''', keyList{2}, ''' is not a key'] );
                end
                value = getValueNested(temp, keyList(2:end));
                % recursively call the getValueNested method.

            end

        end

        function v = subsref(M, S)
            % returns value associated with key list
            %
            % Implements the syntax
            %
            %   value = MapNobj(key1, key2, ...)
            %
            % See also: MapNested, MapNested/subsasgn

            switch S(1).type
                case '.'
                    v = builtin('subsref',M,S);

                case '()'
                    %                     if ~isscalar(S) || ~strcmp(S.type, '()') || length(S)<1
                    %                         error('MapNested:Subsref:LimitedIndexing', ...
                    %                             'Only ''()'' indexing is supported by a MapNested');
                    %                     end

                    try

                        if iscell(S(1).subs{1})
                            temp = S(1).subs{1};
                        else
                            temp = S(1).subs;
                        end
                        v = getValueNested(M, temp);
                    catch me
                        % default is handled in subsrefError for efficiency
                        error('MapNested:Subsref:IndexingError', ...
                            ['Something went wrong in indexing: ',me(1).message] );
                    end

                    if length(S)>1
                        v = subsref(v, S(2:end));
                    end

                case '{}'
                    error('MapNested:Subsasgn:LimitedIndexing', ...
                        '''{}'' indexing is not supported by a MapNested');
                otherwise
                    error('Not a valid indexing expression')
            end

        end

        function M = subsasgn(M, S, v)
            % sets value associated with key list
            %
            % Implements the syntax
            %
            %   MapNobj(key1, key2, ...) = value
            %
            % See also: MapNested, MapNested/subsasgn

            if ~isscalar(S) || ~strcmp(S.type, '()') || length(S)<1
                error('MapNested:Subsasgn:LimitedIndexing', ...
                    'Only ''()'' indexing is supported by a MapNested');
            end

            try

                if iscell(S.subs{1})
                    temp = S.subs{1};
                else
                    temp = S.subs;
                end
                M = setValueNested(M, temp, v);
            catch me
                % default is handled in subsrefError for efficiency
                error('MapNested:Subsasgn:IndexingError', ...
                    'Something went wrong in indexing');
            end
        end

        function bisKey = isKey(M, varargin)

            %% test

            if length(varargin)==1
                keyList = varargin{1};
            else
                keyList = varargin;
            end

            if iscell(keyList)
                if length(keyList)== 1
                    bisKey = isKey@containers.Map(M,keyList{1});
                    return
                else

                    KeyTemp = keyList(1);
                    if M.isKey(KeyTemp)
                        Mtemp = M.getValueNested(KeyTemp);
                        bisKey = isKey(Mtemp, keyList(2:end));
                    else
                        bisKey = false;
                    end
                    return;
                end

            else
                bisKey = isKey@containers.Map(M,varargin{1});
                return;
            end

        end

    end

end


% instantiate the library
disp('Loading the library...');
lib = lsl_loadlib();

% resolve a stream...
disp('Resolving an EEG stream...');
result = {};
while isempty(result)
    result = lsl_resolve_byprop(lib,'type','EEG'); end

% create a new inlet
disp('Opening an inlet...');
inlet = lsl_inlet(result{1});

disp('Now receiving chunked data...');
while true
    % get chunk from the inlet
    [chunk,stamps] = inlet.pull_chunk();
    for s=1:length(stamps)
        % and display it
        fprintf('%.2f\t',chunk(:,s));
        fprintf('%.5f\n',stamps(s));
    end
    pause(0.05);
end


%% Uninstall
%
% Copyright (c) 2018-present, Mahmoud Afifi
% York University, Canada
% mafifi@eecs.yorku.ca | m.3afifi@gmail.com
%
% This source code is licensed under the license found in the
% LICENSE file in the root directory of this source tree.
% All rights reserved.
%
% Please cite the following work if this program is used:
% Mahmoud Afifi, Brian Price, Scott Cohen, and Michael S. Brown,
% "When color constancy goes wrong: Correcting improperly white-balanced
% images", CVPR 2019.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%

disp('Uninstalling WB for sRGB images...')
current = pwd;
rmpath(fullfile(current,'classes'));
savepath
disp('Done!');


%{
 * Copyright (C) 2020-2030, The Regents of The University of Michigan.
 * All rights reserved.
 * This software was developed in the Biped Lab (https://www.biped.solutions/)
 * under the direction of Jessy Grizzle, grizzle@umich.edu. This software may
 * be available under alternative licensing terms; contact the address above.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Regents of The University of Michigan.
 *
 * AUTHOR: Bruce JK Huang (bjhuang[at]umich.edu)
 * WEBSITE: https://www.brucerobot.com/
%}

function edge = findEdgePointsInIdealFrame(H_TL, X_ref, tag_length)
    % X_ref: points that have been transformed back to the ideal frame
    % X_ref(1,:) : x
    % X_ref(2,:) : y
    % X_ref(3,:) : z
    % X_ref(4,:) : I
    % X_ref(5,:) : R
    % X_ref(6,:) : scan
    % X_ref(7,:) : ExpNmbr
    top_ring = max(X_ref(5, :));
    bottom_ring = min(X_ref(5, :));
    num_scan = max(X_ref(6, :)) - min(X_ref(6, :));
    pick_points = max(1, ceil(num_scan));
    % Ideal frame (top-left, bottom-left, bottom-right, top-right)
%     ideal_frame.x = zeros(1,8);
%     ideal_frame.y = [-tag_length/2, -tag_length/2, -tag_length/2, tag_length/2, tag_length/2, tag_length/2, tag_length/2, -tag_length/2];
%     ideal_frame.z = [tag_length/2, -tag_length/2, -tag_length/2, -tag_length/2, -tag_length/2, tag_length/2, tag_length/2, tag_length/2];

    % left, bottom, right, top (y-axis, -z-axis, -y-axis, z-axis)
    edge_list(1).line = [-tag_length/2 0; -tag_length/2 1];
    edge_list(2).line = [0 -tag_length/2; 1 -tag_length/2];
    edge_list(3).line = [tag_length/2 0; tag_length/2 1];
    edge_list(4).line = [0 tag_length/2; 1 tag_length/2];
    edge(4).points = [];

    % choose one point per scan per ring
%     for j = 1:num_scan
%         current_scan_points = X_ref(:, X_ref(6,:)==j);
%         for i = bottom_ring:top_ring
%             if size(current_scan_points(2:3, current_scan_points(5,:)==i), 2) > 1
%                 current_ring_points = current_scan_points(1:3, current_scan_points(5,:)==i);
%                 extreme_points = [current_ring_points(:, 1), current_ring_points(:, end)];
%                 extreme_point1 = current_ring_points(:, 1);
%                 extreme_point2 = current_ring_points(:, end);
%                 dist1 = zeros(1, 4);
%                 dist2 = zeros(1, 4);
%                 for k = 1:4
%                     dist1(1, k) = pointToLineDistance(extreme_point1(2:3, :)', edge_list(k).line(1, :), edge_list(k).line(2, :));
%                     dist2(1, k) = pointToLineDistance(extreme_point2(2:3, :)', edge_list(k).line(1, :), edge_list(k).line(2, :));
%                 end
%                 [~, edge1_i] = min(dist1);
%                 [~, edge2_i] = min(dist2);
%                 edge_point_3D_1 = inv(H_TL) * [extreme_point1; 1];
%                 edge_point_3D_2 = inv(H_TL) * [extreme_point2; 1];
% %                 selected_edge_points = [current_ring_points(1:3, indices(selected_indices)); ones(1, length(selected_indices))];
%                 edge(edge1_i).points = [edge(edge1_i).points, edge_point_3D_1];
%                 edge(edge2_i).points = [edge(edge2_i).points, edge_point_3D_2];
%             end
%         end
%     end

     % choose a few points using all scans
    for i = bottom_ring:top_ring
        current_ring_points = X_ref(:, X_ref(5,:)==i);
%         dist = zeros(length(current_ring_points), 4);
        for k = 1:4
            dist = pointToLineDistance(current_ring_points(2:3,:)', edge_list(k).line(1, :), edge_list(k).line(2, :));
            [value, indices] = mink(dist, pick_points);
            selected_indices = find (value<tag_length/8);
            selected_edge_points = inv(H_TL) * [current_ring_points(1:3, indices(selected_indices)); ones(1, length(selected_indices))];
%             selected_edge_points = [current_ring_points(1:3, indices(selected_indices)); ones(1, length(selected_indices))];
            edge(k).points = [edge(k).points, selected_edge_points];
        end
    end

%     edge_list = [tag_length/2, -tag_length/2, -tag_length/2, tag_length/2];
%     edge(4).points = [];
%     for i = bottom_ring:top_ring
%         current_ring_points = X_ref(:, X_ref(5,:)==i);
%         first_point = current_ring_points(:, 1);
%         edge_distance = [abs(first_point(2) - edge_list(1)), ...
%                          abs(first_point(3) - edge_list(2)), ...
%                          abs(first_point(2) - edge_list(3)), ...
%                          abs(first_point(3) - edge_list(4))];
%         [~, first_index] = min(edge_distance);
%         first_point = inv(H_TL) * [first_point(1:3); 1];
%         edge(first_index).points = [edge(first_index).points, first_point];
%         last_point = current_ring_points(:, end);
%         edge_distance = [abs(last_point(2) - edge_list(1)), ...
%                          abs(last_point(3) - edge_list(2)), ...
%                          abs(last_point(2) - edge_list(3)), ...
%                          abs(last_point(3) - edge_list(4))];
%         [~, last_index] = min(edge_distance);
%         last_point = inv(H_TL) * [last_point(1:3); 1];
%         edge(last_index).points = [edge(last_index).points, last_point];
%     end
%     fig_hangle = figure(99999);
%     cla(fig_hangle)
%     X_move_back = inv(H_TL) * [X_ref(1:3,:); ones(1, size(X_ref(1, :), 2))];
%     scatter3(X_move_back(1,:), X_move_back(2,:), X_move_back(3,:), 'k.')
% %     scatter3(X_ref(1,:), X_ref(2,:), X_ref(3,:), 'k.')
%     hold on
%     scatter3(edge(1).points(1,:), edge(1).points(2,:), edge(1).points(3,:), 'ro', 'filled')
%     scatter3(edge(2).points(1,:), edge(2).points(2,:), edge(2).points(3,:), 'go', 'filled')
%     scatter3(edge(3).points(1,:), edge(3).points(2,:), edge(3).points(3,:), 'bo', 'filled')
%     scatter3(edge(4).points(1,:), edge(4).points(2,:), edge(4).points(3,:), 'mo', 'filled')
%     title('edge parsing results')
%     xlabel("x")
%     ylabel("y")
%     zlabel("z")
%     axis equal
end


function [results, loc] = ismember(A,B)
   %ISMEMBER for scnlobjects
   % TRUE for each waveform that matches any scnl in the anythingelse array.
   %
   % see also ISMEMBER
   %
   % WILDCARD is not implemented
   %
   % since we are looking for scnlA in scnlB, then scnlB may have wildcards.
   % the wildcard is a field value of '*' (only).  These haven't been
   % thoroughly tested.

   wildcard = '*';
   if isempty(A) || isempty(B)
      results = [];
      loc = [];
      return
   end

   assert(isa(A,'scnlobject'),class(A))
   tagA = toTag(A);
   tagB = toTag(B);
   [results, loc] = ismember(tagA, tagB);
   return

   results = false(size(A));
   loc = zeros(size(A));
   for i=1:numel(B)
      theseA = A;
      if strcmpi(B(i).station,wildcard)
         theseA = set(theseA,'station',wildcard);
      end
      if strcmpi(B(i).channel,wildcard)
         theseA = set(theseA,'channel',wildcard);
      end
      if strcmpi(B(i).network,wildcard)
         theseA = set(theseA,'network',wildcard);
      end
      if strcmpi(B(i).location,wildcard)
         theseA = set(theseA,'location',wildcard);
      end
      [resultstmp, loctmp] = ismember(getSearchString(theseA),getSearchString(B));
      results = results | resultstmp;
      loc(loc==0) = loctmp(loc==0);
   end
end
function t = toTag(scnls)

   switch class(scnls)
      case 'scnlobject'
         t = [scnls.tag];
      case 'ChannelTag'
         t = [scnls];
      otherwise
         %try to convert it?
         t = ChannelTag(scnls);
   end
end

function ss = getSearchString(scnl)
   sta = get(scnl,'station');
   if ~iscell(sta),
      sta = {sta};
   end;
   sta(strcmpi(sta,'')) = {'*-noStation-*'};
   cha = get(scnl,'channel');
   if ~iscell(cha), cha = {cha}; end;
   cha(strcmpi(cha,'')) = {'*-noChannel-*'};
   net = get(scnl,'network');
   if ~iscell(net), net = {net}; end;
   net(strcmpi(net,'') | strcmpi(net,'--')) = {'*-noNetwork-*'};
   loc = get(scnl,'location');
   if ~iscell(loc), loc = {loc}; end;
   loc(strcmpi(loc,'') | strcmpi(loc,'--')) = {'*-noLocation-*'};

   ss = strcat(sta,'|',cha,'|', net,'|',loc);
end


%% tri6_subtri3
% Below is a demonstration of the features of the |tri6_subtri3| function

%%
clear; close all; clc;

%% Syntax
% |[Ft3]=tri6_subtri3(Ft6,Vt6);|

%% Description
% UNDOCUMENTED
%% Examples
%
%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*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/>.


classdef(Abstract) AbstractFirstOrderIntegrator < AbstractIntegrator
    %AbstractFirstOrderIntegrator Summary of this class goes here
    %   Detailed explanation goes here

    properties

    end

    methods
        [t,y,te,ye,ie] = integrate(obj, odefun, tspan, y0, evtsFunc, odeOutputFun)
    end
end


function varargout = ma_MissionOptimizerGUI(varargin)
% MA_MISSIONOPTIMIZERGUI MATLAB code for ma_missionoptimizergui.fig
%      MA_MISSIONOPTIMIZERGUI, by itself, creates a new MA_MISSIONOPTIMIZERGUI or raises the existing
%      singleton*.
%
%      H = MA_MISSIONOPTIMIZERGUI returns the handle to a new MA_MISSIONOPTIMIZERGUI or the handle to
%      the existing singleton*.
%
%      MA_MISSIONOPTIMIZERGUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in MA_MISSIONOPTIMIZERGUI.M with the given input arguments.
%
%      MA_MISSIONOPTIMIZERGUI('Property','Value',...) creates a new MA_MISSIONOPTIMIZERGUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before ma_MissionOptimizerGUI_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to ma_MissionOptimizerGUI_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help ma_missionoptimizergui

% Last Modified by GUIDE v2.5 20-May-2016 22:12:18

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @ma_MissionOptimizerGUI_OpeningFcn, ...
                   'gui_OutputFcn',  @ma_MissionOptimizerGUI_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before ma_missionoptimizergui is made visible.
function ma_MissionOptimizerGUI_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to ma_missionoptimizergui (see VARARGIN)

% Choose default command line output for ma_missionoptimizergui
    handles.output = hObject;
    handles.exists = true;

    % Update handles structure
    handles.ma_MainGUI = varargin{1};
    guidata(hObject, handles);

    maData = getappdata(handles.ma_MainGUI,'ma_data');

    excludeList = {'Distance Traveled','Distance to Ref. Station','Dry Mass','Eclipse','Elevation Angle w.r.t. Ref. Station', ...
                   'Line of Sight to Ref. Spacecraft','Line of Sight to Ref. Station','Liquid Fuel/Ox Mass','Monopropellant Mass','Xenon Mass'};
    taskList = ma_getGraphAnalysisTaskList(excludeList);

    propNames = maData.spacecraft.propellant.names;
    for(i=1:length(propNames))
        taskList{end+1} = sprintf('%s Mass', propNames{i}); %#ok<AGROW>
    end
    taskList = sort(taskList);

    set(handles.availConstListbox, 'String', taskList);

    initUserData(handles, maData);

    setOptVarListbox(handles.optVarListbox, maData);
    optVarListbox_Callback(handles.optVarListbox, [], handles);

    setOptVarListbox(handles.eventObjFuncCombo, maData);
    populateBodiesCombo(getappdata(handles.ma_MainGUI,'celBodyData'), handles.bodyObjFuncCombo);
    bodyObjFuncCombo_Callback(handles.objFuncCombo, [], handles);

    populateGUIFromOptSettings(handles, maData);
    objFuncCombo_Callback(handles.objFuncCombo, [], handles);

    % UIWAIT makes ma_missionoptimizergui wait for user response (see UIRESUME)
    uiwait(handles.ma_MissionOptimizerGUI);

function initUserData(handles, maData)
    set(handles.optVarListbox,'UserData',zeros(length(maData.script),5));
    set(handles.actConstsListbox,'UserData',{});

function setOptVarListbox(hListbox, maData)
    script = maData.script;

    i = 1;
    listboxStr = {};
    for(eventArr = script)
        event = eventArr{1};
        listboxStr{end+1} = ['Event ', num2str(i), ': ', event.name]; %#ok<AGROW>
        i = i+1;
    end

    set(hListbox,'String',listboxStr);

function populateGUIFromOptSettings(handles, maData)
    script = maData.script;

    if(isfield(maData.optimizer,'objective') && ~isempty(maData.optimizer.objective))
        value = findValueFromComboBox(maData.optimizer.objective{1}, handles.objFuncCombo);
        if(value <= length(get(handles.objFuncCombo,'String')))
            set(handles.objFuncCombo,'value',value);
        else
            set(handles.objFuncCombo,'value',length(get(handles.objFuncCombo,'String')));
        end

        eventID = maData.optimizer.objective{5};
        [~, eventNum] = getEventByID(eventID, script);
        if(eventNum <= length(get(handles.eventObjFuncCombo,'String')))
            [~, eventNum] = getEventByID(eventID, script);
            if(eventNum >= 1)
                set(handles.eventObjFuncCombo,'value',eventNum);
            else
                set(handles.eventObjFuncCombo,'value',length(get(handles.eventObjFuncCombo,'String')));
            end
        else
            set(handles.eventObjFuncCombo,'value',length(get(handles.eventObjFuncCombo,'String')));
        end

        if(maData.optimizer.objective{4} <= length(get(handles.bodyObjFuncCombo,'String')))
            set(handles.bodyObjFuncCombo,'value',maData.optimizer.objective{4});
        else
            set(handles.bodyObjFuncCombo,'value',length(get(handles.bodyObjFuncCombo,'String')));
        end
    end

    if(~isempty(maData.optimizer.constraints))
        constDetails = maData.optimizer.constraints{1};
        constDetailsToDelete = [];
        for(i=1:size(constDetails,1))
            try
                row = constDetails(i,:);
                details = row{5};

                eventID = details(7);
                [event, eventNum] = getEventByID(eventID, script);
                row{1} = ma_getConstraintStr(row{3}, eventNum);
                constDetails(i,:) = row;
                if(isempty(event) || eventNum<1 || ~isstruct(event) || ~isfield(event,'id') || event.id ~= eventID)
                    constDetailsToDelete(end+1) = i; %constraint no longer applicable, delete
                end

                otherSCID = details(8);
                oSCInfo = getOtherSCInfoByID(maData, otherSCID);
                if(isempty(oSCInfo) && otherSCID >= 0)
                    constDetailsToDelete(end+1) = i;
                end
            catch
                constDetailsToDelete(end+1) = i;
                continue;
            end
        end

        for(i=length(constDetailsToDelete):-1:1)
            idToDelete = constDetailsToDelete(i);
            constDetails(idToDelete,:) = [];
        end

        preSize = size(constDetails);
        constDetails(all(cellfun(@isempty,constDetails),2),:) = [];
        postSize = size(constDetails);

        if(~all(preSize==postSize))
            set(handles.actConstsListbox,'UserData',constDetails);
            updateActConstListBox(handles);
        end

        set(handles.actConstsListbox,'UserData',constDetails);
        updateActConstListBox(handles);
    end

% --- Outputs from this function are returned to the command line.
function varargout = ma_MissionOptimizerGUI_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
% varargout{1} = handles.output;

% --- Executes on selection change in objFuncCombo.
function objFuncCombo_Callback(hObject, eventdata, handles)
% hObject    handle to objFuncCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns objFuncCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from objFuncCombo
    contents = cellstr(get(hObject,'String'));
    selected = deblank(contents{get(hObject,'Value')});

    switch selected
        case 'Minimize Distance to Body'
            set(handles.eventObjFuncCombo,'Enable','on');
            set(handles.bodyObjFuncCombo,'Enable','on');

        case 'Maximize Spacecraft Mass'
            set(handles.eventObjFuncCombo,'Enable','on');
            set(handles.bodyObjFuncCombo,'Enable','off');

        case 'Minimize Inclination'
            set(handles.eventObjFuncCombo,'Enable','on');
            set(handles.bodyObjFuncCombo,'Enable','off');

        case 'Minimize Eccentricity'
            set(handles.eventObjFuncCombo,'Enable','on');
            set(handles.bodyObjFuncCombo,'Enable','off');

        case 'Maximize Inclination'
            set(handles.eventObjFuncCombo,'Enable','on');
            set(handles.bodyObjFuncCombo,'Enable','off');

        case 'Maximize Eccentricity'
            set(handles.eventObjFuncCombo,'Enable','on');
            set(handles.bodyObjFuncCombo,'Enable','off');

        case 'Minimize Mission Duration'
            set(handles.eventObjFuncCombo,'Enable','off');
            set(handles.bodyObjFuncCombo,'Enable','off');

        case 'No Optimization (Satisfy Constraints Only)'
            set(handles.eventObjFuncCombo,'Enable','off');
            set(handles.bodyObjFuncCombo,'Enable','off');
    end

% --- Executes during object creation, after setting all properties.
function objFuncCombo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to objFuncCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in eventObjFuncCombo.
function eventObjFuncCombo_Callback(hObject, eventdata, handles)
% hObject    handle to eventObjFuncCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns eventObjFuncCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from eventObjFuncCombo

% --- Executes during object creation, after setting all properties.
function eventObjFuncCombo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to eventObjFuncCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in optVarListbox.
function optVarListbox_Callback(hObject, eventdata, handles)
% hObject    handle to optVarListbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns optVarListbox contents as cell array
%        contents{get(hObject,'Value')} returns selected item from optVarListbox
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');

    eventNum = get(hObject,'Value');
    event = maData.script{eventNum};

    updateEventInfo(handles.varEventInfoLabel, event, celBodyData);
%     setOptFlagLbUb(handles, eventNum);

function setOptFlagLbUb(handles, eventNum)
    maData = getappdata(handles.ma_MainGUI,'ma_data');

    userData = get(handles.optVarListbox,'UserData');
    if(eventNum > size(userData,1))
        userData = [userData; zeros(eventNum-size(userData,1),5)];
    end
    eventID = ma_GetEventIDByEventNum(eventNum, maData.script);
    event = getEventByID(eventID, maData.script);

    blacklist = false;
    if(strcmpi(event.type,'Mass_Dump'))
        blacklist = true;
    elseif(strcmpi(event.type,'Set_State'))
        blacklist = true;
    elseif(strcmpi(event.type,'Coast'))
        bool1 = strcmpi(event.coastType,'goto_ut');
        bool2 = strcmpi(event.coastType,'goto_dt');
        bool3 = strcmpi(event.coastType,'goto_tru');
        if(~(bool1 || bool2 || bool3))
            blacklist = true;
        end
    elseif(strcmpi(event.type,'DV_Maneuver'))
        bool1 = strcmpi(event.maneuverType,'dv_inertial');
        bool2 = strcmpi(event.maneuverType,'dv_orbit');
        if(~(bool1 || bool2))
            blacklist = true;
        end
    end

    if(blacklist)
        set(handles.varOptEventCheckbox,'Enable','off', 'value',0);
        set(handles.lbVarText,'Enable','off');
        set(handles.ubVarText,'Enable','off');
    else
        set(handles.lbVarText,'Enable','on');
        set(handles.ubVarText,'Enable','on');
        set(handles.varOptEventCheckbox,'Enable','on');

        row = userData(eventNum,:);
        set(handles.varOptEventCheckbox, 'value', row(1));
        set(handles.lbVarText, 'String', num2str(row(2)));
        set(handles.ubVarText, 'String', num2str(row(3)));
    end

function updateEventInfo(hVarEventInfoLabel, event, celBodyData)
    name = event.name;
    type = event.type;

    optStr = {};
    if(isfield(event,'vars'))
        vars = event.vars;
        for(i=1:size(vars,2))
            if(vars(1,i) == 1)
                optStr{i} = '(Opt)';
            else
                optStr{i} = '';
            end
        end
    end

    if(length(name)>13)
        name = [name(1:10),'...'];
    end
    if(length(type)>13)
        type = [type(1:10),'...'];
    end

    eventInfoStr = {};
    eventInfoStr{end+1} = ['Name    = ', name];
    eventInfoStr{end+1} = ['Type    = ', type];

    subtype = [];
    param1Str = 'No Parameters';
    param2Str = '';
    param3Str = '';
    switch event.type
        case 'Set_State'
            subtype = 'None';

        case 'Coast'
            subtype = event.coastType;

            switch subtype
                case 'goto_ut'
                    param1Str = ['UT = ', num2str(event.coastToValue),' sec ', optStr{1}];

                    param2Str = ['Num. of Revs = ', num2str(event.revs)];

                    if(~isempty(event.refBody))
                        bodyInfo = getBodyInfoByNumber(event.refBody.id, celBodyData);
                        param3Str = ['RefBody = ', bodyInfo.name];
                    else
                        param3Str = ['RefBody = None'];
                    end

                case 'goto_dt'
                    param1Str = ['dT = ', num2str(event.coastToValue),' sec ', optStr{1}];

                    param2Str = ['Num. of Revs = ', num2str(event.revs)];

                    bodyInfo = event.refBody;
                    if(~isempty(bodyInfo))
                        param3Str = ['RefBody = ', bodyInfo.name];
                    else
                        param3Str = ['RefBody = None'];
                    end

                case 'goto_tru'
                    param1Str = ['Tru Anom = ', num2str(rad2deg(event.coastToValue)),' deg ', optStr{1}];

                    param2Str = ['Num. of Revs = ', num2str(event.revs)];

                    bodyInfo = event.refBody;
                    if(~isempty(bodyInfo))
                        param3Str = ['RefBody = ', bodyInfo.name];
                    else
                        param3Str = ['RefBody = None'];
                    end

                otherwise
                    param1Str = ['Num. of Revs = ', num2str(event.revs)];

                    bodyInfo = event.refBody;
                    if(~isempty(bodyInfo))
                        param2Str = ['RefBody = ', bodyInfo.name];
                    else
                        param2Str = ['RefBody = None'];
                    end
            end

        case 'DV_Maneuver'
            subtype = event.maneuverType;

            switch event.maneuverType
                case 'dv_inertial'
                    param1Str = ['dVx = ', num2str(event.maneuverValue(1)*1000), ' m/s ', optStr{1}];
                    param2Str = ['dVy = ', num2str(event.maneuverValue(2)*1000), ' m/s ', optStr{2}];
                    param3Str = ['dVz = ', num2str(event.maneuverValue(3)*1000), ' m/s ', optStr{3}];
                case 'dv_orbit'
                    param1Str = ['dVp = ', num2str(event.maneuverValue(1)*1000), ' m/s ', optStr{1}];
                    param2Str = ['dVn = ', num2str(event.maneuverValue(2)*1000), ' m/s ', optStr{2}];
                    param3Str = ['dVr = ', num2str(event.maneuverValue(3)*1000), ' m/s ', optStr{3}];
                case 'finite_inertial'
                    param1Str = ['dVx = ', num2str(event.maneuverValue(1)*1000), ' m/s ', optStr{1}];
                    param2Str = ['dVy = ', num2str(event.maneuverValue(2)*1000), ' m/s ', optStr{2}];
                    param3Str = ['dVz = ', num2str(event.maneuverValue(3)*1000), ' m/s ', optStr{3}];
                case 'finite_steered'
                    param1Str = ['dVp = ', num2str(event.maneuverValue(1)*1000), ' m/s ', optStr{1}];
                    param2Str = ['dVn = ', num2str(event.maneuverValue(2)*1000), ' m/s ', optStr{2}];
                    param3Str = ['dVr = ', num2str(event.maneuverValue(3)*1000), ' m/s ', optStr{3}];
                case 'dv_inertial_spherical'
                    param1Str = ['Az. = ', num2str(rad2deg(event.maneuverValue(1))), ' deg ', optStr{1}];
                    param2Str = ['El. = ', num2str(rad2deg(event.maneuverValue(2))), ' deg ', optStr{2}];
                    param3Str = ['Mag. = ', num2str(event.maneuverValue(3)*1000), ' m/s ', optStr{3}];
                case 'dv_orbit_spherical'
                    param1Str = ['Az. = ', num2str(rad2deg(event.maneuverValue(1))), ' deg ', optStr{1}];
                    param2Str = ['El. = ', num2str(rad2deg(event.maneuverValue(2))), ' deg ', optStr{2}];
                    param3Str = ['Mag. = ', num2str(event.maneuverValue(3)*1000), ' m/s ', optStr{3}];
                case 'finite_inertial_spherical'
                    param1Str = ['Az. = ', num2str(rad2deg(event.maneuverValue(1))), ' deg ', optStr{1}];
                    param2Str = ['El. = ', num2str(rad2deg(event.maneuverValue(2))), ' deg ', optStr{2}];
                    param3Str = ['Mag. = ', num2str(event.maneuverValue(3)*1000), ' m/s ', optStr{3}];
                case 'finite_steered_spherical'
                    param1Str = ['Az. = ', num2str(rad2deg(event.maneuverValue(1))), ' deg ', optStr{1}];
                    param2Str = ['El. = ', num2str(rad2deg(event.maneuverValue(2))), ' deg ', optStr{2}];
                    param3Str = ['Mag. = ', num2str(event.maneuverValue(3)*1000), ' m/s ', optStr{3}];
            end

        case 'Mass_Dump'
            subtype = event.subType;
    end

    if(length(subtype)>13)
        subtype = [subtype(1:10),'...'];
    end
    eventInfoStr{end+1} = ['Subtype = ', subtype];
    eventInfoStr{end+1} = [' '];
    eventInfoStr{end+1} = param1Str;
    eventInfoStr{end+1} = param2Str;
    eventInfoStr{end+1} = param3Str;

    set(hVarEventInfoLabel, 'String',eventInfoStr);

% --- Executes during object creation, after setting all properties.
function optVarListbox_CreateFcn(hObject, eventdata, handles)
% hObject    handle to optVarListbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in varOptEventCheckbox.
function varOptEventCheckbox_Callback(hObject, eventdata, handles)
% hObject    handle to varOptEventCheckbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of varOptEventCheckbox
    updateVarListbox(handles);

function updateVarListbox(handles)
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    varUserData = get(handles.optVarListbox,'UserData');
    eventNum = get(handles.optVarListbox,'Value');

    lb = str2double(get(handles.lbVarText,'String'));
    if(isnan(lb))
        lb = 0;
    end
    ub = str2double(get(handles.ubVarText,'String'));
    if(isnan(ub))
        ub = 0;
    end

    eventID = ma_GetEventIDByEventNum(eventNum, maData.script);
    varUserData(eventNum, :) = [get(handles.varOptEventCheckbox,'Value'), lb, ub, eventNum, eventID];
    set(handles.optVarListbox,'UserData',varUserData);

% --- Executes on button press in optimizeMissionButton.
function optimizeMissionButton_Callback(hObject, eventdata, handles)
% hObject    handle to optimizeMissionButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');
    writeOutput = getappdata(handles.ma_MainGUI,'write_to_output_func');

    contents = cellstr(get(handles.objFuncCombo,'String'));
    selectedObjFunc = deblank(contents{get(handles.objFuncCombo,'Value')});

    contents = cellstr(get(handles.bodyObjFuncCombo,'String'));
    selectedCelBody = contents{get(handles.bodyObjFuncCombo,'Value')};
    selectedCelBodyValue = get(handles.bodyObjFuncCombo,'Value');
    if(~isempty(selectedCelBody))
        bodyID = celBodyData.(strtrim(lower(selectedCelBody))).id;
    else
        bodyID = -1;
    end

    objEventNum = get(handles.eventObjFuncCombo,'value');
    objEventID = ma_GetEventIDByEventNum(objEventNum, maData.script);

    optVarData = get(handles.optVarListbox,'UserData');
    actConsts = get(handles.actConstsListbox,'UserData');

    hWaitbar = waitbar(0,'Please wait while the optimizer initializes...');

    [maData, problem] = ma_setupOptimProblem(maData, celBodyData, hWaitbar, selectedObjFunc, bodyID, selectedCelBodyValue, objEventNum, objEventID, optVarData, actConsts);
    if(isempty(problem))
        return;
    end

    setappdata(handles.ma_MainGUI,'ma_data',maData);

    %%%%%%%
    % Get Var Strings
    %%%%%%%
    varStrs = {};
    for(i=1:length(maData.optimizer.variables{2}))
        varStr = maData.optimizer.variables{2}{i}.varStr;
        varStr = varStr(:)';
        varStrs = horzcat(varStrs,varStr); %#ok<AGROW>
    end

    %%%%%%%
    % Run optimizer!
    %%%%%%%
    set(handles.ma_MissionOptimizerGUI,'Visible','off');
    drawnow;
    waitbar(1,hWaitbar);
    close(hWaitbar);

%     ma_ObserveOptimGUI(celBodyData, problem, false, writeOutput, handles.ma_MainGUI, varStrs);
    handlesObsOptimGui = ma_ObserveOptimGUI();
    handlesObsOptimGui.ma_MainGUI = handles.ma_MainGUI;

    propNames = maData.spacecraft.propellant.names;
    lbUsAll = problem.lb;
    ubUsAll = problem.ub;

    recorder = ma_OptimRecorder();
    outputFnc = @(x, optimValues, state) ma_OptimOutputFunc(x, optimValues, state, handlesObsOptimGui, problem.objective, problem.lb, problem.ub, celBodyData, recorder, propNames, writeOutput, varStrs, lbUsAll, ubUsAll);
    problem.options.OutputFcn = outputFnc;

    executeOptimProblem(handlesObsOptimGui, problem, recorder);
    close(handlesObsOptimGui.ma_ObserveOptimGUI);

    uiresume(handles.ma_MissionOptimizerGUI);
    close(handles.ma_MissionOptimizerGUI);

% --- Executes on selection change in availConstListbox.
function availConstListbox_Callback(hObject, eventdata, handles)
% hObject    handle to availConstListbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns availConstListbox contents as cell array
%        contents{get(hObject,'Value')} returns selected item from availConstListbox
    if(strcmpi(get(handles.ma_MissionOptimizerGUI,'SelectionType'),'open'))
        addConstraintButton_Callback(handles.addConstraintButton, [], handles);
    end

% --- Executes during object creation, after setting all properties.
function availConstListbox_CreateFcn(hObject, eventdata, handles)
% hObject    handle to availConstListbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in actConstsListbox.
function actConstsListbox_Callback(hObject, eventdata, handles)
% hObject    handle to actConstsListbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns actConstsListbox contents as cell array
%        contents{get(hObject,'Value')} returns selected item from actConstsListbox
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    actConsts = get(handles.actConstsListbox,'UserData');
    value = get(handles.actConstsListbox,'value');

    if(strcmpi(get(handles.ma_MissionOptimizerGUI,'SelectionType'),'open'))
        preSize = size(actConsts);
        actConsts(all(cellfun(@isempty,actConsts),2),:) = [];
        postSize = size(actConsts);

        if(~all(preSize==postSize))
            set(handles.actConstsListbox,'UserData',actConsts);
            updateActConstListBox(handles);
            return;
        end

        try
            const = actConsts(value,:);
            type = const{end,3};
            unit = const{end,4};
            numericConstInputs = const{end,5};
            lbLim = numericConstInputs(1);
            ubLim = numericConstInputs(2);
            lbVal = numericConstInputs(3);
            ubVal = numericConstInputs(4);
            body = numericConstInputs(5);
%             eventNum = numericConstInputs(6);
            otherSC = numericConstInputs(8);
            eventID = numericConstInputs(7);

            if(length(numericConstInputs) == 8)
                lbActive = true;
                ubActive = true;
            else
                lbActive = numericConstInputs(9);
                ubActive = numericConstInputs(10);
            end
        catch
            try
                actConsts(value,:) = [];
                set(handles.actConstsListbox,'UserData',actConsts);
                updateActConstListBox(handles);
                return;
            catch
                return;
            end
        end

        [~, eventNum] = getEventByID(eventID, maData.script);
        [constFunc, lbVal, ubVal, body, otherSC, eventID, lbActive, ubActive] = ma_ConstraintDetailsGUI(handles.ma_MainGUI, type, unit, lbLim, ubLim, lbVal, ubVal, body, eventNum, otherSC, eventID, lbActive, ubActive);
        if(~isempty(constFunc))
            [~, eventNum] = getEventByID(eventID, maData.script);
            constStr = ma_getConstraintStr(type, eventNum);

            actConsts = get(handles.actConstsListbox,'UserData');
            actConsts{value,1} = constStr;
            actConsts{value,2} = [];
            actConsts{value,3} = type;
            actConsts{value,4} = unit;
            actConsts{value,5} = [lbLim, ubLim, lbVal, ubVal, body, eventNum, eventID, otherSC, lbActive, ubActive];
            set(handles.actConstsListbox,'UserData',actConsts);

            updateActConstListBox(handles);
        end
    end

% --- Executes during object creation, after setting all properties.
function actConstsListbox_CreateFcn(hObject, eventdata, handles)
% hObject    handle to actConstsListbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in addConstraintButton.
function addConstraintButton_Callback(hObject, eventdata, handles)
% hObject    handle to addConstraintButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    contents = cellstr(get(handles.availConstListbox,'String'));
    type = deblank(contents{get(handles.availConstListbox,'Value')});

    eventNum = -1;
    eventID = -1;

    [unit, lbLim, ubLim, lbVal, ubVal, body, othersc] = ma_getConstraintStaticDetails(type);
    lbActive = true;
    ubActive = true;

    [constFunc, lbVal, ubVal, body, othersc, eventID, lbActive, ubActive] = ma_ConstraintDetailsGUI(handles.ma_MainGUI, type, unit, lbLim, ubLim, lbVal, ubVal, body, eventNum, othersc, eventID, lbActive, ubActive);
    if(~isempty(constFunc))
        [~, eventNum] = getEventByID(eventID, maData.script);
        constStr = ma_getConstraintStr(type, eventNum);

        actConsts = get(handles.actConstsListbox,'UserData');
        actConsts = ma_getConstCellArr(actConsts, constStr, constFunc, type, unit, lbLim, ubLim, lbVal, ubVal, body, eventNum, eventID, othersc, lbActive, ubActive);
        set(handles.actConstsListbox,'UserData',actConsts);

        updateActConstListBox(handles);
    end

function updateActConstListBox(handles)
    actConsts = get(handles.actConstsListbox,'UserData');
    value = get(handles.actConstsListbox,'value');

    listboxStr = cell(size(actConsts,1),1);
    for(i=1:size(actConsts,1))
        listboxStr{i} = actConsts{i,1};
    end

    if(length(listboxStr)==1)
        set(handles.actConstsListbox,'String',listboxStr);
        set(handles.actConstsListbox,'value',1);
    elseif(length(listboxStr) < value)
        set(handles.actConstsListbox,'value',length(listboxStr));
        set(handles.actConstsListbox,'String',listboxStr);
    else
        set(handles.actConstsListbox,'String',listboxStr);
%         set(handles.actConstsListbox,'value',length(listboxStr));
    end

    setActConstListboxTooltip(handles);

function setActConstListboxTooltip(handles)
    actConsts = get(handles.actConstsListbox,'UserData');
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');

    tooltipStr = 'Active Constraints:\n \n';
    for(i=1:size(actConsts,1)) %#ok<*NO4LP>
        try
            constType = actConsts{i,3};
            constUnit = actConsts{i,4};
            constLB = actConsts{i,5}(3);
            constUB = actConsts{i,5}(4);
            constEventID = actConsts{i,5}(7);
            [~, constEventNum] = getEventByID(constEventID, maData.script);
            constBodyID = actConsts{i,5}(5);
        catch
            continue;
        end

        try
            otherSCID = actConsts{i,5}(8);
        catch
            otherSCID = -1;
        end

        if(length(actConsts{i,5}) == 8)
            lbActive = true;
            ubActive = true;
        else
            lbActive = actConsts{i,5}(9);
            ubActive = actConsts{i,5}(10);
        end

        if(constBodyID == -1)
            constBodyStrFull = '';
        else
            bodyInfo = getBodyInfoByNumber(constBodyID, celBodyData);
            constBodyStr = bodyInfo.name;
            constBodyStrFull = ['Body: ', constBodyStr,'\n'];
        end

        if(otherSCID == -1)
            constOSCStrFull = '';
        else
            otherSCInfo = getOtherSCInfoByID(maData, otherSCID);
            if(~isempty(otherSCInfo) && isfield(otherSCInfo,'name'))
                constOSCStr = otherSCInfo.name;
                constOSCStrFull = ['Spacecraft: ',constOSCStr,'\n'];
            else
                constOSCStrFull = '';
            end
        end

        lbActiveStr = '';
        if(lbActive == false)
            lbActiveStr = ' (Inactive)';
        end

        ubActiveStr = '';
        if(ubActive == false)
            ubActiveStr = ' (Inactive)';
        end

        lbStr = ['Lower Bnd: ', num2str(constLB), ' ', constUnit, lbActiveStr, '\n'];
        ubStr = ['Upper Bnd: ', num2str(constUB), ' ', constUnit, ubActiveStr, '\n'];

        if(constLB == 0 && constUB == 0 && isempty(constUnit) && ~strcmpi(constType, 'Eccentricity'))
            lbStr = '';
            ubStr = '';
        end

        tooltipStr = [tooltipStr,...
                      '--',constType,' Constraint--','\n'...
                      'Event: ', num2str(constEventNum),'\n',...
                      lbStr,...
                      ubStr,...
                      constBodyStrFull,...
                      constOSCStrFull,' \n']; %#ok<AGROW>
    end
    set(handles.actConstsListbox, 'TooltipString', sprintf(tooltipStr));

% --- Executes on button press in removeConstraintButton.
function removeConstraintButton_Callback(hObject, eventdata, handles)
% hObject    handle to removeConstraintButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    value = get(handles.actConstsListbox,'value');
    actConsts = get(handles.actConstsListbox,'UserData');
    if(value > 0)
        actConsts(value,:) = [];

        set(handles.actConstsListbox,'UserData',actConsts);

        updateActConstListBox(handles);
    end

% --- Executes on button press in cancelButton.
function cancelButton_Callback(hObject, eventdata, handles)
% hObject    handle to cancelButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    close(handles.ma_MissionOptimizerGUI);

function lbVarText_Callback(hObject, eventdata, handles)
% hObject    handle to lbVarText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of lbVarText as text
%        str2double(get(hObject,'String')) returns contents of lbVarText as a double
    updateVarListbox(handles);

% --- Executes during object creation, after setting all properties.
function lbVarText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to lbVarText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function ubVarText_Callback(hObject, eventdata, handles)
% hObject    handle to ubVarText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of ubVarText as text
%        str2double(get(hObject,'String')) returns contents of ubVarText as a double
    updateVarListbox(handles);

% --- Executes during object creation, after setting all properties.
function ubVarText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to ubVarText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in bodyObjFuncCombo.
function bodyObjFuncCombo_Callback(hObject, eventdata, handles)
% hObject    handle to bodyObjFuncCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns bodyObjFuncCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from bodyObjFuncCombo

% --- Executes during object creation, after setting all properties.
function bodyObjFuncCombo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to bodyObjFuncCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on key press with focus on ma_MissionOptimizerGUI or any of its controls.
function ma_MissionOptimizerGUI_WindowKeyPressFcn(hObject, eventdata, handles)
% hObject    handle to ma_MissionOptimizerGUI (see GCBO)
% eventdata  structure with the following fields (see MATLAB.UI.FIGURE)
%	Key: name of the key that was pressed, in lower case
%	Character: character interpretation of the key(s) that was pressed
%	Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed
% handles    structure with handles and user data (see GUIDATA)
    switch(eventdata.Key)
        case 'escape'
            close(handles.ma_MissionOptimizerGUI);
    end

% --------------------------------------------------------------------
function enableAllConstMenu_Callback(hObject, eventdata, handles)
% hObject    handle to enableAllConstMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    actConsts = get(handles.actConstsListbox,'UserData');
    for(i=1:size(actConsts,1))
        actConsts{i,5}(9) = 1;
        actConsts{i,5}(10) = 1;
    end
    set(handles.actConstsListbox,'UserData',actConsts);

% --------------------------------------------------------------------
function disableAllConstMenu_Callback(hObject, eventdata, handles)
% hObject    handle to disableAllConstMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    actConsts = get(handles.actConstsListbox,'UserData');
    for(i=1:size(actConsts,1))
        actConsts{i,5}(9) = 0;
        actConsts{i,5}(10) = 0;
    end
    set(handles.actConstsListbox,'UserData',actConsts);


classdef LvdPluginOptimVarWrapper < matlab.mixin.SetGet
    %LvdPluginOptimVarWrapper Summary of this class goes here
    %   Detailed explanation goes here

    properties
        name(1,:) char = 'Untitled Plugin Variable';
        value(1,1) double = 0;

        optVar PluginOptimizationVariable

        id(1,1) double = 0
    end

    methods
        function obj = LvdPluginOptimVarWrapper()
            obj.id = rand();
        end

        function optVar = getNewOptVar(obj)
            optVar = PluginOptimizationVariable(obj);
        end

        function optVar = getExistingOptVar(obj)
            optVar = obj.optVar;
        end

        function [lb, ub] = getBounds(obj)
            lb = obj.optVar.lb;
            ub = obj.optVar.ub;
        end

        function setBounds(obj, lb, ub)
            obj.optVar.lb = lb;
            obj.optVar.ub = ub;
        end

        function useTf = isVariableActive(obj)
            useTf = obj.optVar.useTf;
        end

        function setIfVariableIsActive(obj, useTf)
            obj.optVar.useTf = useTf;
        end
    end

    methods(Static)
        function obj = loadobj(obj)
            if(isempty(obj.id) || obj.id == 0)
                obj.id = rand();
            end
        end
    end
end


function gridcosts(ch,k,K,x,~)
if k==K
  ch.add(x.time);
end


function [map] = addColourNode(map, rxnList, colour)
% Add colour to all metabolites linked to a list of reaction names.
% If no colour is specified as input, 'RED' will be used by default.
% Complementary function of changeRxnColorAndWidth.m
%
% USAGE:
%
%   [map] = addColourNode(map, rxnList, color)
%
% INPUTS:
%    map:           A parsed model structure generated by
%                   'transformXML2Map' function
%    rxnlist:       List of reactions which nodes have to be coloured
%
% OPTIONAL INPUT:
%    color:         Color string. Default color being 'RED'
%
% OUTPUT:
%    map:           New parsed file with the colored entities linked
%                   to reactions list given as input
%
% .. Authors:
%       - J.modamio 18/07/2017. LCSB, Belval, Luxembourg.
%       - N.Sompairac - Institut Curie, Paris, 11/10/2017.

    if nargin < 3
        colour = 'RED';
    end

    colors = createColorsMap();
    index = find(ismember(map.rxnName, rxnList));  % find index of reactions

    % Change colour base reactants
    baseR = map.rxnBaseReactantAlias(index, 1);
    for i = 1:length(baseR)
        a = baseR{i};
        id = ismember(map.molAlias, a);
        map.molColor(id) = {colors(colour)};
    end

    % Change colour of base products
    baseP = map.rxnBaseProductAlias(index, 1);
    for i = 1:length(baseP)
        a = baseP{i};
        id = ismember(map.molAlias, a);
        map.molColor(id) = {colors(colour)};
    end

    % Change color of secondary reactants
    react = map.rxnReactantAlias(index, 1);
    for i = 1:length(react)
        a = react{i};
        id = ismember(map.molAlias, a);
        map.molColor(id) = {colors(colour)};
    end

    % Change color of secondary products
    product = map.rxnProductAlias(index, 1);
    for i = 1:length(product)
        a = product{i};
        id = ismember(map.molAlias, a);
        map.molColor(id) = {colors(colour)};
    end

    % Change color of modificators
    modif = map.rxnModAlias(index, 1);
    for i = 1:length(modif)
        a = modif{i};
        id = ismember(map.molAlias, a);
        map.molColor(id) = {colors(colour)};
    end

end


function save_hdf5(key,outfilename)
% Saves the Key to an hdf5 file.
% Inputs:
%   key: An object of type Key.
%   outfilename: The name for the output hdf5 file.

assert(nargin==2)
assert(isa(key,'Key'))
assert(isa(outfilename,'char'))
assert(key.validate())

nummods = length(key.modelset);
numsegs = length(key.segset);

assert(size(key.tar,1)==nummods)
assert(size(key.tar,2)==numsegs)

assert(size(key.non,1)==nummods)
assert(size(key.non,2)==numsegs)

tar = int8(key.tar);
non = int8(key.non);

trialmask = tar - non;

hdf5write(outfilename,'/trial_mask',trialmask,'V71Dimensions',true);
hdf5write(outfilename,'/file_format','2.0','V71Dimensions',true,'WriteMode','append');
hdf5write(outfilename,'/ID/row_ids',key.modelset,'V71Dimensions',true,'WriteMode','append');
hdf5write(outfilename,'/ID/column_ids',key.segset,'V71Dimensions',true,'WriteMode','append');


% Build the C/C++ files provided in the package
%
% @author: B. Schauerte
% @date:   2009
% @url:    http://cvhci.anthropomatik.kit.edu/~bschauer/

cpp_files=dir('*.cpp');
for i=1:length(cpp_files)
  fprintf('Building %d of %d: %s\n',i,length(cpp_files),cpp_files(i).name);
  mex(cpp_files(i).name);
end


function Z = loadAudio(paths)
% Syntax:   Z = loadAudio(paths);

% Parse inputs
p = numel(paths);

% Load audio
audio = cell(1,p);
for i = 1:p
    path = paths{i};
    [~,~,ext] = fileparts(path);
    if strcmpi(ext,'.wav')
        % Load from .wav file
        audio{i} = audioread(path,'double');
    elseif strcmpi(ext,'.mat')
        % Load from .mat file
        data = load(path);
        fields = fieldnames(data);
        audio{i} = data.(fields{1});
    else
        % Unsupported extension
        error('Unsupported extension ''%s''',ext);
    end
end

% Determine sample length
nSamples = cellfun(@numel,audio);
n = min(nSamples);

% Construct audio matrix
Z = zeros(p,n);
for i = 1:p
    ni     = nSamples(i);
    gapL   = floor(0.5 * (ni - n));
    gapR   = ceil( 0.5 * (ni - n));
    Z(i,:) = audio{i}((gapL + 1):(ni - gapR));
end

% Normalize audio
Z = normalizeAudio(Z);


function varargout=lpcss2zz(varargin)
%
% For calling details please see v_lpcss2zz.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_lpcss2zz.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: lpcss2zz.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_lpcss2zz(varargin{:});
else
    v_lpcss2zz(varargin{:});
end


function systemsound(string)
% systemsound v 1.0.0
% Programmed by Drew Weymouth
%
% Plays a Microsoft Windows system sound specified by an input string.
%   string may be an exact filename of a .wav file in the C:\Windows\Media directory
%   or a string with the "Windows" prefix removed from the filename.
%   Input string is case insensitive, and need not include '.wav' extension.
% Examples:
%   systemsound('critical stop')
%   systemsound('exclamation')
% Please Note: 'notify' and 'windows notify' are different sounds
%   likewise, 'recycle' and 'windows recycle', 'ringin' and 'windows ringin',
%   and 'ding' and 'windows ding' are different.
% Tested with Windows 7, results may vary for older versions.

dir= 'C:\Windows\Media\';
string= lower(string);
try [y,fs]= wavread(sprintf('%s%s',dir,string));
catch
    try [y,fs]= wavread(sprintf('%swindows %s',dir,string));
    catch, error('Invalid selection.')
    end
end
sound(y,fs,16)

end