function transformMap2XML(xmlStruct, map, fileName)
% Creates a new XML file from the information contained in the map
% structure. Uses the function "struct2xml" to transform a matlab
% structure into an XML text format.
%
% USAGE:
%
%   transformMap2XML(xmlStruct, map, fileName)
%
% INPUTS:
%   xmlStruct:      XML structure obtained from the function
%                   "xml2struct". Used by the function "struct2xml"
%                   to obtain the XML file.
%   map:            Matlab structure of the map with the relevant
%                   information. This information is then transfered to
%                   the xmlStruct for the conversion.
%   fileName:       Path and name of the new XML file.
%
% .. Author: - N.Sompairac - Institut Curie, Paris, 24/07/2017

tic

if strcmp('~',fileName(1))
    savedPath=pwd;
    cd('~')
    homePath=pwd;
    fileName = strrep(fileName,'~',homePath);
    cd(savedPath)
end

% Loop over molecules to put the info back to the struct for XML
% conversion
for mol = 1:length(map.molAlias)
    xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfSpeciesAliases.celldesigner_colon_speciesAlias{mol}.Attributes.id = map.molAlias{mol};
    xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfSpeciesAliases.celldesigner_colon_speciesAlias{mol}.Attributes.species = map.molID{mol};
    % Check if the info on compartment exists
    if ~isempty(map.molCompartAlias{mol})
        xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfSpeciesAliases.celldesigner_colon_speciesAlias{mol}.Attributes.compartmentAlias = map.molCompartAlias{mol};
    end
    xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfSpeciesAliases.celldesigner_colon_speciesAlias{mol}.celldesigner_colon_bounds.Attributes.x = map.molXPos{mol};
    xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfSpeciesAliases.celldesigner_colon_speciesAlias{mol}.celldesigner_colon_bounds.Attributes.y = map.molYPos{mol};
    xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfSpeciesAliases.celldesigner_colon_speciesAlias{mol}.celldesigner_colon_bounds.Attributes.w = map.molWidth{mol};
    xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfSpeciesAliases.celldesigner_colon_speciesAlias{mol}.celldesigner_colon_bounds.Attributes.h = map.molHeight{mol};
    xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfSpeciesAliases.celldesigner_colon_speciesAlias{mol}.celldesigner_colon_usualView.celldesigner_colon_paint.Attributes.color = map.molColor{mol};
end
clearvars mol

% Loop over species to put the info back to the struct for XML
% conversion
for spec = 1:length(map.specID)
    xmlStruct.sbml.model.listOfSpecies.species{spec}.Attributes.id = map.specID{spec};
    xmlStruct.sbml.model.listOfSpecies.species{spec}.Attributes.metaid = map.specMetaID{spec};
    xmlStruct.sbml.model.listOfSpecies.species{spec}.Attributes.name = map.specName{spec};
    xmlStruct.sbml.model.listOfSpecies.species{spec}.annotation.celldesigner_colon_extension.celldesigner_colon_speciesIdentity.celldesigner_colon_name.Text = map.specName{spec};
    xmlStruct.sbml.model.listOfSpecies.species{spec}.annotation.celldesigner_colon_extension.celldesigner_colon_speciesIdentity.celldesigner_colon_class.Text = map.specType{spec};
    % Check if there are notes for the specie
    if ~isempty(map.specNotes{spec})
        xmlStruct.sbml.model.listOfSpecies.species{spec}.notes.html.body.Text = map.specNotes{spec};
    end
end
clearvars spec

for r = 1:length(map.rxnID)
    lt=length(xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfReactants.speciesReference);
    if lt==1
        if strcmp(xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfReactants.speciesReference.annotation.celldesigner_colon_extension.celldesigner_colon_alias.Text,map.molAlias)
            error('removing only substrate in reaction')
        end
    else
        bool=true(lt,1);
        for s=1:lt
            if ~any(strcmp(xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfReactants.speciesReference{s}.annotation.celldesigner_colon_extension.celldesigner_colon_alias.Text,map.molAlias))
                bool(s)=0;
            end
        end
        xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfReactants.speciesReference =xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfReactants.speciesReference(bool);
    end
%     if ~iscell(xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfReactants.speciesReference)
%         xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfReactants.speciesReference
%     end

    lt=length(xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfProducts.speciesReference);
    if lt==1
        if strcmp(xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfProducts.speciesReference.annotation.celldesigner_colon_extension.celldesigner_colon_alias.Text,map.molAlias)
            error('removing only product in reaction')
        end
    else
        bool=true(lt,1);
        for s=1:lt
            if ~any(strcmp(xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfProducts.speciesReference{s}.annotation.celldesigner_colon_extension.celldesigner_colon_alias.Text,map.molAlias))
                bool(s)=0;
            end
        end
        xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfProducts.speciesReference =xmlStruct.sbml.model.listOfReactions.reaction{r}.listOfProducts.speciesReference(bool);
    end

end

% Loop over reactions to put the info back to the struct for XML
% conversion
for react = 1:length(map.rxnID)
    % Check if there is a reaction ID
    if ~isempty(map.rxnID{react})
        xmlStruct.sbml.model.listOfReactions.reaction{react}.Attributes.id = map.rxnID{react};
    else
        xmlStruct.sbml.model.listOfReactions.reaction{react}.Attributes.id = 'No_ID';
    end
    xmlStruct.sbml.model.listOfReactions.reaction{react}.Attributes.metaid = map.rxnMetaID{react};

    % Check if the reaction has a Name
    if ~isempty(map.rxnName{react})
        xmlStruct.sbml.model.listOfReactions.reaction{react}.Attributes.name = map.rxnName{react};
        xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_name.Text = map.rxnName{react};
    else
        xmlStruct.sbml.model.listOfReactions.reaction{react}.Attributes.name = 'No_Name';
        xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_name.Text = 'No_Name';
    end
    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_reactionType.Text = map.rxnType{react};
    if strcmp(map.rxnReversibility{react},'false')
        xmlStruct.sbml.model.listOfReactions.reaction{react}.Attributes.reversible = map.rxnReversibility{react};
    end
    % Test if there is only 1 base reactant
    if length(map.rxnBaseReactantAlias{react}) == 1
        xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_baseReactants.celldesigner_colon_baseReactant(1).Attributes.alias = map.rxnBaseReactantAlias{react}{1};
        xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_baseReactants.celldesigner_colon_baseReactant(1).Attributes.species = map.rxnBaseReactantID{react}{1};
    else
        for x = 1:length(map.rxnBaseReactantAlias{react})
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_baseReactants.celldesigner_colon_baseReactant{x}.Attributes.alias = map.rxnBaseReactantAlias{react}{x};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_baseReactants.celldesigner_colon_baseReactant{x}.Attributes.species = map.rxnBaseReactantID{react}{x};
        end
        clearvars x
    end

    % Test if there is only 1 base product
    if length(map.rxnBaseProductAlias{react}) == 1
        xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_baseProducts.celldesigner_colon_baseProduct(1).Attributes.alias = map.rxnBaseProductAlias{react}{1};
        xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_baseProducts.celldesigner_colon_baseProduct(1).Attributes.species = map.rxnBaseProductID{react}{1};
    else
        for x = 1:length(map.rxnBaseProductAlias{react})
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_baseProducts.celldesigner_colon_baseProduct{x}.Attributes.alias = map.rxnBaseProductAlias{react}{x};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_baseProducts.celldesigner_colon_baseProduct{x}.Attributes.species = map.rxnBaseProductID{react}{x};
        end
    end

    % Test if there are some reactants in the reaction
    if ~isempty(map.rxnReactantAlias{react})
        % Test if there is only 1 reactant
        if length(map.rxnReactantAlias{react}) == 1
            %needed if there is a reduction in number of reactant aliases
            if iscell(xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink)
                xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink=xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink{1};
            end
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink(1).Attributes.alias = map.rxnReactantAlias{react}{1};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink(1).Attributes.reactant = map.rxnReactantID{react}{1};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink(1).celldesigner_colon_line.Attributes.color = map.rxnColor{react};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink(1).celldesigner_colon_line.Attributes.width = map.rxnWidth{react};
        else
            for x = 1:length(map.rxnReactantAlias{react})
                if length(map.rxnReactantAlias{react})== length(xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink)-1
                    error('inconsistent reactant aliases')
                end
                if iscell(xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink)
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink{x}.Attributes.alias = map.rxnReactantAlias{react}{x};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink{x}.Attributes.reactant = map.rxnReactantID{react}{x};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink{x}.celldesigner_colon_line.Attributes.color = map.rxnColor{react};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink{x}.celldesigner_colon_line.Attributes.width = map.rxnWidth{react};
                else
                    error('should not be cell')
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink(x).Attributes.alias = map.rxnReactantAlias{react}{x};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink(x).Attributes.reactant = map.rxnReactantID{react}{x};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink(x).celldesigner_colon_line.Attributes.color = map.rxnColor{react};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfReactantLinks.celldesigner_colon_reactantLink(x).celldesigner_colon_line.Attributes.width = map.rxnWidth{react};
                end
            end
            clearvars x
        end
    end

    % Test if there are some products in the reaction
    if ~isempty(map.rxnProductAlias{react})
        % Test if there is only 1 product
        if length(map.rxnProductAlias{react}) == 1
            %needed if there is a reduced number of product aliases
            if iscell(xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink)
                xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink=xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink{1};
            end
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink(1).Attributes.alias = map.rxnProductAlias{react}{1};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink(1).Attributes.product = map.rxnProductID{react}{1};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink(1).celldesigner_colon_line.Attributes.color = map.rxnColor{react};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink(1).celldesigner_colon_line.Attributes.width = map.rxnWidth{react};
        else
            for x = 1:length(map.rxnProductAlias{react})
                if length(map.rxnProductAlias{react})== length(xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink)-1
                    error('inconsistent product aliases')
                end
                if iscell(xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink)
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink{x}.Attributes.alias = map.rxnProductAlias{react}{x};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink{x}.Attributes.product = map.rxnProductID{react}{x};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink{x}.celldesigner_colon_line.Attributes.color = map.rxnColor{react};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink{x}.celldesigner_colon_line.Attributes.width = map.rxnWidth{react};
                else
                    error('should not be cell')
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink(x).Attributes.alias = map.rxnProductAlias{react}{x};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink(x).Attributes.product = map.rxnProductID{react}{x};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink(x).celldesigner_colon_line.Attributes.color = map.rxnColor{react};
                    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfProductLinks.celldesigner_colon_productLink(x).celldesigner_colon_line.Attributes.width = map.rxnWidth{react};
                end
            end
            clearvars x
        end
    end

    % Check if there are modifications for the reaction
    if ~isempty(map.rxnModAlias{react})
        % Test if there is only one modification
        if length(map.rxnModAlias{react}) == 1
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification(1).Attributes.aliases = map.rxnModAlias{react}{1};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification(1).Attributes.modifiers = map.rxnModID{react}{1};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification(1).Attributes.type = map.rxnModType{react}{1};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification(1).celldesigner_colon_line.Attributes.color = map.rxnModColor{react}{1};
            xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification(1).celldesigner_colon_line.Attributes.width = map.rxnModWidth{react}{1};
        else
            for m = 1:length(map.rxnModAlias{react})
                xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification{m}.Attributes.aliases = map.rxnModAlias{react}{m};
                xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification{m}.Attributes.modifiers = map.rxnModID{react}{m};
                xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification{m}.Attributes.type = map.rxnModType{react}{m};
                xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification{m}.celldesigner_colon_line.Attributes.color = map.rxnModColor{react}{m};
                xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_listOfModification.celldesigner_colon_modification{m}.celldesigner_colon_line.Attributes.width = map.rxnModWidth{react}{m};
            end
            clearvars m
        end
    end

    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_line.Attributes.color = map.rxnColor{react};
    xmlStruct.sbml.model.listOfReactions.reaction{react}.annotation.celldesigner_colon_extension.celldesigner_colon_line.Attributes.width = map.rxnWidth{react};

    % Check if there are notes for the reaction
    if ~isempty(map.rxnNotes{react})
        xmlStruct.sbml.model.listOfReactions.reaction{react}.notes.html.body.Text = map.rxnNotes{react};
    end
end
clearvars react

% Check if there is any information on Compartments
if ~isempty(map.compartAlias)
    % Test if there is only 1 compartment
    if length(map.compartAlias) == 1
        xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfCompartmentAliases.celldesigner_colon_compartmentAlias(1).Attributes.id = map.compartAlias{1};
        xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfCompartmentAliases.celldesigner_colon_compartmentAlias(1).Attributes.compartment = map.compartName{1};
    else
        % Loop over compartments to put the info back to the struct for XML
        % conversion
        for compart = 1:length(map.compartAlias)
            xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfCompartmentAliases.celldesigner_colon_compartmentAlias{compart}.Attributes.id = map.compartAlias{compart};
            xmlStruct.sbml.model.annotation.celldesigner_colon_extension.celldesigner_colon_listOfCompartmentAliases.celldesigner_colon_compartmentAlias{compart}.Attributes.compartment = map.compartName{compart};
        end
        clearvars compart
    end
end

struct2xml(xmlStruct, fileName);
toc


classdef MimLevelSlider < MimGuiPluginSlider
    % MimLevelSlider. Gui Plugin for changing overlay opacity
    %
    %     You should not use this class within your own code. It is intended to
    %     be used by the gui of the TD MIM Toolkit.
    %
    %     MimLevelSlider is a Gui Plugin for changing the value of the
    %     window used to display the greyscale image
    %
    %
    %     Licence
    %     -------
    %     Part of the TD MIM Toolkit. https://github.com/tomdoel
    %     Author: Tom Doel, Copyright Tom Doel 2014.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    properties
        ButtonText = 'Level'
        SelectedText = 'Level'
        ToolTip = 'Change the level'
        Category = 'Window / Level'
        Visibility = 'Dataset'
        Mode = 'Toolbar'

        HidePluginInDisplay = false
        PTKVersion = '1'
        ButtonWidth = 6
        ButtonHeight = 1
        Location = 26

        MinValue = 0
        MaxValue = 100
        SmallStep = 0.01
        LargeStep = 0.1
        DefaultValue = 50

        EditBoxPosition = 50
        EditBoxWidth = 40

        StackVertically = true
    end

    methods (Static)
        function RunGuiPlugin(gui_app)
        end

        function enabled = IsEnabled(gui_app)
            enabled = gui_app.IsDatasetLoaded && ~strcmp(gui_app.ImagePanel.Mode, MimModes.View3DMode);
        end

        function is_selected = IsSelected(gui_app)
            is_selected = true;
        end

        function [value_instance_handle, value_property_name, limits_instance_handle, limits_property_name] = GetHandleAndProperty(gui_app)
            value_instance_handle = gui_app.ImagePanel.GetBackgroundImageDisplayParameters;
            value_property_name = 'Level';
            limits_instance_handle = gui_app.ImagePanel;
            limits_property_name = 'LevelLimits';
        end

    end
end


% Functions enabling use of multiple colormaps per figure.
%
% version 2.3, 3/2007
%
%   freezeColors    - Lock colors of plot, enabling multiple colormaps per figure.
%   unfreezeColors  - Restore colors of a plot to original indexed color.
%
% demo/html
%   freezeColors_pub.html   - Published demonstration.
%
% test
%   test_main       - Test function.

% AUTHOR
% John Iversen, 2005-10
% john_iversen@post.harvard.edu
%
% Free for any use, so long as AUTHOR information remains with code.
%
% HISTORY
%
% JRI 6/2005  (v1)
% JRI 9/2006  (v2.1) now operates on all objects with CData (not just images as before)
% JRI 11/2006 handle NaNs in images/surfaces (was not posted on file exchange, included in v2.3)
% JRI 3/2007  (v2.3) Fix bug in handling of caxis that made colorbar scales on frozen plots incorrect.
% JRI 4/2007  Add 'published' html documentation.
% JRI 9/2010  Changed documentation for colorbars


function this = MrDimInfo_get_add_remove(this)
% Unit test for MrDimInfo get, add and remove method
%
%   Y = MrUnitTest()
%   run(Y, 'MrDimInfo_get_add_remove')
%
% This is a method of class MrUnitTest.
%
% IN
%
% OUT
%
% EXAMPLE
%   MrDimInfo_methods
%
%   See also MrUnitTest

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

% construct MrDimInfo object from sampling points
dimInfo = this.make_dimInfo_reference(0);

% define expected solution
expSolution = dimInfo.copyobj;

% get, remove and add dims

% get dimInfo along x
dimInfoX = dimInfo.get_dims('x');

% remove x from dimInfo
dimInfo.remove_dims('x');

% add x back to dimInfo
dimInfo.add_dims(1, 'samplingPoints', dimInfoX.samplingPoints{1}, ...
    'dimLabels', dimInfoX.dimLabels{1}, 'units', dimInfoX.units{1});

% define actual solution
actSolution = dimInfo;

% verify whether expected and actual solution are identical
% Note: convert to struct, since the PublicPropertyComparator (to allow
% nans to be treated as equal) does not compare properties of objects that
% overload subsref

warning('off', 'MATLAB:structOnObject');
this.verifyEqual(struct(actSolution), struct(expSolution), 'absTol', 10e-7);
warning('on', 'MATLAB:structOnObject');

end


% POP_SAVEH - save the EEGLAB session command history stored in ALLCOM
%               or in the 'history' field of the current dataset
%
% Usage:
%   >> pop_saveh( ALLCOM, filename, filepath);
%   >> pop_saveh( EEG.history, filename, filepath);
%
% Inputs:
%   ALLCOM      - cell array of strings containing the EEGLAB command history
%   EEG.history - history field of the current dataset
%   filename    - name of the file to save to (optional, default "eeglabhist.m"
%   filepath    - path of the file to save to (optional, default pwd)
%
% Author: Arnaud Delorme, CNL / Salk Institute, 22 March 2002
%
% See also: EEGH, EEGLAB

% Copyright (C) 22 March 2002 Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% 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 HOLDER 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.

% 01-25-02 reformated help & license -ad
% 03-29-02 added update menu -ad

function com = pop_saveh( allcoms, curfilename, curfilepath);

com = '';
if nargin < 1
	help pop_saveh;
	return;
end

if nargin < 3
	[curfilename, curfilepath] = uiputfile('eeglabhist.m', 'Save the EEGLAB session command history with .m extension -- pop_saveh()');
    drawnow;
	if curfilename == 0 return; end
end

fid = fopen( [ curfilepath '/' curfilename ], 'w');
if fid == -1
    error('pop_saveh(): Cannot open named file');
end;
fprintf(fid, '%% EEGLAB history file generated on the %s\n', date);
fprintf(fid, '%% ------------------------------------------------\n');
if iscell(allcoms)
    disp('Saving the EEGLAB session command history...');
    for index = length(allcoms):-1:1
        fprintf(fid, '%s\n', allcoms{index});
    end
    fprintf(fid, 'eeglab redraw;\n');
else
    disp('Saving the current EEG dataset command history...');
    fprintf(fid, '%s\n', allcoms);
end
fclose(fid);

if iscell(allcoms) && nargout == 1
    com = sprintf('pop_saveh( %s, ''%s'', ''%s'');', inputname(1), curfilename, curfilepath);
else
    com = sprintf('pop_saveh( EEG.history, ''%s'', ''%s'');', curfilename, curfilepath);
end

return;


classdef PTKMetrics < dynamicprops
    % PTKMetrics. A structure for holding data analysis results
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties (SetAccess = private)
        MetricNameMap
    end

    methods
        function obj = PTKMetrics
            obj.MetricNameMap = containers.Map;
        end

        function AddMetric(obj, property_name, value, user_visible_name)
            valid_property_name = CoreTextUtilities.CreateValidFieldName(property_name);
            obj.addprop(valid_property_name);
            obj.(valid_property_name) = value;
            obj.MetricNameMap(valid_property_name) = user_visible_name;
        end

        function property_list = GetListOfMetrics(obj)
            property_list = properties(obj);
            property_list = setdiff(property_list, 'MetricNameMap');
        end

        function Merge(obj, metrics, reporting, prefix, user_visible_prefix)
            if nargin < 4
                prefix = [];
                user_visible_prefix = [];
            end
            if ~isa(metrics, 'PTKMetrics')
                reporting.Error('PTKMetrics:NotAMetricsClass', 'The argument passed to Merge() was not of type PTKMetrics');
            end

            metric_list = metrics.GetListOfMetrics;
            for i = 1 : length(metric_list)
                metric = metric_list{i};
                obj.AddMetric([prefix, metric], metrics.(metric), [user_visible_prefix, metrics.MetricNameMap(metric)]);
            end
        end
    end

    methods (Static)
        function results = MergeResults(results_1, results_2)
            if isempty(results_2)
                results = results_1;
            else
                metric_names = unique([fieldnames(results_1), fieldnames(results_2)]);
                results = [];
                for metric_cell = metric_names'
                    metric_name = metric_cell{1};
                    if isfield(results_1, metric_name)
                        results.(metric_name) = results_1.(metric_name);
                    end
                    if isfield(results, metric_name)
                        if isfield(results_2, metric_name)
                            results.(metric_name).Merge(results_2.(metric_name))
                        else
                            results.(metric_name) = results_2.(metric_name);
                        end
                    end
                end
            end
        end
    end
end


function obj = subsasgn(obj,subs,dat)
% Overloaded subsasgn function for file_array objects
%__________________________________________________________________________
% Copyright (C) 2005-2013 Wellcome Trust Centre for Neuroimaging

%
% $Id: subsasgn.m 6157 2014-09-05 18:17:54Z guillaume $

if isempty(subs), return; end

%-Subscript types '.' or '{}'
%==========================================================================
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

%-Subscript type '()'
%==========================================================================
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

%-Index vectors
%--------------------------------------------------------------------------
dm   = [dm ones(1,16)];
di   = ones(1,16);
args = cell(1,length(subs.subs));
for i=1:length(subs.subs)
    if ischar(subs.subs{i})
        if ~strcmp(subs.subs{i},':')
            error('Invalid subscript value.');
        end
        args{i} = int32(1:dm(i));
    else
        args{i} = int32(subs.subs{i});
    end
    di(i) = length(args{i});
end

%-Check read/write permissions
%--------------------------------------------------------------------------
for j=1:length(sobj)
    if strcmp(sobj(j).permission,'ro')
        error('Array is read-only.');
    end
end

%-Perform the assignment
%--------------------------------------------------------------------------
if length(sobj)==1
    sobj.dim = dm;
    if numel(dat)~=1
        subfun(sobj,double(dat),args{:});
    else
        dat = repmat(double(dat),di);
        subfun(sobj,dat,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

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

%-Get datatype
%--------------------------------------------------------------------------
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

%-Apply DC offset
%--------------------------------------------------------------------------
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

%-Apply scalefactor
%--------------------------------------------------------------------------
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

%-Convert data into output datatype
%--------------------------------------------------------------------------
if dt(ind).isint, dat = round(dat); end

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

%-Write data to file
%--------------------------------------------------------------------------
nelem = dt(ind).nelem;
if nelem==1
    mat2file(sobj,dat,va{:});

    %if sobj.be, swap = @(x) swapbytes(x); else swap = @(x) x; end
    %m = memmapfile(sobj.fname, 'Format', {dt(ind).prec, sobj.dim,'dat'}, ...
    %       'Offset', sobj.offset, 'Writable', true);
    %m.Data.dat = subsasgn(m.Data.dat, substruct('()',va), swap(dat));
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

%==========================================================================
% function obj = asgn(obj,fun,subs,dat)
%==========================================================================
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


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

function s=randstr()
    s=char(ceil(rand(1,20)*20+64));

function test_config_unable_to_find_file()
    fn=tempname();
    assertExceptionThrown(@()cosmo_config(fn),'');

function test_config_unable_to_open_file()
    dirname=fileparts(mfilename('fullpath'));
    assertExceptionThrown(@()cosmo_config(dirname),'');

function test_config_reading_empty()
    helper_write_read_config(false);

function test_config_reading_with_paths()
    helper_write_read_config(true);

function s=helper_generate_config(n_keys,include_keys)
    s=struct();
    for k=1:n_keys
        if k<=numel(include_keys)
            key=include_keys{k};
            value=pwd();
        else
            key=randstr();
            value=randstr();
        end
        s.(key)=value;
    end

function tmp_fn=helper_write_config(c, suffix)
    tmp_fn=tempname();
    fid=fopen(tmp_fn,'w');
    file_closer=onCleanup(@()fclose(fid));

    key_value_pairs_cell=cellfun(@(key)sprintf('%s=%s\n',key,c.(key)),...
                                fieldnames(c),...
                                'UniformOutput',false);
    fprintf(fid,'%s',key_value_pairs_cell{:});
    fprintf(fid,'%s',suffix);

function test_error_when_quote_in_paths()
    orig_warning_state=cosmo_warning();
    warning_state_resetter=onCleanup(@()cosmo_warning(orig_warning_state));
    cosmo_warning('off');

    for with_path_suffix=[true false]
        key=randstr();
        if with_path_suffix
            key=[key '_path'];
        end

        around_chars={'','''','"'};
        for k=1:numel(around_chars)
            c=around_chars{k};

            value=randstr();
            config=struct();
            config.(key)=[c value c];

            fn=helper_write_config(config,'');
            cleaner=onCleanup(@()delete(fn));

            f_handle=@()cosmo_config(fn);
            if numel(c)>0
                assertExceptionThrown(f_handle,'');
            else
                f_handle();
            end

            clear cleaner
        end
    end

function helper_write_read_config(include_path_settings, config)
    orig_warning_state=cosmo_warning();
    warning_state_resetter=onCleanup(@()cosmo_warning(orig_warning_state));

    cosmo_warning('reset');
    cosmo_warning('off');

    n_keys=ceil(rand()*5+5);

    if include_path_settings
        include_keys={'tutorial_data_path','output_data_path'};
    else
        include_keys={};
    end

    % generate and write config
    if nargin<=2
        config=helper_generate_config(n_keys,include_keys);
    end

    tmp_fn=helper_write_config(config, '# this is a comment');
    file_deleter=onCleanup(@()delete(tmp_fn));

    % read configuration
    [c,read_tmp_fn]=cosmo_config(tmp_fn);
    assertEqual(c,config);
    assertEqual(read_tmp_fn,tmp_fn);

    w=cosmo_warning();
    if include_path_settings
        % no warnign shown
        assert(isempty(w.shown_warnings));
    else
        % warning must have been shown if not include path settings
        assert(numel(w.shown_warnings)>0);
        assert(iscellstr(w.shown_warnings))
    end

    % add one key-value pair
    c2=c;
    key=randstr();
    c2.(key)=randstr();

    % write and read new configuration
    cosmo_config(tmp_fn,c2);
    c3=cosmo_config(tmp_fn);

    % should be different with missing key-value pair
    assert(~isequal(c,c3));

    % should be the same
    assertEqual(c2,c3);


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

    enumeration
        Minimize('Minimize')
        Maximize('Maximize')
    end

    properties
        name(1,:) char
    end

    methods
        function obj = ObjFcnDirectionTypeEnum(name)
            obj.name = name;
        end
    end

    methods(Static)
        function listBoxStr = getListBoxStr()
            m = enumeration('ObjFcnDirectionTypeEnum');
            [~,I] = sort({m.name});
            listBoxStr = {m(I).name};
        end

        function [ind, enum] = getIndForName(name)
            m = enumeration('ObjFcnDirectionTypeEnum');
            [~,I] = sort({m.name});
            m = m(I);
            ind = find(ismember({m.name},name),1,'first');
            enum = m(ind);
        end

        function [enum, ind] = getEnumForListboxStr(nameStr)
            m = enumeration('ObjFcnDirectionTypeEnum');
            ind = find(ismember({m.name},nameStr),1,'first');
            enum = m(ind);
        end
    end
end


function eeg_write_scan41(f,filename)

% eeg_write_scan41 - Write a Neuroscan 'scan4.1' average file
%
% Useage: eeg_write_scan41(f,filename)
%
% where:    filename is a complete 'path\fileprefix.ext' string;
%           the file will be a neuroscan 4.1 avg file.
%
%           f is a structure containing:
%
%               f.header
%               f.electloc
%               f.data
%               f.variance
%               f.tag
%
%           See companion function: eeg_load_scan4_avg.m
%

% $Revision: 1.1 $ $Date: 2009-04-28 22:13:54 $

% Licence:  GNU GPL, no implied or express warranties
% Created:  08/2000, Sean Fitzgibbon <psspf@id.psy.flinders.edu.au>
% Modified: 08/2001, Darren.Weber_at_radiology.ucsf.edu
%                    distribute under GPL, with Sean's permission
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fid = fopen(filename,'w');

fwrite(fid,f.header.rev,'char');
fwrite(fid,f.header.nextfile,'long');
fwrite(fid,f.header.prevfile,'long');
fwrite(fid,f.header.type,'char');
fwrite(fid,f.header.id,'char');
fwrite(fid,f.header.oper,'char');
fwrite(fid,f.header.doctor,'char');
fwrite(fid,f.header.referral,'char');
fwrite(fid,f.header.hospital,'char');
fwrite(fid,f.header.patient,'char');
fwrite(fid,f.header.age,'short');
fwrite(fid,f.header.sex,'char');
fwrite(fid,f.header.hand,'char');
fwrite(fid,f.header.med,'char');
fwrite(fid,f.header.category,'char');
fwrite(fid,f.header.state,'char');
fwrite(fid,f.header.label,'char');
fwrite(fid,f.header.date,'char');
fwrite(fid,f.header.time,'char');
fwrite(fid,f.header.mean_age,'float');
fwrite(fid,f.header.stdev,'float');
fwrite(fid,f.header.n,'short');
fwrite(fid,f.header.compfile,'char');
fwrite(fid,f.header.spectwincomp,'float');
fwrite(fid,f.header.meanaccuracy,'float');
fwrite(fid,f.header.meanlatency,'float');
fwrite(fid,f.header.sortfile,'char');
fwrite(fid,f.header.numevents,'int');
fwrite(fid,f.header.compoper,'char');
fwrite(fid,f.header.avgmode,'char');
fwrite(fid,f.header.review,'char');
fwrite(fid,f.header.nsweeps,'ushort');
fwrite(fid,f.header.compsweeps,'ushort');
fwrite(fid,f.header.acceptcnt,'ushort');
fwrite(fid,f.header.rejectcnt,'ushort');
fwrite(fid,f.header.pnts,'ushort');
fwrite(fid,f.header.nchannels,'ushort');
fwrite(fid,f.header.avgupdate,'ushort');
fwrite(fid,f.header.domain,'char');
fwrite(fid,f.header.variance,'char');
fwrite(fid,f.header.rate,'ushort');
fwrite(fid,f.header.scale,'double');
fwrite(fid,f.header.veogcorrect,'char');
fwrite(fid,f.header.heogcorrect,'char');
fwrite(fid,f.header.aux1correct,'char');
fwrite(fid,f.header.aux2correct,'char');
fwrite(fid,f.header.veogtrig,'float');
fwrite(fid,f.header.heogtrig,'float');
fwrite(fid,f.header.aux1trig,'float');
fwrite(fid,f.header.aux2trig,'float');
fwrite(fid,f.header.heogchnl,'short');
fwrite(fid,f.header.veogchnl,'short');
fwrite(fid,f.header.aux1chnl,'short');
fwrite(fid,f.header.aux2chnl,'short');
fwrite(fid,f.header.veogdir,'char');
fwrite(fid,f.header.heogdir,'char');
fwrite(fid,f.header.aux1dir,'char');
fwrite(fid,f.header.aux2dir,'char');
fwrite(fid,f.header.veog_n,'short');
fwrite(fid,f.header.heog_n,'short');
fwrite(fid,f.header.aux1_n,'short');
fwrite(fid,f.header.aux2_n,'short');
fwrite(fid,f.header.veogmaxcnt,'short');
fwrite(fid,f.header.heogmaxcnt,'short');
fwrite(fid,f.header.aux1maxcnt,'short');
fwrite(fid,f.header.aux2maxcnt,'short');
fwrite(fid,f.header.veogmethod,'char');
fwrite(fid,f.header.heogmethod,'char');
fwrite(fid,f.header.aux1method,'char');
fwrite(fid,f.header.aux2method,'char');
fwrite(fid,f.header.ampsensitivity,'float');
fwrite(fid,f.header.lowpass,'char');
fwrite(fid,f.header.highpass,'char');
fwrite(fid,f.header.notch,'char');
fwrite(fid,f.header.autoclipadd,'char');
fwrite(fid,f.header.baseline,'char');
fwrite(fid,f.header.offstart,'float');
fwrite(fid,f.header.offstop,'float');
fwrite(fid,f.header.reject,'char');
fwrite(fid,f.header.rejstart,'float');
fwrite(fid,f.header.rejstop,'float');
fwrite(fid,f.header.rejmin,'float');
fwrite(fid,f.header.rejmax,'float');
fwrite(fid,f.header.trigtype,'char');
fwrite(fid,f.header.trigval,'float');
fwrite(fid,f.header.trigchnl,'char');
fwrite(fid,f.header.trigmask,'short');
fwrite(fid,f.header.trigisi,'float');
fwrite(fid,f.header.trigmin,'float');
fwrite(fid,f.header.trigmax,'float');
fwrite(fid,f.header.trigdir,'char');
fwrite(fid,f.header.autoscale,'char');
fwrite(fid,f.header.n2,'short');
fwrite(fid,f.header.dir,'char');
fwrite(fid,f.header.dispmin,'float');
fwrite(fid,f.header.dispmax,'float');
fwrite(fid,f.header.xmin,'float');
fwrite(fid,f.header.xmax,'float');
fwrite(fid,f.header.automin,'float');
fwrite(fid,f.header.automax,'float');
fwrite(fid,f.header.zmin,'float');
fwrite(fid,f.header.zmax,'float');
fwrite(fid,f.header.lowcut,'float');
fwrite(fid,f.header.highcut,'float');
fwrite(fid,f.header.common,'char');
fwrite(fid,f.header.savemode,'char');
fwrite(fid,f.header.manmode,'char');
fwrite(fid,f.header.ref,'char');
fwrite(fid,f.header.rectify,'char');
fwrite(fid,f.header.displayxmin,'float');
fwrite(fid,f.header.displayxmax,'float');
fwrite(fid,f.header.phase,'char');
fwrite(fid,f.header.screen,'char');
fwrite(fid,f.header.calmode,'short');
fwrite(fid,f.header.calmethod,'short');
fwrite(fid,f.header.calupdate,'short');
fwrite(fid,f.header.calbaseline,'short');
fwrite(fid,f.header.calsweeps,'short');
fwrite(fid,f.header.calattenuator,'float');
fwrite(fid,f.header.calpulsevolt,'float');
fwrite(fid,f.header.calpulsestart,'float');
fwrite(fid,f.header.calpulsestop,'float');
fwrite(fid,f.header.calfreq,'float');
fwrite(fid,f.header.taskfile,'char');
fwrite(fid,f.header.seqfile,'char');
fwrite(fid,f.header.spectmethod,'char');
fwrite(fid,f.header.spectscaling,'char');
fwrite(fid,f.header.spectwindow,'char');
fwrite(fid,f.header.spectwinlength,'float');
fwrite(fid,f.header.spectorder,'char');
fwrite(fid,f.header.notchfilter,'char');
fwrite(fid,f.header.headgain,'short');
fwrite(fid,f.header.additionalfiles,'int');
fwrite(fid,f.header.unused,'char');
fwrite(fid,f.header.fspstopmethod,'short');
fwrite(fid,f.header.fspstopmode,'short');
fwrite(fid,f.header.fspfvalue,'float');
fwrite(fid,f.header.fsppoint,'short');
fwrite(fid,f.header.fspblocksize,'short');
fwrite(fid,f.header.fspp1,'ushort');
fwrite(fid,f.header.fspp2,'ushort');
fwrite(fid,f.header.fspalpha,'float');
fwrite(fid,f.header.fspnoise,'float');
fwrite(fid,f.header.fspv1,'short');
fwrite(fid,f.header.montage,'char');
fwrite(fid,f.header.eventfile,'char');
fwrite(fid,f.header.fratio,'float');
fwrite(fid,f.header.minor_rev,'char');
fwrite(fid,f.header.eegupdate,'short');
fwrite(fid,f.header.compressed,'char');
fwrite(fid,f.header.xscale,'float');
fwrite(fid,f.header.yscale,'float');
fwrite(fid,f.header.xsize,'float');
fwrite(fid,f.header.ysize,'float');
fwrite(fid,f.header.acmode,'char');
fwrite(fid,f.header.commonchnl,'uchar');
fwrite(fid,f.header.xtics,'char');
fwrite(fid,f.header.xrange,'char');
fwrite(fid,f.header.ytics,'char');
fwrite(fid,f.header.yrange,'char');
fwrite(fid,f.header.xscalevalue,'float');
fwrite(fid,f.header.xscaleinterval,'float');
fwrite(fid,f.header.yscalevalue,'float');
fwrite(fid,f.header.yscaleinterval,'float');
fwrite(fid,f.header.scaletoolx1,'float');
fwrite(fid,f.header.scaletooly1,'float');
fwrite(fid,f.header.scaletoolx2,'float');
fwrite(fid,f.header.scaletooly2,'float');
fwrite(fid,f.header.port,'short');
fwrite(fid,f.header.numsamples,'long');
fwrite(fid,f.header.filterflag,'char');
fwrite(fid,f.header.lowcutoff,'float');
fwrite(fid,f.header.lowpoles,'short');
fwrite(fid,f.header.highcutoff,'float');
fwrite(fid,f.header.highpoles,'short');
fwrite(fid,f.header.filtertype,'char');
fwrite(fid,f.header.filterdomain,'char');
fwrite(fid,f.header.snrflag,'char');
fwrite(fid,f.header.coherenceflag,'char');
fwrite(fid,f.header.continuoustype,'char');
fwrite(fid,f.header.eventtablepos,'long');
fwrite(fid,f.header.continuousseconds,'float');
fwrite(fid,f.header.channeloffset,'long');
fwrite(fid,f.header.autocorrectflag,'char');
fwrite(fid,f.header.dcthreshold,'uchar');

for n = 1:f.header.nchannels
fwrite(fid,f.electloc(n).lab,'char');
fwrite(fid,f.electloc(n).reference,'char');
fwrite(fid,f.electloc(n).skip,'char');
fwrite(fid,f.electloc(n).reject,'char');
fwrite(fid,f.electloc(n).display,'char');
fwrite(fid,f.electloc(n).bad,'char');
fwrite(fid,f.electloc(n).n,'ushort');
fwrite(fid,f.electloc(n).avg_reference,'char');
fwrite(fid,f.electloc(n).clipadd,'char');
fwrite(fid,f.electloc(n).x_coord,'float');
fwrite(fid,f.electloc(n).y_coord,'float');
fwrite(fid,f.electloc(n).veog_wt,'float');
fwrite(fid,f.electloc(n).veog_std,'float');
fwrite(fid,f.electloc(n).snr,'float');
fwrite(fid,f.electloc(n).heog_wt,'float');
fwrite(fid,f.electloc(n).heog_std,'float');
fwrite(fid,f.electloc(n).baseline,'short');
fwrite(fid,f.electloc(n).filtered,'char');
fwrite(fid,f.electloc(n).fsp,'char');
fwrite(fid,f.electloc(n).aux1_wt,'float');
fwrite(fid,f.electloc(n).aux1_std,'float');
fwrite(fid,f.electloc(n).senstivity,'float');
fwrite(fid,f.electloc(n).gain,'char');
fwrite(fid,f.electloc(n).hipass,'char');
fwrite(fid,f.electloc(n).lopass,'char');
fwrite(fid,f.electloc(n).page,'uchar');
fwrite(fid,f.electloc(n).size,'uchar');
fwrite(fid,f.electloc(n).impedance,'uchar');
fwrite(fid,f.electloc(n).physicalchnl,'uchar');
fwrite(fid,f.electloc(n).rectify,'char');
fwrite(fid,f.electloc(n).calib,'float');
end

for i = 1:f.header.nchannels
   fwrite(fid,f.data(i).header,'char');
   fwrite(fid,f.data(i).samples,'float');
end

for j = 1:f.header.nchannels
   fwrite(fid,f.variance(j).samples,'float');
end

fwrite(fid,f.tag,'char');

frewind(fid);

fclose(fid);


function display(r)
% called to display a robot object

% Ryan Steindl based on Robotics Toolbox for MATLAB (v6 and v9)
%
% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com

	disp(' ');
	disp([inputname(1), ' = '])
	disp(' ');
	disp(char(r))
	disp(' ');


function site = db_get_site_info(stalist,datetime,dbname)

% SITE = DB_GET_SITE_INFO(STATION_LIST,DATE,DATABASE_NAME) This
% This function takes a list of stations and returns a structure containing
% relavent fields from the site table. The database must include a
% site table. The DATE field is required to resolve conflicts when a
% station configuration has changed through time. Typically the date will
% match waveform, origin or arrival data that is being extracted from the
% database. The date should be given is a string format recognized by
% antelope, or as a matlab-format numeric time.
%
%
% Example:
%    site = db_get_site_info({'AUL' 'AUH' 'AUW'},'7/1/2007','dbtmp')
%
%

% Author: Michael West, Geophysical Institute, Univ. of Alaska Fairbanks
% $Date$
% $Revision$

% FORMAT INPUT
if ischar(stalist)
   stalist = cellstr(stalist);
end
site.sta = reshape( stalist , numel(stalist), 1 );

% PREP DAY OF YEAR
if isreal(datetime)
   datetime = datestr(datetime,'mm/dd/yy HH:MM:SS.FFF');
end
jday = num2str(yearday(str2epoch(datetime)));

% GET SITE INFO
db = dbopen(dbname,'r');
db = dblookup_table(db,'site');
nlist = [];
for n = 1:length(site.sta);
	db1 = dbsubset(db,['sta==''' site.sta{n} '''']);
    db1 = dbsubset(db1,['ondate<=''' jday ''' ']);
    db1 = dbsubset(db1,['offdate>=''' jday ''' || offdate==NULL']);
    recnum = dbquery(db1,'dbRECORD_COUNT');
	[ site.ondate(n) , site.offdate(n) , site.lat(n) , site.lon(n) , site.elev(n) ] = dbgetv(db1,'ondate','offdate','lat','lon','elev');
end
dbclose(db);
site.ondate = reshape( site.ondate , numel(site.ondate), 1 );
site.offdate = reshape( site.offdate , numel(site.offdate), 1 );
site.lat = reshape( site.lat , numel(site.lat), 1 );
site.lon = reshape( site.lon , numel(site.lon), 1 );
site.elev = reshape( site.elev , numel(site.elev), 1 );

% plot(correlation(w));
%figure
%plot(w(1),'b')
%hold on;
%plot(w1(1),'g')
%plot(w2(1),'r')


function compareOutputs_subjs(group_h2, group_h3, type)

prec = -10;
if isempty(group_h2) || isempty(group_h3)
    return;
end
for qq=1:length(group_h3.group.subjs)
    yavg_h2 = eval( sprintf('group_h2.group.subjs(qq).procResult.%s;', type) );
    yavg_h3 = eval( sprintf('group_h3.group.subjs(qq).procStream.output.%s;', type) );
    for ll=1:size(yavg_h3,2)
        for mm=1:size(yavg_h3,3)
            for nn=1:size(yavg_h3,4)
                if ~isequal_prec(yavg_h2(:,ll,mm,nn), yavg_h3(:,ll,mm,nn), prec)
                    fprintf('Subj %d: %s data for Hb type %d, Ch %d, Cond %d does not match\n', qq, type, ll, mm, nn);
                end
            end
        end
    end
end


function varargout = size(f, varargin)
%SIZE   Size of a DELTAFUN.
%   [S1, S2] = SIZE(F) returns the size of the funPart of F.
%
%   S = SIZE(F) returns the same as above in a 1x2 vector, S = [S1, S2].
%
% See also LENGTH.

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

% The size of a DELTAFUN is the size of its funPart.
varargout{1:nargout} = size(f.funPart, varargin{:});

end


% eeglab2eegtoolbox() - convert EEGLAB structure to EEG toolbox
%                       structure (for ERP peak picking mainly).
%
% Usage:
%   >> p = eeglab2eegtoolbox( EEG );
%
% Inputs:
%   EEG - EEG structure
%
% Outputs:
%   p   - EEG toolbox structure
%
% Author: Arnaud Delorme, SCCN, INC, UCSD
%
% See also: eeglab()

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

function p = eeglab2eegtoolbox( EEG );

    if nargin < 1
        help eeglab2eegtoolbox;
        return;
    end;

    % default structure
    % -----------------
    p = eeg_toolbox_defaults;

    % exporting importing electrodes
    % ------------------------------
    fid = fopen('tmp.txt', 'w');
    % fiducials should also be added here
    for index = 1:length(EEG.chanlocs)
        tmp = EEG.chanlocs(index);
        fprintf(fid, '%s\t%d\t%f\t%f\t%f\n', tmp.labels, 69, tmp.X, tmp.Y, tmp.Z);
    end;
    fprintf(fid, 'Centroid\t%d\t%f\t%f\t%f\n\n', 99, 0, 0, 0);
    fclose(fid);

    p.elec.path = pwd;
    p.elec.file = 'tmp.txt';
    p.elec.n    = length(EEG.chanlocs)+1;
    p = elec_open(p);
    delete(fullfile(pwd, 'tmp.txt'));

    % importing data
    % --------------
    p.volt.data = double(mean(EEG.data,3)');
    p.volt.timeArray = EEG.times';
    p.volt.points    = EEG.pnts;
    p.volt.sampleHz  = EEG.srate;
    p.volt.sampleTime = EEG.srate;
    p.volt.sampleMsec = 1000/EEG.srate;
    p.volt.channels   = length(EEG.chanlocs);
    p.volt.epochStart = EEG.xmin*1000;
    p.volt.epochEnd   = EEG.xmax*1000;


% Installer for the Covariance toolbox

HOME = pwd;

if isunix
    path([HOME,'/lib'],path);
    path([HOME,'/lib/distance'],path);
    path([HOME,'/lib/geodesic'],path);
    path([HOME,'/lib/riemann'],path);
    path([HOME,'/lib/visu'],path);
    path([HOME,'/lib/estimation'],path);
    path([HOME,'/lib/mean'],path);
    path([HOME,'/lib/simulation'],path);
    path([HOME,'/lib/jointdiag'],path);
    path([HOME,'/lib/classification'],path);
    path([HOME,'/lib/potato'],path);
else
    path([HOME,'\lib'],path);
    path([HOME,'\lib\distance'],path);
    path([HOME,'\lib\geodesic'],path);
    path([HOME,'\lib\riemann'],path);
    path([HOME,'\lib\visu'],path);
    path([HOME,'\lib\estimation'],path);
    path([HOME,'\lib\mean'],path);
    path([HOME,'\lib\simulation'],path);
    path([HOME,'\lib\jointdiag'],path);
    path([HOME,'\lib\classification'],path);
    path([HOME,'\lib\potato'],path);
end
disp('Covariance toolbox activated');


%PlotBrowser
% Creates GUI window which allows the user to quickly view plots of
% simulation. User can either select plots from list box, or scroll through
% plots using the previous and next page buttons.
%
%Uses meta class to find names of all public static  plot methods in
%analysis classes. Their signature should be:
%   function plot*(sim, axes, time, compartments)
%   end
%
% Author: Jonathan Karr, jkarr@stanford.edu
% Affiliation: Covert Lab, Department of Bioengineering, Stanford University
% Last updated: 8/6/2011
classdef PlotBrowser < handle
    properties (SetAccess = protected)
        simulation

        plotNames
        plotFunctions

        figure
        buttonsPanel
        compartmentListBoxTitle
        compartmentListBox
        plotListBoxTitle
        plotListBox
        plotButton
        prevButton
        nextButton
        saveButton
        printButton
        plotPanel
    end

    properties (Constant = true)
        plotClasses = {
            'Chromosome'
            'MetabolicReaction'
            'Transcription'
            'Translation'
            }
    end

    methods
        function this = PlotBrowser(sim, selectedPlotNames, selectedCompartmentNames)
            this = this@handle;
            this.simulation = sim;

            %find plots
            this.discoverPlots();

            %open window
            this.open();

            %layout window fullscreen
            screenSize = get(0, 'ScreenSize');
            screenSize(2) = 30;
            screenSize(4) = screenSize(4) - screenSize(2);
            screenSize([3 4]) = max(1, screenSize([3 4]));
            set(this.figure, 'OuterPosition', screenSize);

            %plot
            if nargin < 2
                selectedPlotNames = this.plotNames{1};
            end
            if nargin < 3
                selectedCompartmentNames = 'Sum';
            end
            this.selectPlots(selectedPlotNames, selectedCompartmentNames);
        end
    end

    methods
        function selectPlots(this, selectedPlotNames, selectedCompartmentNames)
            %select plots
            [~, selectedPlots] = ismember(selectedPlotNames, this.plotNames);
            set(this.plotListBox, 'Value', selectedPlots);

            %select compartments
            if nargin < 3
                selectedCompartmentNames = 'Sum';
            end
            [~, selectedCompartments] = ismember(selectedCompartmentNames, get(this.compartmentListBox, 'String'));
            set(this.compartmentListBox, 'Value', selectedCompartments);

            %plot
            this.graphSelectedPlots();
        end

        function open(this)
            %figure
            this.figure = figure('Name', 'Whole Cell Simulation :: Plot Browser', ...
                'NumberTitle', 'off', 'ResizeFcn', @this.layoutWindow); %#ok<CPROP,PROP>

            %list box panel
            this.buttonsPanel = uipanel('Title', 'Configure Plots');

            %select compartment
            this.compartmentListBoxTitle = uicontrol(this.buttonsPanel, 'Style', 'text',...
                'String', 'Select Compartments', 'HorizontalAlignment', 'Center');
            this.compartmentListBox = uicontrol(this.buttonsPanel, 'Style', 'listbox',...
                'String', [{'Sum'; 'Mean'; 'Median'; 'Std Dev'}; this.simulation.compartment.names],...
                'Min', 1, 'Max', 4 + this.simulation.compartment.count, 'Value', 1);

            %plot list box
            this.plotListBoxTitle = uicontrol(this.buttonsPanel,'Style', 'text',...
                'String','Select Plots', 'HorizontalAlignment', 'Center');
            this.plotListBox = uicontrol(this.buttonsPanel, 'Style', 'listbox',...
                'String', this.plotNames, 'Min', 1, 'Max', length(this.plotNames), 'Value', 1);

            %plot button
            this.plotButton = uicontrol(this.buttonsPanel, 'Style', 'pushbutton',...
                'String', 'Plot', 'Callback', @this.graphSelectedPlots);

            %previous page button
            this.prevButton = uicontrol(this.buttonsPanel, 'Style', 'pushbutton',...
                'String', 'Prev', 'Callback', @this.graphPrevPlots);

            %next page button
            this.nextButton = uicontrol(this.buttonsPanel, 'Style', 'pushbutton',...
                'String', 'Next', 'Callback', @this.graphNextPlots);

            %save button
            this.saveButton = uicontrol(this.buttonsPanel, 'Style', 'pushbutton',...
                'String', 'Save', 'Callback', @this.save);

            %print button
            this.printButton = uicontrol(this.buttonsPanel, 'Style', 'pushbutton',...
                'String', 'Print', 'Callback', @this.print);

            %plot panel
            this.plotPanel = uipanel('Title','Plots');
        end

        function close(this)
            close(this.figure);

            this.figure = [];
            this.buttonsPanel = [];
            this.compartmentListBoxTitle = [];
            this.compartmentListBox = [];
            this.plotListBoxTitle = [];
            this.plotListBox = [];
            this.plotButton = [];
            this.prevButton = [];
            this.nextButton = [];
            this.saveButton = [];
            this.printButton = [];
            this.plotPanel = [];
        end
    end

    %helper methods
    methods (Access = protected)
        %Return list of names of plotting functions
        function discoverPlots(this)
            this.plotNames = cell(0, 1);
            this.plotFunctions = cell(0, 1);

            metaPackage = meta.package.fromName('edu.stanford.covert.cell.sim.analysis');
            for i = 1:numel(metaPackage.Classes)
                metaClass = metaPackage.Classes{i};

                %ignore test clases, handle clases
                if any(ismember(cellfun(@(class) class.Name, metaClass.SuperClasses, 'UniformOutput', false), {'TestCase', 'handle'}))
                    continue;
                end

                %ignore unsupported classes
                className = metaClass.Name(find(metaClass.Name == '.', 1, 'last') + 1:end);
                if ~ismember(className, this.plotClasses)
                    continue;
                end

                %find plotting methods
                for j = 1:numel(metaClass.Methods)
                    metaMethod = metaClass.Methods{j};

                    %filter out methods to match required signature
                    if ...
                            length(metaMethod.Name) < 5 || ...
                            ~strcmp(metaMethod.Name(1:4), 'plot') || ...
                            ~metaMethod.Static || ...
                            ~strcmp(metaMethod.Access, 'public') || ...
                            length(metaMethod.InputNames) < 4
                        continue;
                    end

                    this.plotNames = [this.plotNames; className ':' strrep(metaMethod.Name(5:end), '_', ' ')];
                    this.plotFunctions = [this.plotFunctions; metaClass.Name '.' metaMethod.Name];
                end

                %sort plots by class, name
                [~, order] = sort(this.plotNames);
                this.plotNames = this.plotNames(order);
                this.plotFunctions = this.plotFunctions(order);
            end
        end

        function graphSelectedPlots(this, ~, ~)
            sim = this.simulation;
            selectedPlots = sort(get(this.plotListBox, 'Value'));
            time = permute(sim.state('Time').values, [3 1 2]);
            compartments = sort(get(this.compartmentListBox, 'Value') - 4);

            rows = ceil(sqrt(length(selectedPlots)));
            cols = ceil(length(selectedPlots) / rows);
            for i = 1:length(selectedPlots)
                axes = subplot(rows, cols, i, 'Parent', this.plotPanel);
                cla(axes);
                legend(axes, 'off');
                set(axes, 'Box', 'on');

                feval(this.plotFunctions{selectedPlots(i)}, sim, axes, time, compartments);

                set(axes, 'fontSize', 6);
                title(axes, this.plotNames{selectedPlots(i)}, 'fontSize', 10);
            end
        end
    end

    %Callbacks
    methods (Access = protected)
        function layoutWindow(this, ~, ~)
            %figure size
            figureSize = get(this.figure, 'Position');
            figureWidth = figureSize(3);
            figureHeight = figureSize(4);

            %list box panel
            panelWidth = 300;
            set(this.buttonsPanel, 'Position', [0 0 panelWidth / figureWidth 1]);

            %select compartment
            compartmentListBoxWidth = panelWidth - 20;
            compartmentListBoxHeight = 100;
            compartmentListBoxSize = [10 120 compartmentListBoxWidth compartmentListBoxHeight];
            set(this.compartmentListBoxTitle, 'Position', [10 120+compartmentListBoxHeight compartmentListBoxWidth 20]);
            set(this.compartmentListBox, 'Position', compartmentListBoxSize);

            %plot list box
            plotListBoxWidth = compartmentListBoxWidth;
            plotListBoxHeight = figureHeight-140-compartmentListBoxHeight-35-10-20;
            plotListBoxSize = [10 120+compartmentListBoxHeight+10+35 plotListBoxWidth plotListBoxHeight];
            set(this.plotListBoxTitle, 'Position', [10 120+compartmentListBoxHeight+10+35+plotListBoxHeight compartmentListBoxWidth 20]);
            set(this.plotListBox, 'Position', plotListBoxSize);

            %plot button
            buttonWidth = panelWidth-20;
            buttonHeight = 20;
            buttonSize = [10 70 buttonWidth buttonHeight];
            set(this.plotButton, 'Position', buttonSize);

            %previous page button
            buttonWidth = (panelWidth-20-10)/2;
            buttonSize = [10 40 buttonWidth buttonHeight];
            set(this.prevButton, 'Position', buttonSize);

            %next page button
            buttonSize = [10+buttonWidth+10 40 buttonWidth buttonHeight];
            set(this.nextButton, 'Position', buttonSize);

            %save button
            buttonSize = [10 10 buttonWidth buttonHeight];
            set(this.saveButton, 'Position', buttonSize);

            %print button
            buttonSize = [10 + buttonWidth + 10 10 buttonWidth buttonHeight];
            set(this.printButton, 'Position', buttonSize);

            %plot panel
            set(this.plotPanel, 'Position', [panelWidth / figureWidth 0 1 - panelWidth/figureWidth 1]);
        end

        function graphPrevPlots(this, ~, ~)
            selectedPlots = get(this.plotListBox, 'Value');

            unselectedPlots = setdiff(1:length(this.plotNames), selectedPlots);

            %select next plots
            if ...
                    max(selectedPlots) - min(selectedPlots) + 1 == length(selectedPlots) || ...
                    max(unselectedPlots) - min(unselectedPlots) + 1 == length(unselectedPlots)
                selectedPlots = mod(selectedPlots - length(selectedPlots) - 1, length(this.plotNames)) + 1;
            else
                selectedPlots = (1:length(selectedPlots)) + min(selectedPlots) - 1;
            end
            set(this.plotListBox ,'Value', sort(selectedPlots));

            %graph
            this.graphSelectedPlots();
        end

        function graphNextPlots(this, ~, ~)
            selectedPlots = get(this.plotListBox, 'Value');

            unselectedPlots = setdiff(1:length(this.plotNames), selectedPlots);

            %select next plots
            if ...
                    max(selectedPlots) - min(selectedPlots) + 1 == length(selectedPlots) || ...
                    max(unselectedPlots) - min(unselectedPlots) + 1 == length(unselectedPlots)
                selectedPlots = mod(selectedPlots+length(selectedPlots)-1,length(this.plotNames))+1;
            else
                selectedPlots = (1:length(selectedPlots)) + min(selectedPlots) - 1;
            end
            set(this.plotListBox, 'Value', sort(selectedPlots));

            %graph
            this.graphSelectedPlots();
        end

        function save(this, ~, ~)
            filemenufcn(this.figure, 'FileSaveAs')
        end

        function print(this, ~, ~)
            printdlg(this.figure);
        end
    end
end


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

    enumeration
        NoDir('Either Increasing or Decreasing',0)
        Increasing('Increasing at Value',1)
        Decreasing('Decreasing at Value',-1)
    end

    properties
        name char = '';
        direction(1,1) double = 0;
    end

    methods
        function obj = EventTermCondDirectionEnum(name,direction)
            obj.name = name;
            obj.direction = direction;
        end
    end

    methods(Static)
        function listBoxStr = getListboxStr()
            m = enumeration('EventTermCondDirectionEnum');
            listBoxStr = {m.name};
        end

        function [enum, ind] = getEnumForListboxStr(nameStr)
            m = enumeration('EventTermCondDirectionEnum');
            ind = find(ismember({m.name},nameStr),1,'first');
            enum = m(ind);
        end
    end
end