1279 lines
50 KiB
Matlab
1279 lines
50 KiB
Matlab
classdef spider_plot_class < matlab.graphics.chartcontainer.ChartContainer & ...
|
|
matlab.graphics.chartcontainer.mixin.Legend
|
|
%spider_plot_class Create a spider or radar plot with individual axes.
|
|
%
|
|
% Syntax:
|
|
% s = spider_plot_class(P)
|
|
% s = spider_plot_class(P, Name, Value, ...)
|
|
% s = spider_plot_class(parent, ___)
|
|
%
|
|
% Input Arguments:
|
|
% (Required)
|
|
% P - The data points used to plot the spider chart. The
|
|
% rows are the groups of data and the columns are the
|
|
% data points. The axes labels and axes limits are
|
|
% automatically generated if not specified.
|
|
% [vector | matrix]
|
|
%
|
|
% Name-Value Pair Arguments:
|
|
% (Optional)
|
|
% AxesLabels - Used to specify the label each of the axes.
|
|
% [auto-generated (default) | array of strings | 'none']
|
|
%
|
|
% AxesInterval - Used to change the number of intervals displayed
|
|
% between the webs.
|
|
% [3 (default) | integer]
|
|
%
|
|
% AxesPrecision - Used to change the precision level on the value
|
|
% displayed on the axes.
|
|
% [1 (default) | integer | vector]
|
|
%
|
|
% AxesDisplay - Used to change the number of axes in which the
|
|
% axes text are displayed. 'None' or 'one' can be used
|
|
% to simplify the plot appearance for normalized data.
|
|
% ['all' (default) | 'none' | 'one']
|
|
%
|
|
% AxesLimits - Used to manually set the axes limits. A matrix of
|
|
% 2 x size(P, 2). The top row is the minimum axes
|
|
% limits and the bottow row is the maximum axes limits.
|
|
% [auto-scaled (default) | matrix]
|
|
%
|
|
% FillOption - Used to toggle color fill option.
|
|
% ['off' (default) | 'on']
|
|
%
|
|
% FillTransparency - Used to set color fill transparency.
|
|
% [0.1 (default) | scalar in range (0, 1)]
|
|
%
|
|
% Color - Used to specify the line color, specified as an RGB
|
|
% triplet. The intensities must be in the range (0, 1).
|
|
% [MATLAB Color (default) | RGB triplet]
|
|
%
|
|
% LineStyle - Used to change the line style of the plots.
|
|
% ['-' (default) | '--' | ':' | '-.' | 'none']
|
|
%
|
|
% LineWidth - Used to change the line width, where 1 point is
|
|
% 1/72 of an inch.
|
|
% [0.5 (default) | positive value]
|
|
%
|
|
% Marker - Used to change the options.Marker symbol of the plots.
|
|
% ['o' (default) | 'none' | '*' | 's' | 'd' | ...]
|
|
%
|
|
% MarkerSize - Used to change the options.Marker size, where 1 point is
|
|
% 1/72 of an inch.
|
|
% [8 (default) | positive value]
|
|
%
|
|
% AxesFont - Used to change the font type of the values
|
|
% displayed on the axes.
|
|
% [Helvetica (default) | supported font name]
|
|
%
|
|
% LabelFont - Used to change the font type of the labels.
|
|
% [Helvetica (default) | supported font name]
|
|
%
|
|
% AxesFontSize - Used to change the font size of the values
|
|
% displayed on the axes.
|
|
% [10 (default) | scalar value greater than zero]
|
|
%
|
|
% LabelFontSize - Used to change the font size of the labels.
|
|
% [10 (default) | scalar value greater than zero]
|
|
%
|
|
% Direction - Used to change the direction of rotation of the
|
|
% plotted data and axis labels.
|
|
% ['clockwise' (default) | 'counterclockwise']
|
|
%
|
|
% AxesDirection - Used to change the direction of axes.
|
|
% ['normal' (default) | 'reverse' | cell array of character vectors]
|
|
%
|
|
% AxesLabelsOffset - Used to adjust the position offset of the axes
|
|
% labels.
|
|
% [0.1 (default) | positive value]
|
|
%
|
|
% AxesScaling - Used to change the scaling of the axes.
|
|
% ['linear' (default) | 'log' | cell array of character vectors]
|
|
%
|
|
% AxesColor - Used to change the color of the spider axes.
|
|
% [grey (default) | RGB triplet | hexadecimal color code]
|
|
%
|
|
% AxesLabelsEdge - Used to change the edge color of the axes labels.
|
|
% [black (default) | RGB triplet | hexadecimal color code | 'none']
|
|
%
|
|
% LegendLabels - Used to add the labels to the legend.
|
|
% [cell array of character vectors]
|
|
%
|
|
% LegendHandle - Used to customize legend settings.
|
|
% [legend handle object]
|
|
%
|
|
% AxesOffset - Used to change to axes offset from the origin.
|
|
% [1 (default) | any integer less than the axes interval]
|
|
%
|
|
% Output Arguments:
|
|
% (Optional)
|
|
% s - Returns a chart class object. These are unique
|
|
% identifiers, which you can use to query and
|
|
% modify properties of the spider chart.
|
|
% [chart class object]
|
|
%
|
|
% Examples:
|
|
% % Example 1: Minimal number of arguments. All non-specified, optional
|
|
% arguments are set to their default values. Axes labels
|
|
% and limits are automatically generated and set.
|
|
%
|
|
% D1 = [5 3 9 1 2];
|
|
% D2 = [5 8 7 2 9];
|
|
% D3 = [8 2 1 4 6];
|
|
% P = [D1; D2; D3];
|
|
% if exist('s', 'var')
|
|
% delete(s);
|
|
% end
|
|
% s = spider_plot_class(P);
|
|
% s.LegendLabels = {'D1', 'D2', 'D3'};
|
|
% s.LegendHandle.Location = 'southoutside';
|
|
%
|
|
% % Example 2: Manually setting the axes limits and axes precision.
|
|
% All non-specified, optional arguments are set to their
|
|
% default values.
|
|
%
|
|
% D1 = [5 3 9 1 2];
|
|
% D2 = [5 8 7 2 9];
|
|
% D3 = [8 2 1 4 6];
|
|
% P = [D1; D2; D3];
|
|
% if exist('s', 'var')
|
|
% delete(s);
|
|
% end
|
|
% s = spider_plot_class(P);
|
|
% s.AxesLimits = [1, 2, 1, 1, 1; 10, 8, 9, 5, 10]; % [min axes limits; max axes limits]
|
|
% s.AxesPrecision = [0, 1, 1, 1, 1];
|
|
%
|
|
% % Example 3: Set fill option on. The fill transparency can be adjusted.
|
|
%
|
|
% D1 = [5 3 9 1 2];
|
|
% D2 = [5 8 7 2 9];
|
|
% D3 = [8 2 1 4 6];
|
|
% P = [D1; D2; D3];
|
|
% if exist('s', 'var')
|
|
% delete(s);
|
|
% end
|
|
% s = spider_plot_class(P);
|
|
% s.AxesLabels = {'S1', 'S2', 'S3', 'S4', 'S5'};
|
|
% s.AxesInterval = 2;
|
|
% s.FillOption = 'on';
|
|
% s.FillTransparency = 0.1;
|
|
%
|
|
% % Example 4: Maximum number of arguments.
|
|
%
|
|
% D1 = [5 3 9 1 2];
|
|
% D2 = [5 8 7 2 9];
|
|
% D3 = [8 2 1 4 6];
|
|
% P = [D1; D2; D3];
|
|
% if exist('s', 'var')
|
|
% delete(s);
|
|
% end
|
|
% s = spider_plot_class(P);
|
|
% s.AxesLabels = {'S1', 'S2', 'S3', 'S4', 'S5'};
|
|
% s.AxesInterval = 4;
|
|
% s.AxesPrecision = 0;
|
|
% s.AxesDisplay = 'one';
|
|
% s.AxesLimits = [1, 2, 1, 1, 1; 10, 8, 9, 5, 10];
|
|
% s.FillOption = 'on';
|
|
% s.FillTransparency = 0.2;
|
|
% s.Color = [1, 0, 0; 0, 1, 0; 0, 0, 1];
|
|
% s.LineStyle = '--';
|
|
% s.LineWidth = 3;
|
|
% s.Marker = 'd';
|
|
% s.MarkerSize = 10;
|
|
% s.AxesFont = 'Times New Roman';
|
|
% s.LabelFont = 'Times New Roman';
|
|
% s.AxesFontSize = 12;
|
|
% s.LabelFontSize = 10;
|
|
% s.Direction = 'clockwise';
|
|
% s.AxesDirection = {'reverse', 'normal', 'normal', 'normal', 'normal'};
|
|
% s.AxesLabelsOffset = 0;
|
|
% s.AxesScaling = 'linear';
|
|
% s.AxesOffset = 1;
|
|
% s.LegendLabels = {'D1', 'D2', 'D3'};
|
|
% s.LegendHandle.Location = 'northeastoutside';
|
|
%
|
|
% % Example 5: Excel-like radar charts.
|
|
%
|
|
% D1 = [5 0 3 4 4];
|
|
% D2 = [2 1 5 5 4];
|
|
% P = [D1; D2];
|
|
% if exist('s', 'var')
|
|
% delete(s);
|
|
% end
|
|
% s = spider_plot_class(P);
|
|
% s.AxesInterval = 5;
|
|
% s.AxesPrecision = 0;
|
|
% s.AxesDisplay = 'one';
|
|
% s.AxesLimits = [0, 0, 0, 0, 0; 5, 5, 5, 5, 5];
|
|
% s.FillOption = 'on';
|
|
% s.FillTransparency = 0.1;
|
|
% s.Color = [139, 0, 0; 240, 128, 128]/255;
|
|
% s.LineWidth = 4;
|
|
% s.Marker = 'none';
|
|
% s.AxesFontSize = 14;
|
|
% s.LabelFontSize = 10;
|
|
% title('Excel-like Radar Chart',...
|
|
% 'FontSize', 14);
|
|
% s.LegendLabels = {'D1', 'D2'};
|
|
%
|
|
% % Example 6: Logarithimic scale on all axes. Axes limits and axes
|
|
% intervals are automatically set to factors of 10.
|
|
%
|
|
% D1 = [5 3 9 1 1];
|
|
% D2 = [5 8 7 2 10];
|
|
% D3 = [8 2 1 4 100];
|
|
% P = [D1; D2; D3];
|
|
% if exist('s', 'var')
|
|
% delete(s);
|
|
% end
|
|
% s = spider_plot_class(P);
|
|
% s.AxesInterval = 2;
|
|
% s.AxesPrecision = 0;
|
|
% s.AxesFontSize = 10;
|
|
% s.AxesLabels = {'Linear Scale', 'Linear Scale', 'Linear Scale', 'Linear Scale', 'Logarithimic Scale'};
|
|
% s.AxesScaling = {'linear', 'linear', 'linear', 'linear', 'log'};
|
|
% s.AxesLimits = [1, 1, 1, 1, 1; 10, 10, 10, 10, 100];
|
|
% s.LegendLabels = {'D1', 'D2', 'D3'};
|
|
%
|
|
% Author:
|
|
% Moses Yoo, (jyoo at hatci dot com)
|
|
% 2020-12-01: Added support for adjust the axes offset from origin.
|
|
% 2020-11-30: Allow for one data group without specified axes limits.
|
|
% 2020-11-30: Added support for changing axes and label font type.
|
|
% 2020-11-06: Fix bug in reverse axes direction feature.
|
|
% 2020-10-08: Adjust axes precision to be set to one or more axis.
|
|
% 2020-10-01: Fix legend feature with inherited legend class.
|
|
% 2020-09-30: -Fix axes limit bug. Updated examples.
|
|
% -Added feature to change spider axes and axes labels edge color.
|
|
% -Allow logarithmic scale to be set to one or more axis.
|
|
% -Added feature to allow different line styles, line width,
|
|
% marker type, and marker sizes for the data groups.
|
|
% -Allow ability to reverse axes direction.
|
|
% 2020-02-17: Major revision in converting the function into a custom
|
|
% chart class. New feature introduced in R2019b.
|
|
% 2020-02-12: Fixed condition and added error checking for when only one
|
|
% data group is plotted.
|
|
% 2020-01-27: Corrected bug where only 7 entries were allowed in legend.
|
|
% 2020-01-06: Added support for tiledlayout feature introduced in R2019b.
|
|
% 2019-11-27: Add option to change axes to logarithmic scale.
|
|
% 2019-11-15: Add feature to customize the plot rotational direction and
|
|
% the offset position of the axis labels.
|
|
% 2019-10-28: Major revision in implementing the new function argument
|
|
% validation feature introduced in R2019b. Replaced previous
|
|
% method of error checking and setting of default values.
|
|
% 2019-10-23: Minor revision to set starting axes as the vertical line.
|
|
% Add customization option for font sizes and axes display.
|
|
% 2019-10-16: Minor revision to add name-value pairs for customizing
|
|
% color, Marker, and line settings.
|
|
% 2019-10-08: Another major revision to convert to name-value pairs and
|
|
% add color fill option.
|
|
% 2019-09-17: Major revision to improve speed, clarity, and functionality
|
|
%
|
|
% Special Thanks:
|
|
% Special thanks to Gabriela Andrade, Andrés Garcia, Alex Grenyer,
|
|
% Omar Hadri, Zafar Ali, Christophe Hurlin, Roman, Mariusz Sepczuk,
|
|
% Mohamed Abubakr, Maruis Mueller, Nicolai, Jingwei Too,
|
|
% Cedric Jamet & Richard Ruff for their feature recommendations
|
|
% and bug finds. A huge thanks to Jiro Doke and Sean de Wolski for
|
|
% demonstrating the implementation of argument validation and custom chart
|
|
% class introduced in R2019b.
|
|
|
|
%%% Public, SetObservable Properties %%%
|
|
properties(Access = public, SetObservable)
|
|
% Property validation and defaults
|
|
P (:, :) double
|
|
AxesLabels cell % Axes labels
|
|
LegendLabels cell % Legend labels
|
|
LegendHandle % Lengend handle
|
|
AxesInterval (1, 1) double {mustBeInteger, mustBePositive} = 3 % Number of axes grid lines
|
|
AxesPrecision (:, :) double {mustBeInteger, mustBeNonnegative} = 1 % Tick precision
|
|
AxesDisplay char {mustBeMember(AxesDisplay, {'all', 'none', 'one'})} = 'all' % Number of tick label groups shown on axes
|
|
AxesLimits double = [] % Axes limits
|
|
FillOption matlab.lang.OnOffSwitchState = 'off' % Whether to shade data
|
|
FillTransparency (1, 1) double {mustBeGreaterThanOrEqual(FillTransparency, 0), mustBeLessThanOrEqual(FillTransparency, 1)} % Shading alpha
|
|
Color = get(groot,'defaultAxesColorOrder') % Color order
|
|
LineStyle = '-' % Data line style
|
|
LineWidth (:, :) double {mustBePositive} = 2 % Data line width
|
|
Marker = 'o' % Data marker
|
|
MarkerSize (:, :) double {mustBePositive} = 8 % Data marker size
|
|
AxesFont char ='Helvetica' % Axes tick font type
|
|
LabelFont char = 'Helvetica' % Label font type
|
|
AxesFontSize (1, 1) double {mustBePositive} = 10 % Axes tick font size
|
|
LabelFontSize (1, 1) double {mustBePositive} = 10 % Label font size
|
|
Direction char {mustBeMember(Direction, {'counterclockwise', 'clockwise'})} = 'clockwise'
|
|
AxesDirection = 'normal'
|
|
AxesLabelsOffset (1, 1) double {mustBeNonnegative} = 0.1 % Offset position of axes labels
|
|
AxesScaling = 'linear' % Scaling of axes
|
|
AxesColor = [0.6, 0.6, 0.6] % Axes color
|
|
AxesLabelsEdge = 'k' % Axes label color
|
|
AxesOffset (1, 1) double {mustBeNonnegative, mustBeInteger} = 1 % Axes offset
|
|
end
|
|
|
|
%%% Private, NonCopyable, Transient Properties %%%
|
|
properties(Access = private, NonCopyable, Transient)
|
|
% Data line object
|
|
DataLines = gobjects(0)
|
|
|
|
% Background web object
|
|
ThetaAxesLines = gobjects(0)
|
|
RhoAxesLines = gobjects(0)
|
|
|
|
% Fill shade object
|
|
FillPatches = gobjects(0)
|
|
|
|
% Web axes tick values
|
|
AxesValues = [];
|
|
|
|
% Axes label object
|
|
AxesTextLabels = gobjects(0)
|
|
AxesTickLabels = gobjects(0)
|
|
|
|
% Initialize toggle state
|
|
InitializeToggle = true;
|
|
end
|
|
|
|
%%% Protected, Dependent, Hidden Properties %%%
|
|
properties(Access = protected, Dependent, Hidden)
|
|
NumDataGroups
|
|
NumDataPoints
|
|
end
|
|
|
|
methods
|
|
%%% Constructor Methods %%%
|
|
function obj = spider_plot_class(parentOrP, varargin)
|
|
% Validate number of input arguments
|
|
narginchk(1, inf);
|
|
|
|
% Check if first argument is a graphic object or data
|
|
if isa(parentOrP, 'matlab.graphics.Graphics')
|
|
% spider_plot_class(parent, P, Name, Value, ...)
|
|
args = [{parentOrP, 'P'}, varargin];
|
|
else
|
|
% spider_plot_class(P, Name, Value, ...)
|
|
args = [{'P', parentOrP}, varargin];
|
|
end
|
|
|
|
% Call superclass constructor method
|
|
obj@matlab.graphics.chartcontainer.ChartContainer(args{:});
|
|
end
|
|
|
|
%%% Set Methods %%%
|
|
function set.P(obj, value)
|
|
% Set property
|
|
obj.P = value;
|
|
|
|
% Toggle re-initialize to true if P was changed
|
|
obj.InitializeToggle = true; %#ok<*MCSUP>
|
|
end
|
|
|
|
function set.AxesLabels(obj, value)
|
|
% Validate axes labels
|
|
validateAxesLabels(value, obj.P);
|
|
|
|
% Set property
|
|
obj.AxesLabels = value;
|
|
|
|
% Toggle re-initialize to true if AxesLabels was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.LegendLabels(obj, value)
|
|
% Validate legend labels
|
|
validateLegendLabels(value, obj.P);
|
|
|
|
% Set property
|
|
obj.LegendLabels = value;
|
|
obj.LegendVisible = 'on';
|
|
|
|
% Set legend handle
|
|
obj.LegendHandle = getLegend(obj);
|
|
|
|
% Toggle re-initialize to true iLegendLabels was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesInterval(obj, value)
|
|
% Set property
|
|
obj.AxesInterval = value;
|
|
|
|
% Toggle re-initialize to true if AxesInterval was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesPrecision(obj, value)
|
|
% Set property
|
|
obj.AxesPrecision = value;
|
|
|
|
% Toggle re-initialize to true if AxesPrecision was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesDisplay(obj, value)
|
|
% Set property
|
|
obj.AxesDisplay = value;
|
|
|
|
% Toggle re-initialize to true if AxesDisplay was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesLimits(obj, value)
|
|
% Set property
|
|
obj.AxesLimits = value;
|
|
|
|
% Toggle re-initialize to true if AxesLimits was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.FillOption(obj, value)
|
|
% Set property
|
|
obj.FillOption = value;
|
|
|
|
% Toggle re-initialize to true if FillOption was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.FillTransparency(obj, value)
|
|
% Set property
|
|
obj.FillTransparency = value;
|
|
|
|
% Toggle re-initialize to true if FillTransparency was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.Color(obj, value)
|
|
% Set property
|
|
obj.Color = value;
|
|
|
|
% Toggle re-initialize to true if Color was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.LineStyle(obj, value)
|
|
% Set property
|
|
obj.LineStyle = value;
|
|
|
|
% Toggle re-initialize to true if LineStyle was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.LineWidth(obj, value)
|
|
% Set property
|
|
obj.LineWidth = value;
|
|
|
|
% Toggle re-initialize to true if LineWidth was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.Marker(obj, value)
|
|
% Set property
|
|
obj.Marker = value;
|
|
|
|
% Toggle re-initialize to true if Marker was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.MarkerSize(obj, value)
|
|
% Set property
|
|
obj.MarkerSize = value;
|
|
|
|
% Toggle re-initialize to true if MarkerSize was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesFont(obj, value)
|
|
% Set property
|
|
obj.AxesFont = value;
|
|
|
|
% Toggle re-initialize to true if AxesFont was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.LabelFont(obj, value)
|
|
% Set property
|
|
obj.LabelFont = value;
|
|
|
|
% Toggle re-initialize to true if LabelFont was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesFontSize(obj, value)
|
|
% Set property
|
|
obj.AxesFontSize = value;
|
|
|
|
% Toggle re-initialize to true if AxesFontSize was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.LabelFontSize(obj, value)
|
|
% Set property
|
|
obj.LabelFontSize = value;
|
|
|
|
% Toggle re-initialize to true if LabelFontSize was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.Direction(obj, value)
|
|
% Set property
|
|
obj.Direction = value;
|
|
|
|
% Toggle re-initialize to true if Direction was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesDirection(obj, value)
|
|
% Set property
|
|
obj.AxesDirection = value;
|
|
|
|
% Toggle re-initialize to true if Direction was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesLabelsOffset(obj, value)
|
|
% Set property
|
|
obj.AxesLabelsOffset = value;
|
|
|
|
% Toggle re-initialize to true if AxesLabelsOffset was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesScaling(obj, value)
|
|
% Set property
|
|
obj.AxesScaling = value;
|
|
|
|
% Toggle re-initialize to true if AxesScaling was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesColor(obj, value)
|
|
% Set property
|
|
obj.AxesColor = value;
|
|
|
|
% Toggle re-initialize to true if AxesColor was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesLabelsEdge(obj, value)
|
|
% Set property
|
|
obj.AxesLabelsEdge = value;
|
|
|
|
% Toggle re-initialize to true if AxesLabelsEdge was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
function set.AxesOffset(obj, value)
|
|
% Set property
|
|
obj.AxesOffset = value;
|
|
|
|
% Toggle re-initialize to true if AxesOffset was changed
|
|
obj.InitializeToggle = true;
|
|
end
|
|
|
|
%%% Get Methods %%%
|
|
function num_data_points = get.NumDataPoints(obj)
|
|
% Get number of data points
|
|
num_data_points = size(obj.P, 2);
|
|
end
|
|
|
|
function num_data_groups = get.NumDataGroups(obj)
|
|
% Get number of data groups
|
|
num_data_groups = size(obj.P, 1);
|
|
end
|
|
|
|
function axes_labels = get.AxesLabels(obj)
|
|
% Check if value is empty
|
|
if isempty(obj.AxesLabels)
|
|
% Set axes labels
|
|
axes_labels = cellstr("Label " + (1:obj.NumDataPoints));
|
|
else
|
|
% Keep axes labels
|
|
axes_labels = obj.AxesLabels;
|
|
end
|
|
end
|
|
|
|
function legend_labels = get.LegendLabels(obj)
|
|
% Check if value is empty
|
|
if isempty(obj.LegendLabels)
|
|
% Set legend labels
|
|
legend_labels = cellstr("Data " + (1:obj.NumDataGroups));
|
|
else
|
|
% Keep legend labels
|
|
legend_labels = obj.LegendLabels;
|
|
end
|
|
end
|
|
|
|
function color = get.Color(obj)
|
|
% Check if value is empty
|
|
if isempty(obj.Color)
|
|
% Set color order
|
|
color = lines(obj.NumDataGroups);
|
|
else
|
|
% Keep color order
|
|
color = obj.Color;
|
|
end
|
|
end
|
|
|
|
function axes_limits = get.AxesLimits(obj)
|
|
% Validate axes limits
|
|
validateAxesLimits(obj.AxesLimits, obj.P);
|
|
|
|
% Get property
|
|
axes_limits = obj.AxesLimits;
|
|
end
|
|
|
|
function axes_precision = get.AxesPrecision(obj)
|
|
% Check if axes precision is numeric
|
|
if isnumeric(obj.AxesPrecision)
|
|
% Check is length is one
|
|
if length(obj.AxesPrecision) == 1
|
|
% Repeat array to number of data points
|
|
obj.AxesPrecision = repmat(obj.AxesPrecision, obj.NumDataPoints, 1);
|
|
elseif length(obj.AxesPrecision) ~= obj.NumDataPoints
|
|
error('Error: Please specify the same number of axes precision as number of data points.');
|
|
end
|
|
else
|
|
error('Error: Please make sure the axes precision is a numeric value.');
|
|
end
|
|
|
|
% Get property
|
|
axes_precision = obj.AxesPrecision;
|
|
end
|
|
|
|
function axes_scaling = get.AxesScaling(obj)
|
|
% Check if axes scaling is valid
|
|
if any(~ismember(obj.AxesScaling, {'linear', 'log'}))
|
|
error('Error: Invalid axes scaling entry. Please enter in "linear" or "log" to set axes scaling.');
|
|
end
|
|
|
|
% Check if axes scaling is a cell
|
|
if iscell(obj.AxesScaling)
|
|
% Check is length is one
|
|
if length(obj.AxesScaling) == 1
|
|
% Repeat array to number of data groups
|
|
obj.AxesScaling = repmat(obj.AxesScaling, obj.NumDataPoints, 1);
|
|
elseif length(obj.AxesScaling) ~= obj.NumDataPoints
|
|
error('Error: Please specify the same number of axes scaling as number of data points.');
|
|
end
|
|
else
|
|
% Repeat array to number of data groups
|
|
obj.AxesScaling = repmat({obj.AxesScaling}, obj.NumDataPoints, 1);
|
|
end
|
|
|
|
% Get property
|
|
axes_scaling = obj.AxesScaling;
|
|
end
|
|
|
|
function line_style = get.LineStyle(obj)
|
|
% Check if line style is a char
|
|
if ischar(obj.LineStyle)
|
|
% Convert to cell array of char
|
|
obj.LineStyle = cellstr(obj.LineStyle);
|
|
|
|
% Repeat cell to number of data groups
|
|
obj.LineStyle = repmat(obj.LineStyle, obj.NumDataGroups, 1);
|
|
elseif iscellstr(obj.LineStyle) %#ok<*ISCLSTR>
|
|
% Check is length is one
|
|
if length(obj.LineStyle) == 1
|
|
% Repeat cell to number of data groups
|
|
obj.LineStyle = repmat(obj.LineStyle, obj.NumDataGroups, 1);
|
|
elseif length(obj.LineStyle) ~= obj.NumDataGroups
|
|
error('Error: Please specify the same number of line styles as number of data groups.');
|
|
end
|
|
else
|
|
error('Error: Please make sure the line style is a char or a cell array of char.');
|
|
end
|
|
|
|
% Get property
|
|
line_style = obj.LineStyle;
|
|
end
|
|
|
|
function line_width = get.LineWidth(obj)
|
|
% Check if line width is numeric
|
|
if isnumeric(obj.LineWidth)
|
|
% Check is length is one
|
|
if length(obj.LineWidth) == 1
|
|
% Repeat array to number of data groups
|
|
obj.LineWidth = repmat(obj.LineWidth, obj.NumDataGroups, 1);
|
|
elseif length(obj.LineWidth) ~= obj.NumDataGroups
|
|
error('Error: Please specify the same number of line width as number of data groups.');
|
|
end
|
|
else
|
|
error('Error: Please make sure the line width is a numeric value.');
|
|
end
|
|
|
|
% Get property
|
|
line_width = obj.LineWidth;
|
|
end
|
|
|
|
function marker_style = get.Marker(obj)
|
|
% Check if marker type is a char
|
|
if ischar(obj.Marker)
|
|
% Convert to cell array of char
|
|
obj.Marker = cellstr(obj.Marker);
|
|
|
|
% Repeat cell to number of data groups
|
|
obj.Marker = repmat(obj.Marker, obj.NumDataGroups, 1);
|
|
elseif iscellstr(obj.Marker)
|
|
% Check is length is one
|
|
if length(obj.Marker) == 1
|
|
% Repeat cell to number of data groups
|
|
obj.Marker = repmat(obj.Marker, obj.NumDataGroups, 1);
|
|
elseif length(obj.Marker) ~= obj.NumDataGroups
|
|
error('Error: Please specify the same number of line styles as number of data groups.');
|
|
end
|
|
else
|
|
error('Error: Please make sure the line style is a char or a cell array of char.');
|
|
end
|
|
|
|
% Get property
|
|
marker_style = obj.Marker;
|
|
end
|
|
|
|
function marker_size = get.MarkerSize(obj)
|
|
% Check if line width is numeric
|
|
if isnumeric(obj.MarkerSize)
|
|
if length(obj.MarkerSize) == 1
|
|
% Repeat array to number of data groups
|
|
obj.MarkerSize = repmat(obj.MarkerSize, obj.NumDataGroups, 1);
|
|
elseif length(obj.MarkerSize) ~= obj.NumDataGroups
|
|
error('Error: Please specify the same number of line width as number of data groups.');
|
|
end
|
|
else
|
|
error('Error: Please make sure the line width is numeric.');
|
|
end
|
|
|
|
% Get property
|
|
marker_size = obj.MarkerSize;
|
|
end
|
|
|
|
function axes_direction = get.AxesDirection(obj)
|
|
% Check if axes direction is a cell
|
|
if iscell(obj.AxesDirection)
|
|
% Check is length is one
|
|
if length(obj.AxesDirection) == 1
|
|
% Repeat array to number of data groups
|
|
obj.AxesDirection = repmat(obj.AxesDirection, obj.NumDataPoints, 1);
|
|
elseif length(obj.AxesDirection) ~= obj.NumDataPoints
|
|
error('Error: Please specify the same number of axes direction as number of data points.');
|
|
end
|
|
else
|
|
% Repeat array to number of data groups
|
|
obj.AxesDirection = repmat({obj.AxesDirection}, obj.NumDataPoints, 1);
|
|
end
|
|
|
|
% Get property
|
|
axes_direction = obj.AxesDirection;
|
|
end
|
|
|
|
function axes_offset = get.AxesOffset(obj)
|
|
% Check if axes offset is valid
|
|
if obj.AxesOffset > obj.AxesInterval
|
|
error('Error: Invalid axes offset entry. Please enter in an integer value that is between [0, axes_interval].');
|
|
end
|
|
|
|
% Get property
|
|
axes_offset = obj.AxesOffset;
|
|
end
|
|
end
|
|
|
|
methods (Access = public)
|
|
function title(obj, title_text, varargin)
|
|
% Get axes and title handles
|
|
ax = getAxes(obj);
|
|
tlt = ax.Title;
|
|
|
|
% Set title string
|
|
tlt.String = title_text;
|
|
|
|
% Initialze name-value arguments
|
|
name_arguments = varargin(1:2:end);
|
|
value_arguments = varargin(2:2:end);
|
|
|
|
% Iterate through name-value arguments
|
|
for ii = 1:length(name_arguments)
|
|
% Set name value pair
|
|
name = name_arguments{ii};
|
|
value = value_arguments{ii};
|
|
tlt.(name) = value;
|
|
end
|
|
end
|
|
end
|
|
|
|
methods (Access = protected)
|
|
%%% Setup Methods %%%
|
|
function setup(obj)
|
|
% Figure properties
|
|
fig = gcf;
|
|
fig.Color = 'w';
|
|
|
|
% Axis properties
|
|
ax = getAxes(obj);
|
|
hold(ax, 'on');
|
|
axis(ax, 'square');
|
|
axis(ax, 'off');
|
|
axis(ax, [-1, 1, -1, 1] * 1.3);
|
|
end
|
|
|
|
%%% Update Methods %%%
|
|
function update(obj)
|
|
% Check re-initialize toggle
|
|
if obj.InitializeToggle
|
|
% Reset graphic objects
|
|
reset_objects(obj);
|
|
initialize(obj);
|
|
|
|
% Set initialize toggle to false
|
|
obj.InitializeToggle = false;
|
|
end
|
|
|
|
% Update plot appearance
|
|
update_plot(obj);
|
|
end
|
|
|
|
function reset_objects(obj)
|
|
% Delete old objects
|
|
delete(obj.DataLines)
|
|
delete(obj.ThetaAxesLines)
|
|
delete(obj.RhoAxesLines)
|
|
delete(obj.FillPatches)
|
|
delete(obj.AxesTextLabels)
|
|
delete(obj.AxesTickLabels)
|
|
|
|
% Reset object with empty objects
|
|
obj.DataLines = gobjects(0);
|
|
obj.ThetaAxesLines = gobjects(0);
|
|
obj.RhoAxesLines = gobjects(0);
|
|
obj.FillPatches = gobjects(0);
|
|
obj.AxesValues = [];
|
|
obj.AxesTextLabels = gobjects(0);
|
|
obj.AxesTickLabels = gobjects(0);
|
|
end
|
|
|
|
function initialize(obj)
|
|
% Selected data
|
|
P_selected = obj.P;
|
|
|
|
% Check axes scaling option
|
|
log_index = strcmp(obj.AxesScaling, 'log');
|
|
|
|
% If any log scaling is specified
|
|
if any(log_index)
|
|
% Initialize copy
|
|
P_log = P_selected(:, log_index);
|
|
|
|
% Logarithm of base 10, account for numbers less than 1
|
|
P_log = sign(P_log) .* log10(abs(P_log));
|
|
|
|
% Minimum and maximun log limits
|
|
min_limit = min(min(fix(P_log)));
|
|
max_limit = max(max(ceil(P_log)));
|
|
recommended_axes_interval = max_limit - min_limit;
|
|
|
|
% Warning message
|
|
warning('For the log scale values, recommended axes limit is [%i, %i] with an axes interval of %i.',...
|
|
10^min_limit, 10^max_limit, recommended_axes_interval);
|
|
|
|
% Replace original
|
|
P_selected(:, log_index) = P_log;
|
|
end
|
|
|
|
% Axes handles
|
|
ax = getAxes(obj);
|
|
|
|
% Polar increments
|
|
theta_increment = 2*pi/obj.NumDataPoints;
|
|
full_interval = obj.AxesInterval+1;
|
|
rho_offset = obj.AxesOffset/full_interval;
|
|
|
|
%%% Scale Data %%%
|
|
% Pre-allocation
|
|
P_scaled = zeros(size(P_selected));
|
|
axes_range = zeros(3, obj.NumDataPoints);
|
|
|
|
% Check axes scaling option
|
|
axes_direction_index = strcmp(obj.AxesDirection, 'reverse');
|
|
|
|
% Iterate through number of data points
|
|
for ii = 1:obj.NumDataPoints
|
|
% Check for one data group and no axes limits
|
|
if obj.NumDataGroups == 1 && isempty(obj.AxesLimits)
|
|
% Group of points
|
|
group_points = P_selected(:, :);
|
|
else
|
|
% Group of points
|
|
group_points = P_selected(:, ii);
|
|
end
|
|
|
|
% Check for log axes scaling option
|
|
if log_index(ii)
|
|
% Minimum and maximun log limits
|
|
min_value = min(fix(group_points));
|
|
max_value = max(ceil(group_points));
|
|
else
|
|
% Automatically the range of each group
|
|
min_value = min(group_points);
|
|
max_value = max(group_points);
|
|
end
|
|
|
|
% Range of min and max values
|
|
range = max_value - min_value;
|
|
|
|
% Check if axes_limits is not empty
|
|
if ~isempty(obj.AxesLimits)
|
|
% Check for log axes scaling option
|
|
if log_index(ii)
|
|
% Logarithm of base 10, account for numbers less than 1
|
|
obj.AxesLimits(:, ii) = sign(obj.AxesLimits(:, ii)) .* log10(abs(obj.AxesLimits(:, ii)));
|
|
end
|
|
|
|
% Manually set the range of each group
|
|
min_value = obj.AxesLimits(1, ii);
|
|
max_value = obj.AxesLimits(2, ii);
|
|
range = max_value - min_value;
|
|
|
|
% Check if the axes limits are within range of points
|
|
if min_value > min(group_points) || max_value < max(group_points)
|
|
error('Error: Please make the manually specified axes limits are within range of the data points.');
|
|
end
|
|
end
|
|
|
|
% Scale points to range from [0, 1]
|
|
P_scaled(:, ii) = ((P_selected(:, ii) - min_value) / range);
|
|
|
|
% If reverse axes direction is specified
|
|
if axes_direction_index(ii)
|
|
% Store to array
|
|
axes_range(:, ii) = [max_value; min_value; range];
|
|
P_scaled(:, ii) = -(P_scaled(:, ii) - 1);
|
|
else
|
|
% Store to array
|
|
axes_range(:, ii) = [min_value; max_value; range];
|
|
end
|
|
|
|
% Add offset of [rho_offset] and scaling factor of [1 - rho_offset]
|
|
P_scaled(:, ii) = P_scaled(:, ii) * (1 - rho_offset) + rho_offset;
|
|
end
|
|
|
|
%%% Polar Axes %%%
|
|
% Polar coordinates
|
|
rho_increment = 1/full_interval;
|
|
rho = 0:rho_increment:1;
|
|
|
|
% Check specified direction of rotation
|
|
switch obj.Direction
|
|
case 'counterclockwise'
|
|
% Shift by pi/2 to set starting axis the vertical line
|
|
theta = (0:theta_increment:2*pi) + (pi/2);
|
|
case 'clockwise'
|
|
% Shift by pi/2 to set starting axis the vertical line
|
|
theta = (0:-theta_increment:-2*pi) + (pi/2);
|
|
end
|
|
|
|
% Remainder after using a modulus of 2*pi
|
|
theta = mod(theta, 2*pi);
|
|
|
|
% Iterate through each theta
|
|
for ii = 1:length(theta)-1
|
|
% Convert polar to cartesian coordinates
|
|
[x_axes, y_axes] = pol2cart(theta(ii), rho);
|
|
|
|
% Plot
|
|
obj.ThetaAxesLines(ii) = line(ax, x_axes, y_axes,...
|
|
'LineWidth', 1.5, ...
|
|
'Color', obj.AxesColor,...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
|
|
% Iterate through each rho
|
|
for ii = 2:length(rho)
|
|
% Convert polar to cartesian coordinates
|
|
[x_axes, y_axes] = pol2cart(theta, rho(ii));
|
|
|
|
% Plot
|
|
obj.RhoAxesLines(ii-1) = line(ax, x_axes, y_axes,...
|
|
'Color', obj.AxesColor,...
|
|
'HandleVisibility', 'off');
|
|
end
|
|
|
|
% Set end index depending on axes display argument
|
|
switch obj.AxesDisplay
|
|
case 'all'
|
|
theta_end_index = length(theta)-1;
|
|
case 'one'
|
|
theta_end_index = 1;
|
|
case 'none'
|
|
theta_end_index = 0;
|
|
end
|
|
|
|
% Rho start index and offset interval
|
|
rho_start_index = obj.AxesOffset+1;
|
|
offset_interval = full_interval - obj.AxesOffset;
|
|
|
|
%%% Plot %%%
|
|
% Initialize data children
|
|
for ii = 1:obj.NumDataGroups
|
|
obj.FillPatches(ii) = patch(nan, nan, nan,...
|
|
'Parent', ax,...
|
|
'EdgeColor', 'none',...
|
|
'HandleVisibility', 'off');
|
|
obj.DataLines(ii) = line(nan, nan,...
|
|
'Parent', ax);
|
|
end
|
|
|
|
% Iterate through number of data groups
|
|
for ii = 1:obj.NumDataGroups
|
|
% Convert polar to cartesian coordinates
|
|
[x_points, y_points] = pol2cart(theta(1:end-1), P_scaled(ii, :));
|
|
|
|
% Make points circular
|
|
x_circular = [x_points, x_points(1)];
|
|
y_circular = [y_points, y_points(1)];
|
|
|
|
% Plot data points
|
|
obj.DataLines(ii).XData = x_circular;
|
|
obj.DataLines(ii).YData = y_circular;
|
|
|
|
% Check if fill option is toggled on
|
|
obj.FillPatches(ii).XData = x_circular;
|
|
obj.FillPatches(ii).YData = y_circular;
|
|
end
|
|
|
|
%%% Labels %%%
|
|
% Iterate through number of data points
|
|
for ii = 1:obj.NumDataPoints
|
|
% Convert polar to cartesian coordinates
|
|
[x_axes, y_axes] = pol2cart(theta, rho(end));
|
|
|
|
% Angle of point in radians
|
|
[horz_align, vert_align, x_pos, y_pos] = obj.quadrant_position(theta(ii));
|
|
|
|
% Display text label
|
|
obj.AxesTextLabels(ii) = text(ax, x_axes(ii)+x_pos, y_axes(ii)+y_pos, '',...
|
|
'Units', 'Data',...
|
|
'HorizontalAlignment', horz_align,...
|
|
'VerticalAlignment', vert_align,...
|
|
'EdgeColor', obj.AxesLabelsEdge,...
|
|
'BackgroundColor', 'w',...
|
|
'FontName', obj.LabelFont,...
|
|
'FontSize', obj.LabelFontSize,...
|
|
'Visible', 'off');
|
|
end
|
|
|
|
% Iterate through each theta
|
|
for ii = 1:theta_end_index
|
|
% Convert polar to cartesian coordinates
|
|
[x_axes, y_axes] = pol2cart(theta(ii), rho);
|
|
|
|
% Iterate through points on isocurve
|
|
for jj = rho_start_index:length(rho)
|
|
% Axes increment value
|
|
min_value = axes_range(1, ii);
|
|
range = axes_range(3, ii);
|
|
|
|
% If reverse axes direction is specified
|
|
if axes_direction_index(ii)
|
|
% Axes increment value
|
|
axes_value = min_value - (range/offset_interval) * (jj-rho_start_index);
|
|
else
|
|
% Axes increment value
|
|
axes_value = min_value + (range/offset_interval) * (jj-rho_start_index);
|
|
end
|
|
|
|
% Check for log axes scaling option
|
|
if log_index(ii)
|
|
% Exponent to the tenth power
|
|
axes_value = 10^axes_value;
|
|
end
|
|
|
|
% Display axes text
|
|
obj.AxesValues(ii, jj) = axes_value;
|
|
obj.AxesTickLabels(ii, jj) = text(ax, x_axes(jj), y_axes(jj), '',...
|
|
'Units', 'Data',...
|
|
'Color', 'k',...
|
|
'FontName', obj.AxesFont,...
|
|
'FontSize', obj.AxesFontSize,...
|
|
'HorizontalAlignment', 'center',...
|
|
'VerticalAlignment', 'middle',...
|
|
'Visible', 'off');
|
|
end
|
|
end
|
|
|
|
% Keep only valid entries
|
|
obj.AxesValues = obj.AxesValues(:, rho_start_index:end);
|
|
obj.AxesTickLabels = obj.AxesTickLabels(:, rho_start_index:end);
|
|
end
|
|
|
|
function update_plot(obj)
|
|
% Iterate through patch objects
|
|
for ii = 1:numel(obj.FillPatches)
|
|
% Check fill option argument
|
|
if obj.FillOption
|
|
% Fill in patch with specified color and transparency
|
|
obj.FillPatches(ii).FaceColor = obj.Color(ii, :);
|
|
obj.FillPatches(ii).FaceAlpha = obj.FillTransparency;
|
|
else
|
|
% Set no patch color
|
|
obj.FillPatches(ii).FaceColor = 'none';
|
|
end
|
|
end
|
|
|
|
% Iterate through data line objects
|
|
for ii = 1:numel(obj.DataLines)
|
|
% Set line settings
|
|
obj.DataLines(ii).LineStyle = obj.LineStyle{ii};
|
|
obj.DataLines(ii).Marker = obj.Marker{ii};
|
|
obj.DataLines(ii).Color = obj.Color(ii, :);
|
|
obj.DataLines(ii).LineWidth = obj.LineWidth(ii);
|
|
obj.DataLines(ii).MarkerSize = obj.MarkerSize(ii);
|
|
obj.DataLines(ii).MarkerFaceColor = obj.Color(ii, :);
|
|
obj.DataLines(ii).DisplayName = obj.LegendLabels{ii};
|
|
end
|
|
|
|
% Check axes display argument
|
|
if isequal(obj.AxesLabels, 'none')
|
|
% Set axes text labels to invisible
|
|
set(obj.AxesTextLabels, 'Visible', 'off')
|
|
else
|
|
% Set axes text labels to visible
|
|
set(obj.AxesTextLabels, 'Visible', 'on')
|
|
|
|
% Iterate through number of data points
|
|
for ii = 1:obj.NumDataPoints
|
|
% Display text label
|
|
obj.AxesTextLabels(ii).String = obj.AxesLabels{ii};
|
|
obj.AxesTextLabels(ii).FontName = obj.LabelFont;
|
|
obj.AxesTextLabels(ii).FontSize = obj.LabelFontSize;
|
|
obj.AxesTextLabels(ii).EdgeColor = obj.AxesLabelsEdge;
|
|
end
|
|
end
|
|
|
|
% Check axes precision argument
|
|
if isequal(obj.AxesPrecision, 'none')
|
|
% Set axes tick label invisible
|
|
set(obj.AxesTickLabels, 'Visible', 'off')
|
|
else
|
|
% Set axes tick label visible
|
|
set(obj.AxesTickLabels, 'Visible', 'on')
|
|
|
|
% Iterate through axes values rows
|
|
for ii = 1:size(obj.AxesValues, 1)
|
|
% Iterate through axes values columns
|
|
for jj = 1:size(obj.AxesValues, 2)
|
|
% Display and set axes tick label settings
|
|
text_str = sprintf(sprintf('%%.%if', obj.AxesPrecision(ii)), obj.AxesValues(ii, jj));
|
|
obj.AxesTickLabels(ii, jj).String = text_str;
|
|
obj.AxesTickLabels(ii, jj).FontName= obj.AxesFont;
|
|
obj.AxesTickLabels(ii, jj).FontSize = obj.AxesFontSize;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function [horz_align, vert_align, x_pos, y_pos] = quadrant_position(obj, theta_point)
|
|
% Find out which quadrant the point is in
|
|
if theta_point == 0
|
|
quadrant = 0;
|
|
elseif theta_point == pi/2
|
|
quadrant = 1.5;
|
|
elseif theta_point == pi
|
|
quadrant = 2.5;
|
|
elseif theta_point == 3*pi/2
|
|
quadrant = 3.5;
|
|
elseif theta_point == 2*pi
|
|
quadrant = 0;
|
|
elseif theta_point > 0 && theta_point < pi/2
|
|
quadrant = 1;
|
|
elseif theta_point > pi/2 && theta_point < pi
|
|
quadrant = 2;
|
|
elseif theta_point > pi && theta_point < 3*pi/2
|
|
quadrant = 3;
|
|
elseif theta_point > 3*pi/2 && theta_point < 2*pi
|
|
quadrant = 4;
|
|
end
|
|
|
|
% Adjust label alignment depending on quadrant
|
|
switch quadrant
|
|
case 0
|
|
horz_align = 'left';
|
|
vert_align = 'middle';
|
|
x_pos = obj.AxesLabelsOffset;
|
|
y_pos = 0;
|
|
case 1
|
|
horz_align = 'left';
|
|
vert_align = 'bottom';
|
|
x_pos = obj.AxesLabelsOffset;
|
|
y_pos = obj.AxesLabelsOffset;
|
|
case 1.5
|
|
horz_align = 'center';
|
|
vert_align = 'bottom';
|
|
x_pos = 0;
|
|
y_pos = obj.AxesLabelsOffset;
|
|
case 2
|
|
horz_align = 'right';
|
|
vert_align = 'bottom';
|
|
x_pos = -obj.AxesLabelsOffset;
|
|
y_pos = obj.AxesLabelsOffset;
|
|
case 2.5
|
|
horz_align = 'right';
|
|
vert_align = 'middle';
|
|
x_pos = -obj.AxesLabelsOffset;
|
|
y_pos = 0;
|
|
case 3
|
|
horz_align = 'right';
|
|
vert_align = 'top';
|
|
x_pos = -obj.AxesLabelsOffset;
|
|
y_pos = -obj.AxesLabelsOffset;
|
|
case 3.5
|
|
horz_align = 'center';
|
|
vert_align = 'top';
|
|
x_pos = 0;
|
|
y_pos = -obj.AxesLabelsOffset;
|
|
case 4
|
|
horz_align = 'left';
|
|
vert_align = 'top';
|
|
x_pos = obj.AxesLabelsOffset;
|
|
y_pos = -obj.AxesLabelsOffset;
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
%%% Custom Validation Functions %%%
|
|
% Validate axes labels
|
|
function validateAxesLabels(axes_labels, P)
|
|
if ~isequal(axes_labels, 'none')
|
|
validateattributes(axes_labels, {'cell'}, {'size', [1, size(P, 2)]}, mfilename, 'axes_labels')
|
|
end
|
|
end
|
|
|
|
% Validate legend labels
|
|
function validateLegendLabels(legend_labels, P)
|
|
if ~isequal(legend_labels, 'none')
|
|
validateattributes(legend_labels, {'cell'}, {'size', [1, size(P, 1)]}, mfilename, 'legend_labels')
|
|
end
|
|
end
|
|
|
|
% Validate axes limits
|
|
function validateAxesLimits(axes_limits, P)
|
|
if ~isempty(axes_limits)
|
|
validateattributes(axes_limits, {'double'}, {'size', [2, size(P, 2)]}, mfilename, 'axes_limits')
|
|
|
|
% Lower and upper limits
|
|
lower_limits = axes_limits(1, :);
|
|
upper_limits = axes_limits(2, :);
|
|
|
|
% Difference in upper and lower limits
|
|
diff_limits = upper_limits - lower_limits;
|
|
|
|
% Check to make sure upper limit is greater than lower limit
|
|
if any(diff_limits < 0)
|
|
error('Error: Please make sure max axes limits are greater than the min axes limits.');
|
|
end
|
|
|
|
% Check the range of axes limits
|
|
if any(diff_limits == 0)
|
|
error('Error: Please make sure the min and max axes limits are different.');
|
|
end
|
|
end
|
|
end |