Ось, равная в логарифмическом графике Matlab

В Matlab команда 'axis equal':

устанавливает соотношение сторон так, чтобы равная отметка    приращения по оси x, y и z равны по размеру. Эта    делает СФЕРУ (25) похожим на сферу, вместо эллипсоида

Однако при использовании функции построения loglog это не работает "правильно". Мне бы хотелось, чтобы я получил соотношение сторон, так что данный фактор занимает одно и то же визуальное расстояние. Что на самом деле происходит, так это то, что

>> loglog(2.^[1:20]*1e10,(2.^[1:20]).^2)
>> axis equal

приводит к

alt text

а не

alt text

Чтобы можно было легко заметить наклон 2 (из квадрата) и не было бы лишнего лишнего пробела.

Мой вопрос:

Есть ли команда Matlab, которая делает это для меня? Или кто-нибудь решил эту проблему раньше?

Ответы

Ответ 1

Одним из решений является изменение ограничений осей и 'DataAspectRatio' самостоятельно, так что десятилетие на одной оси равно десятилетию - с другой. Вот как вы можете это сделать для своего примера:

loglog(2.^[1:20]*1e10,(2.^[1:20]).^2);   %# Plot your sample data
xLimits = [1e10 1e16];                   %# Limits for the x axis
yLimits = [1 1e12];                      %# Limits for the y axis
logScale = diff(yLimits)/diff(xLimits);  %# Scale between the x and y ranges
powerScale = diff(log10(yLimits))/...    %# Scale between the x and y powers
             diff(log10(xLimits));
set(gca,'Xlim',xLimits,'YLim',yLimits,...              %# Set the limits and the
        'DataAspectRatio',[1 logScale/powerScale 1]);  %#   data aspect ratio
set(gca,'XTick',[1e10 1e12 1e14 1e16]);  %# Change the x axis tick marks

И вот результат:

alt text

Обратите внимание, что пробел между отметками 10 0 и 10 2 по оси y охватывает такое же количество пикселей, что и пространство между 10 10 и 10 12 галочки на оси x, что делает десятилетие на одной оси равным десятилетию на другом.

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

xLimits = get(hAxes,'XLim');
yLimits = get(hAxes,'YLim');

Однако, чтобы отключить поведение изменения размеров автоматических осей MATLAB, вам все равно придется либо установить пределы осей на те же самые значения , либо установить свойства предельного режима до 'manual' при обновлении свойства 'DataAspectRatio':

set(gca,'Xlim',xLimits,'YLim',yLimits,...
        'DataAspectRatio',[1 logScale/powerScale 1]);
%# OR...
set(gca,'XLimMode','manual','YLimMode','manual',...
        'DataAspectRatio',[1 logScale/powerScale 1]);

Если все это похоже на большую работу, вы можете упростить все, включив все это в функцию. Я фактически буду отправлять функцию decades_equal в MathWorks File Exchange на основе кода в этом ответе. На данный момент это сокращенная версия (т.е. Проверка ошибок или помощь), которые вы можете использовать:

function decades_equal(hAxes,xLimits,yLimits)

  if (nargin < 2) || isempty(xLimits)
    xLimits = get(hAxes,'XLim');
  end
  if (nargin < 3) || isempty(yLimits)
    yLimits = get(hAxes,'YLim');
  end

  logScale = diff(yLimits)/diff(xLimits);
  powerScale = diff(log10(yLimits))/diff(log10(xLimits));

  set(hAxes,'Xlim',xLimits,...
            'YLim',yLimits,...
            'DataAspectRatio',[1 logScale/powerScale 1]);

end

И вы можете вызвать функцию следующим образом:

loglog(2.^[1:20]*1e10,(2.^[1:20]).^2);   %# Plot your sample data
decades_equal(gca);                      %# Make the decades equal sizes


Как это работает...

Вам может быть интересно, что за логикой стоит, как я выбрал масштабные факторы выше. При попытке сделать отображаемый размер десятилетия равным для каждой оси, мы должны учитывать как количество, так и размеры десятилетий в пределах осей. В приведенном выше коде я в основном вычисляю средний размер десятилетия для каждой оси, а затем используя отношения средних десятилетних размеров для масштабирования осей соответственно. Например, diff(yLimits) дает общий размер оси y, а diff(log10(yLimits)) дает количество десятилетий (т.е. Степень десяти), отображаемых на оси y.

Это может быть проще увидеть, если я изменил порядок операций в приведенном выше коде следующим образом:

yDecade = diff(yLimits)/diff(log10(yLimits));  %# Average y decade size
xDecade = diff(xLimits)/diff(log10(xLimits));  %# Average x decade size
set(gca,'XLim',xLimits,'YLim',yLimits,...
        'DataAspectRatio',[1 yDecade/xDecade 1]);

И это даст те же результаты масштабирования, что и раньше.