基于matlab实现地平线图

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。

🍎个人主页:Matlab科研工作室

🍊个人信条:格物致知。

更多Matlab仿真内容点击👇

智能优化算法       神经网络预测       雷达通信       无线传感器        电力系统

信号处理              图像处理               路径规划       元胞自动机        无人机 

⛄ 内容介绍

描述

Horizon Chart 是一种数据可视化技术,它以紧凑且分层的格式显示时间序列数据,提高可读性并能够随时间比较多个数据集。

依赖关系

为了获得最佳性能和准确的图表,请安装Mapping Toolbox。

句法

  • HorizonChart 为每个切片创建 Horizon Chart x 轴数据和 y 轴数据

  • horizonChart(x, y)创建一个包含 x 和 y 数据且 NumBands = 2 的水平图表,即在每个切片中,数据分为 2 个区域 - 一个位于基线上方,一个位于基线下方

  • horizonChart(x, y, numBands)使用 x 和 y 数据创建一个水平图表,其中波段数 = numBands。Number of Bands 是数据被划分为的部分的数量

  • horizonChart(__ , Name, Value)使用一个或多个名称-值对参数指定地平线图的其他选项。在所有其他输入参数之后指定选项。

名称-值对参数/属性

  • XDataXData 是一个二维矩阵,其中每列指定要在图表的各个切片中显示的数据的 x 坐标。
    XData也可以是一维矩阵,它可以表示每个子图/单独切片的公共 x 值。

  • YDataYData 是一个二维矩阵,其中每列指定要在图表的各个切片中显示的数据的 y 坐标。

  • Labels图表中每个切片的标签列表

  • NumBands用于划分地平线图表的波段/段数

风格名称-值对参数/属性

  • ColorAboveBaseline它用于确定基线上方的条带着色的颜色梯度。

  • ColorBelowBaseline它用于确定基线以下的带被着色的颜色梯度

  • XLabelX 轴标签

  • YLabelY 轴标签

  • Title地平线图的标题

⛄ 部分代码

classdef horizonChart < matlab.graphics.chartcontainer.ChartContainer  & ...        matlab.graphics.chartcontainer.mixin.Legend    % horizonChart creates a Horizon Chart x-axis data and    % y-axis data for each slice    %     % horizonChart(x, y) creates a horizon chart with x an y data and    % NumBands = 2 i.e. in each of the slices, the data is divided into    % 2 regions - one above the baseline and one below the baseline    %     % horizonChart(x, y, numBands) creates a horizon chart with x and y data    % with number of bands = numBands. Number of Bands is the number of    % sections that the data is divided into.    %     % horizonChart(__ , Name, Value) specifies additional options for the horizon chart    % using one or more name-value pair arguments. Specify the options after all other    % input arguments.            properties        XData (:, :) double = [];        YData (:, :) double = [];        Labels (1, :) string = [];        NumBands double {mustBeGreaterThanOrEqual(NumBands, 1)} = 2;        XLabel string = "";        YLabel string = "";        Title string = "";    end    properties(Dependent)        Baseline double = 0;        ColorAboveBaseline {validatecolor} = [0, 0, 1];        ColorBelowBaseline {validatecolor} = [1, 0, 0];    end        properties(Access = private,Transient,NonCopyable)        PatchObjectListPerSlice (:, :)  = [];        AxisHandlePerSlice (1, :) = [];        SegRanges (1, :) double = [];        NumSlices;        ColorMap (:, 3) double;                     end    properties(Access = private)        Baseline_I = NaN ;        BaselineSetMethod string = "auto";                ColorAboveBaseline_I = NaN;        ColorAboveBaselineSetMethod = "auto";        ColorBelowBaseline_I = NaN;        ColorBelowBaselineSetMethod = "auto";                ContainsMappingToolbox matlab.lang.OnOffSwitchState = 'on';    end    methods         function obj = horizonChart(varargin)           % Intialize list of arguments           args = varargin;           leadingArgs = cell(0);            if numel(args) >= 2 && isnumeric(args{1}) ...                && isnumeric(args{2})                                    x = args{1};                   y = args{2};                if mod(numel(args), 2) == 1 && isnumeric(args{3})                   % horizonChart(x, y, numBands)                   numBands = args{3};                   leadingArgs = [leadingArgs {'XData', x, 'YData', y , 'NumBands', numBands}];                   args = args(4:end);                else                   % horizonChart(x, y)                   leadingArgs = [leadingArgs {'XData', x, 'YData', y }];                   args = args(3:end);                end            else                if numel(args) < 2                    error('Invalid Input Arguments. Too few inputs were provided. ')                else                    error('The first two arguments are not numeric and do not conform to XData and YData definition')                end            end                        % Combine positional arguments with name/value pairs            args = [leadingArgs args];            % Call superclass constructor method            obj@matlab.graphics.chartcontainer.ChartContainer(args{:});        end    end    methods(Access=protected)        function setup(obj)            if ~any(strcmp('Mapping Toolbox', {ver().Name}))                 obj.ContainsMappingToolbox = 'off';                warning("Mapping Toolbox is not installed. " + ...                    "This may lead to degraded performance of the horizon chart. " + ...                    "Install Mapping Toolbox for better performance")            end        end        function update(obj)                        [obj.XData, obj.YData] = transformInputData(obj.XData, obj.YData) ;            % Validate Inputs             validateInputs(obj.XData, obj.YData, obj.Labels);                        % If Grid Layout is already defined then clear the layout            % during the update step            children = obj.getLayout().Children;            set(children, "Parent" , []);                        % Clear all patch objects             obj.PatchObjectListPerSlice = [];            obj.AxisHandlePerSlice = [];                        % Set GridLayout to be vertical layout            obj.NumSlices = size(obj.YData, 2);            obj.getLayout().GridSize = [obj.NumSlices 1];            title(obj.getLayout(), obj.Title);            xlabel(obj.getLayout(), obj.XLabel);            ylabel(obj.getLayout(), obj.YLabel);                        % If user doesn't specify baseline we setup the baseline as the            % median of the data. If the user specifies baseline, we adjust            % the segment lengths to match the new baseline.            if obj.BaselineSetMethod == "auto"                obj.calculateSegmentsWithoutUserSetBaseline();            else                obj.calculateSegmentsWithUserSetBaseline();            end                         for slice = 1:obj.NumSlices                % We obtain XData/ YData for each slice and calculate                 % which band each data point belongs to                  sliceXData = obj.XData(:, min(slice,size(obj.XData,2)))';                sliceYData = obj.YData(:, slice)';                binsPoint = binData(sliceYData, obj.SegRanges);                PatchObjectList = [];                order = [];                               % Get axis for the current tile and set all the properties                ax = nexttile(obj.getLayout());                               % Disable data tips                disableDefaultInteractivity(ax)                % Specify labels only if the user has specified labels for                % each slice                if slice <= numel(obj.Labels)                     title(ax, obj.Labels(slice));                end                 y_min_slice = max(obj.YData(:));                                ax.XLim = [min(sliceXData), max(sliceXData)];                ax.YTickLabel = [];                ax.YTick = [];                polygonOrder = gobjects(0);                hold(ax, 'all')                                % Calculate color map for all the bands                bgColor = get(ax, 'Color');                order = ax.ColorOrder;                                if obj.ColorAboveBaselineSetMethod == "auto"                    obj.ColorAboveBaseline_I = order(1, :);                 end                                if obj.ColorBelowBaselineSetMethod == "auto"                    obj.ColorBelowBaseline_I = order(2, :);                end                                               obj.CalculateColorMap(bgColor);                % For each band we create a polygon that makes up the area                % of the band.                 for band = 1:obj.NumBands                      lower = obj.SegRanges(band);                    upper = obj.SegRanges(band + 1);                    color = obj.ColorMap(band, :);                    % Calculate the vertices of the polygon depeding on                    % whether it lies above the baseline/ or below the                    % baseline                     [x_vertices, y_vertices] = generatePolygonPoints(sliceXData, sliceYData, lower, upper, lower >= obj.Baseline_I, obj.ContainsMappingToolbox);                                        % Transform polygon and reflect it over the baseline                    y_vertices = transformPolygon(y_vertices, lower, upper, obj.Baseline_I);                                                            % Create the PatchObject for the band                    PatchObject = patch(ax, x_vertices, y_vertices, color, 'DisplayName', num2str(lower) + " - " + num2str(upper));                                        % If x_vertices/ y_vertices are empty then we need to                    % create an empty patch object                    if numel(x_vertices) == 0                         PatchObject = patch(ax, NaN, NaN, color, 'DisplayName', num2str(lower) + " - " + num2str(upper));                    else                         % Find minimum all transformed y data in a particular slice                         y_min_slice = min(y_min_slice, min(y_vertices(:)));                    end                      % The bands that lie furthest from the baseline are                    % displayed in the front. While the bands that are the                    % closest to the baseline are displayed in the back                    if lower >= obj.Baseline_I                        polygonOrder = [PatchObject, polygonOrder];                    else                        polygonOrder = [polygonOrder, PatchObject];                    end                                        PatchObjectList = [PatchObjectList, PatchObject];                end                                if y_min_slice ~= obj.Baseline_I                    ax.YLim(1) = y_min_slice;                end                ax.Children = polygonOrder;                hold(ax, 'off')                obj.PatchObjectListPerSlice = [obj.PatchObjectListPerSlice; PatchObjectList];                obj.AxisHandlePerSlice = [obj.AxisHandlePerSlice, ax];            end              cbh = obj.buildColorBar(obj.AxisHandlePerSlice(end));            cbh.Layout.Tile = 'east';        end        function CalculateColorMap(obj, backgroundColor)            % The color of a band is decided by whether it lies above or            % below the baseline. In case of bands that lie below the            % baseline, the lower bands have a darker shade of            % obj.colorsBelowBaseline. In case of bands that lie above the            % baseline, the upper bands have a darker shade of            % obj.colorsAboveBaseline            nBandsBelowBaseline = sum(obj.SegRanges(2:end)<=obj.Baseline_I);            nBandsAboveBaseline = obj.NumBands - nBandsBelowBaseline;                        % Calculate color gradient for the bands below the baseline            alphas = fliplr(linspace(0.5, 1, nBandsBelowBaseline))';            colorsBelowBaseline = alphas .* obj.ColorBelowBaseline_I + (1 - alphas) .* backgroundColor;            % Calculate color gradient for the bands above the baseline            alphas = linspace(0.5, 1, nBandsAboveBaseline)';            colorsAboveBaseline = alphas .* obj.ColorAboveBaseline_I + (1 - alphas) .* backgroundColor;            obj.ColorMap = [colorsBelowBaseline; colorsAboveBaseline];        end            end    methods(Access = private)        function calculateSegmentsWithoutUserSetBaseline(obj)            % We divide the data into segments which contain equal amount of            % data. For eg: If NumBands = 5, the first segment contains 20%            % of the data. The second segment represents 20% - 40% of data            % and so on            obj.SegRanges = quantile(obj.YData(:), linspace(0, 1, obj.NumBands + 1));            if mod(obj.NumBands, 2) == 0                obj.Baseline_I = obj.SegRanges(obj.NumBands / 2 + 1);            else                obj.Baseline_I = obj.SegRanges((obj.NumBands + 1) / 2);            end        end        function calculateSegmentsWithUserSetBaseline(obj)            % In the first step, we divide data into segments using the            % method proposed above.            % Then we calculate segments below the baseline and above the            % baseline. We accordingly divide the data below/above the            % baseline using the newly found segments.             all_data = obj.YData(:);            max_data = max(all_data);            min_data = min(all_data);            if obj.Baseline_I >= max_data                nSegmentsAboveBaseline = 0;                nSegmentsBelowBaseline = obj.NumBands;            elseif obj.Baseline_I <= min_data                nSegmentsAboveBaseline = obj.NumBands;                nSegmentsBelowBaseline = 0;            else                segRanges = quantile(all_data, linspace(0, 1, obj.NumBands + 1));                nSegmentsBelowBaseline = find(obj.Baseline_I >= segRanges, 1, 'last');                if nSegmentsBelowBaseline == 0                    nSegmentsBelowBaseline = nSegmentsBelowBaseline + 1;                elseif nSegmentsBelowBaseline == obj.NumBands                    nSegmentsBelowBaseline = nSegmentsBelowBaseline - 1;                end                nSegmentsAboveBaseline = obj.NumBands- nSegmentsBelowBaseline;            end            dataBelowBaseline = all_data(all_data < obj.Baseline_I);            dataAboveBaseline = all_data(all_data > obj.Baseline_I);            segRangesBelowBaseline = [];            segRangesAboveBaseline = [];            if nSegmentsBelowBaseline ~= 0                 segRangesBelowBaseline = quantile(dataBelowBaseline, linspace(0, 1, nSegmentsBelowBaseline + 1));            end             if nSegmentsAboveBaseline ~= 0                segRangesAboveBaseline = quantile(dataAboveBaseline, linspace(0, 1, nSegmentsAboveBaseline + 1));            end             obj.SegRanges = [segRangesBelowBaseline(1:nSegmentsBelowBaseline), obj.Baseline_I, segRangesAboveBaseline(2: nSegmentsAboveBaseline + 1)];        end        function cbh = buildColorBar(obj, ax)            % Build a colorbar where the length of each color is proportional             % to the ratio of the length of each segment            segLengths = obj.SegRanges(2:end) - obj.SegRanges(1: end - 1);            lengthRatios = segLengths / sum(segLengths);            lengthRatios = round(lengthRatios * 100);            tLength = sum(lengthRatios);            modifiedColorMap = colormap(repelem(obj.ColorMap, lengthRatios, 1));            cbh = colorbar(ax);            cumulLengthRatios = cumsum(lengthRatios) / tLength;            cbh.Ticks = [0, cumulLengthRatios];            cbh.TickLabels = num2cell(obj.SegRanges);        end    end    methods        function set.Baseline(obj, newBaseline)            obj.BaselineSetMethod = "manual";            obj.Baseline_I = newBaseline;        end        function baseline = get.Baseline(obj)             baseline = obj.Baseline_I;        end        function set.ColorAboveBaseline(obj, color)            obj.ColorAboveBaselineSetMethod = "manual";            obj.ColorAboveBaseline_I = validatecolor(color);        end        function colorAboveBaseline = get.ColorAboveBaseline(obj)            colorAboveBaseline = obj.ColorAboveBaseline_I;        end        function set.ColorBelowBaseline(obj, color)            obj.ColorBelowBaselineSetMethod = "manual";            obj.ColorBelowBaseline_I = validatecolor(color);        end        function colorBelowBaseline = get.ColorBelowBaseline(obj)            colorBelowBaseline = obj.ColorBelowBaseline_I;        end    endendfunction [x, y] = validateInputs(x, y, labels)    x_size = size(x);    y_size = size(y);    if x_size(1) == 0 || x_size(2) == 0 || y_size(1) == 0 || y_size(2) == 0        error("Horizon chart cannot be constructed with empty data");    end    if ~isreal(x) || ~isreal(y)        error("Chart does not work for complex data")    end     if x_size(1) ~= y_size(1)        error("Number of datapoints for each slice does not match between X and Y");    end    if ~validateIsIncreasing(x)        error("X values should be strictly monotonically increasing")    end    if x_size(2) > 1 && x_size(2) < y_size(2)        error("Number of slices for X-Data can either be 1 or need to match the Y-Data");    end    if numel(labels) ~= 0 && numel(labels) ~= y_size(2)        error("Size of Labels is incorrect. It should either be empty or equal to the number of slices/ 1st dimension of Y data");    endendfunction isIncreasing = validateIsIncreasing(x)    for slice = 1:size(x, 2)        if ~issorted(x(:, slice), 'strictascend')            isIncreasing = false;            return;        end    end    isIncreasing = true;endfunction resultAr = binData(data, bins)    resultAr = histcounts(data, bins);endfunction [x_data, y_data] = transformInputData(x_data, y_data)    if size(x_data, 1) == 1        x_data = x_data';    end    if size(y_data, 1) == 1        y_data = y_data';    endend function [x_vertices, y_vertices] = generatePolygonPoints(dataX, dataY, lower, upper, isSegmentOverBaseline, containsMappingToolbox)    if isSegmentOverBaseline        keep = dataY >= lower;    else        keep = dataY < upper;    end        xi = dataX(keep);    yi = dataY(keep);        yi(yi >= upper) = upper;    yi(yi < lower) = lower;    if containsMappingToolbox        [x_u, y_u] = polyxpoly(dataX, dataY, dataX, upper * ones(1, numel(dataX)));        [x_l, y_l] = polyxpoly(dataX, dataY, dataX, lower * ones(1, numel(dataX)));        xi = [xi, x_u', x_l'];        yi = [yi, y_u', y_l'];    end    [xi, idx] = sort(xi);    yi = yi(idx);    x_vertices = [xi fliplr(xi)];    if isSegmentOverBaseline        y_vertices = [yi ones(1, numel(xi)) * lower];    else        y_vertices = [yi ones(1, numel(xi)) * upper];    endendfunction yi = transformPolygon(yi, lower, upper, baseline)            if lower >= baseline        yi = yi - (lower - baseline);    else        yi = yi + (baseline - upper);        yi = baseline + abs(baseline - yi);    endend
function [ y_data, x_data, labels] = GenerateRandomData(n)    x_data = [2000:2021];    y_data_all = [[791, 829, 881, 950, 1010, 1080, 1190, 1260, 1300, 1420, 1530, 1620, 1700, 1820, 1940, 2110, 2280, 2430, 2600, 2680, 2520, 2740],                   [770, 830, 849, 931, 988, 1050, 1150, 1230, 1290, 1190, 1240, 1300, 1360, 1370, 1380, 1350, 1380, 1380, 1420, 1450, 1410, 1500],                  [3980, 4010, 3990, 4080, 4150, 4220, 4300, 4360, 4310, 4040, 4210, 4230, 4270, 4370, 4370, 4430, 4480, 4550, 4590, 4580, 4370, 4450],                  [2040, 2100, 2120, 2130, 2200, 2220, 2290, 2340, 2330, 2280, 2320, 2370, 2390, 2400, 2400, 2430, 2470, 2530, 2570, 2620, 2400, 259],                  [1830, 1890, 1880, 1880, 1920, 1940, 1950, 2000, 1970, 1880, 1890, 1920, 1860, 1820, 1810, 1850, 1870, 1900, 1900, 1920, 1750, 1850]];    labels_all = ["Apple(AAPL)", "Microsoft(MSFT)", "Amazon(AMZN)", "Google(GOOGL)", "Coca Cola(KO)"];        y_data = y_data_all(1:n, :)';    labels = labels_all(1:n);end
Horizon ChartData Intialization and PreprocessingFirst, we need to read the data and do some inital preprocessing to ensure that y is a 2d matrix and that x is either a 2d matrix with same dimensions as y or that x is 1d matrix with same number of rows as y. Labels is the individual title for each slice in the tiled layout. Note: All data is random and is for representation purposes only. The data is not indicative of real stock market data. Further, each column indicates the price of each stock for the years 2000 - 2021. n_stocks = 5;[y_data, x_data, labels] = GenerateRandomData(5);Let us create a basic horizon chartbasicHorizonChart = horizonChart(x_data, y_data);Let us add some labels to our chart. Here, each slice of the chart denotes the gdp of a country. So, we pass in country names as labels. basicHorizonChart = horizonChart(x_data, y_data, 6, 'Labels', labels);Color SchemeThe horizon chart's color scheme is split into two zones: above the baseline and below the baseline. The user is required to specify a color for each zone. The segments in the chart are colored with a darker shade of the specified color based on their distance from the baseline. To set colors for the segments above and below the baseline, we can..coloredHorizonChart = horizonChart(x_data, y_data, 6, 'Labels', labels, 'ColorAboveBaseline' , 'g' , 'ColorBelowBaseline' , 'm', 'Baseline', 1800);BaselineWe can also set the baseline according to our preferences. In this case, depending on distribution of data we accordingly rearrange the number of bands above the baseline/ below the baseline. baselineHorizonChart = horizonChart(x_data, y_data , 6, 'Labels', labels, 'Baseline', 2000);Labelling the chartTo decorate the chart, we can also add the X-Label, Y-Label and chart title. basicHorizonChart = horizonChart(x_data, y_data, 6, 'Labels', labels, 'XLabel', 'Time(in years)', 'YLabel', 'Stock Price(In USD)', 'Title', 'Stock Price over the years');

⛄ 运行结果

⛳️ 代码获取关注我

❤️部分理论引用网络文献,若有侵权联系博主删除
❤️ 关注我领取海量matlab电子书和数学建模资料

🍅 仿真咨询

1 各类智能优化算法改进及应用
生产调度、经济调度、装配线调度、充电优化、车间调度、发车优化、水库调度、三维装箱、物流选址、货位优化、公交排班优化、充电桩布局优化、车间布局优化、集装箱船配载优化、水泵组合优化、解医疗资源分配优化、设施布局优化、可视域基站和无人机选址优化
2 机器学习和深度学习方面
卷积神经网络(CNN)、LSTM、支持向量机(SVM)、最小二乘支持向量机(LSSVM)、极限学习机(ELM)、核极限学习机(KELM)、BP、RBF、宽度学习、DBN、RF、RBF、DELM、XGBOOST、TCN实现风电预测、光伏预测、电池寿命预测、辐射源识别、交通流预测、负荷预测、股价预测、PM2.5浓度预测、电池健康状态预测、水体光学参数反演、NLOS信号识别、地铁停车精准预测、变压器故障诊断
2.图像处理方面
图像识别、图像分割、图像检测、图像隐藏、图像配准、图像拼接、图像融合、图像增强、图像压缩感知
3 路径规划方面
旅行商问题(TSP)、车辆路径问题(VRP、MVRP、CVRP、VRPTW等)、无人机三维路径规划、无人机协同、无人机编队、机器人路径规划、栅格地图路径规划、多式联运运输问题、车辆协同无人机路径规划、天线线性阵列分布优化、车间布局优化
4 无人机应用方面
无人机路径规划、无人机控制、无人机编队、无人机协同、无人机任务分配
5 无线传感器定位及布局方面
传感器部署优化、通信协议优化、路由优化、目标定位优化、Dv-Hop定位优化、Leach协议优化、WSN覆盖优化、组播优化、RSSI定位优化
6 信号处理方面
信号识别、信号加密、信号去噪、信号增强、雷达信号处理、信号水印嵌入提取、肌电信号、脑电信号、信号配时优化
7 电力系统方面
微电网优化、无功优化、配电网重构、储能配置
8 元胞自动机方面
交通流 人群疏散 病毒扩散 晶体生长
9 雷达方面
卡尔曼滤波跟踪、航迹关联、航迹融合

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

matlab科研助手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值