[Из песочницы] Дескрипторная графика в MATLAB: вторая горизонтальная ось

При изучении дескрипторной графики в MATLAB обнаружилась нехватка «юзер френдли» функционала, а именно отсутствие стандартной команды позволяющей добавить дополнительную горизонтальную ось.

Добавление дополнительной вертикальной оси, командой plotyy предусмотрено и в help к ней, в разделе topics, есть пример добавления дополнительной оси x, однако данный пример, как и сама команда, не без недостатков, что любезно сообщает нам сам разработчик фразой:

plotyy is not recommended


Разбор недостатков самой команды пожалуй опустим, а вот о недостатках указанного разработчиками примера стоит упомянуть:

  • Во-первых, нам предлагают расположить дополнительную ось в самой что ни на есть моветоновой области — в верху графика. Глаза разбегаются при попытке анализа такой картины…
  • Во-вторых, как подписывать такую ось даже продвинутому пользователю matlab может быть не ясно;
  • В-третьих, зачем нам ещё одна ось y?


Код из help
figure
x1 = 0:0.1:40;
y1 = 4.*cos(x1)./(x1+2);
line(x1,y1,'Color','r')
title('Не читаемо') % Сам вставил
ax1 = gca; % current axes
ax1.XColor = 'r';
ax1.YColor = 'r';
ax1_pos = ax1.Position; % position of first axes
ax2 = axes('Position',ax1_pos,...
    'XAxisLocation','top',...
    'YAxisLocation','right',...
    'Color','none');
x2 = 1:0.2:20;
y2 = x2.^2./x2.^3;
line(x2,y2,'Parent',ax2,'Color','k')
xlabel('f,Гц') % Сам вставил


Визуализированно распекаю пример из help
image


Для решения выше указанных проблем напишем свой код:

Решение проблем
clc
clear all
close all
%% Мои данные, возьми свои
U=[5.5 5.5 5.5 5.2 5.1 5 5 4.8 4.8]; % Значения амплитуды
F=[30 40 50 10000 12000 14000 16000 18000 20000]; % Значения частоты
[xi,ni]=find(F==50);
K=U/U(ni); % Расчёт относительных значений АЧХ
%%
figure
%% Это устанавливает шрифт и размер, речь не об этом
set(0,'DefaultAxesFontSize',20,'DefaultAxesFontName','Times New Roman');
set(0,'DefaultTextFontSize',20,'DefaultTextFontName','Times New Roman');
%% То, о чём шла речь
ax=get(axes,'Position'); % Получаю стандартное расположение осей в виде числового массива
a=gca; % Получаю свойства стандартных осей
set(a,'Position',[ax(1) ax(2)+(ax(2)/2) ax(3) ax(4)-ax(4)/10]) % Сдвигаю стандартные оси
plot(a,log(F),K,'-o'); % Строю свой график
xlim(a,[min(log(F)) max(log(F))]) % Задаю пределы своих осей
grid on % Сетка
BX=get(gca,'XTick'); % Получаю стандартную градуировку оси x в виде числового массива
BY=get(gca,'YTick'); % Получаю стандартную градуировку оси y в виде числового массива
%% Подписываю первые оси используя сдвиг
xlabel('бел','Position',[BX(size(BX,2))+1.1 BY(1)+(BY(1)/100)]) 
ylabel('K(f)')
%% Строю и подписываю дополнительную горизонтальную ось
F1=num2str(F,'%0.0i\n'); % Перевожу отсчёты предназначенные для дополнительной оси в строковый формат
ax2=[ax(1) ax(2)-(ax(2)/4) ax(3) 0]; % Задаю сдвиг относительно первых осей
b=axes('Position',ax2); % Ввожу сдвиг
xlabel('f, Гц', 'Position',[BX(size(BX,2))+1.1 BY(1)+(BY(1)/100)]) % Подписываю вторую ось
xlim(b,[min(log(F)) max(log(F))]) % Задаю пределы дополнительной оси, учитывая сдвиг
xticks(b,log(F)) % Градуирую дополнительную ось
xticklabels(b,F1) % Подписываю дополнительную ось
xtickangle(90) % Поворачиваю подпись дополнительной оси, для удобства восприятия


Давайте подробней рассмотрим некоторые элементы кода:

С помощью ниже указанной команды получаем положение осей в виде числового массива.

ax=get(axes,'Position');


Массив ax представлен в виде [a b c d], где a и b — положение левого нижнего угла графика, по горизонтали и по вертикали соответственно. Т. е. координаты начала отсчёта; с — длина горизонтальной оси, d — длина вертикальной оси.

Вводя смещения ни какое золотое сечение не вычислялось, всё «на глаз»:

set(a,'Position',[ax(1) ax(2)+(ax(2)/2) ax(3) ax(4)-ax(4)/10]) 


Так, ax (2)+(ax (2)/2) — смещает начало стандартной оси по вертикали в половину текущего, т. е. вверх от первоначального положения, что необходимо для удобочитаемости нумерованных отметок шкалы. Смещение ax (4)-ax (4)/10 задаёт размер первых осей по вертикали, т.е. уменьшает на десятую часть от текущего значения, нужно для удобочитаемости подписи графика, напомню title. Если задать d=0, то вертикальной оси попросту будет не будет видно, чем и воспользуемся в случае:

ax2=[ax(1) ax(2)-(ax(2)/4) ax(3) 0]; 


Следующий код позволяет задать положение подписей горизонтальных осей:

BX=get(gca,'XTick'); 
BY=get(gca,'YTick'); 
xlabel('бел','Position',[BX(size(BX,2))+1.1 BY(1)+(BY(1)/100)]) 
xlabel('f, Гц', 'Position',[BX(size(BX,2))+1.1 BY(1)+(BY(1)/100)]) 


Массив BX, равно как и BY, представлен как [x y], где x — положение подписи по горизонтали, y — положение подписи по вертикали.

В результате мы можем лицезреть вот такую красоту
image


Ниже оставлю пару полезных ссылок.

описание команды axes;
настройки команды axes;
команда plotyy;
метод введения дополнительной горизонтальной оси от разработчиков.

© Habrahabr.ru