ось равна на графике логлога Matlab

В Matlab команда «ось равна»:

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

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

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

приводит к

альтернативный текст

скорее, чем

альтернативный текст

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

Мой вопрос:

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


person Yossi Farjoun    schedule 09.11.2010    source источник


Ответы (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

И вот получившийся сюжет:

альтернативный текст

Обратите внимание, что расстояние между делениями 100 и 102 по оси Y составляет такое же количество пикселей, как и расстояние между делениями 1010. > и 1012 делений по оси 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 на основе кода в этом ответе. . На данный момент вот урезанная версия (т.е. без проверки ошибок или справки), которую вы можете использовать:

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]);

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

person gnovice    schedule 09.11.2010
comment
Хороший. Это похоже на решение, которое я нашел, хотя я надеялся на что-то более автоматическое (например, без ручной настройки осей), поэтому я взял ограничения из оси(). Однако проблема в том, что когда вы меняете соотношение сторон, пределы могут измениться (если, как вы это сделали, вы не установили их вручную)... - person Yossi Farjoun; 10.11.2010
comment
Сравнивая ваш пример с тем, что сделал я более внимательно, понимаю, что решения совсем не те. Я на самом деле не понимаю, что вы сделали... в частности, я не понимаю, зачем вам нужно logScale (но это явно работает!!) - person Yossi Farjoun; 10.11.2010
comment
@Yossi: Комментарии недостаточно велики, чтобы я мог все объяснить, поэтому я вскоре обновлю свой ответ, объясняя, как все это работает. - person gnovice; 10.11.2010