How to display images with log axes?

29 views (last 30 days)
Henrik Mannerström
Henrik Mannerström on 20 Jan 2011
I want to plot an image with logarithmic scaling, but MATLAB seems to fail.
This works fine:
load mandrill
axes('XScale', 'log');
image('CData', X, 'XData', [0.1 10]);
But this produces a warning and an empty plot:
axes('XScale', 'log');
image('CData', X, 'XData', [0.1 100]);
The warning is:
'Warning: Negative data ignored '
Images that have a range close to 1000 fold makes the plotting command behave strangely:
a = axes('XScale', 'log');
image('CData', X, 'XData', [1 990]);
set(a, 'XLim', [0.009 1000]);
More precisely, when I run the following code in Matlab, it does what I expect it to do: It displays the Mandrill (although upside down and in wrong colors, but that is not the point). I asked Matlab to scale the x-axis logarithmically and I asked it to display the Mandrill so that the center of the leftmost pixel is over coordinate 0.1 and the center of the rightmost pixel is over coordinate 10. This is also the result I get.
load mandrill
axes('XScale', 'log');
image('CData', X, 'XData', [0.1 10]);
On the other hand, when I run the following piece of code, the results are not what I expect. Building on the experience of the previous code, I would expect to see the same mandrill, this time with the scale on the x-axis ranging to 100. This is not what I get on my computer. Instead, I get an empty plot and this warning:
"Warning: Negative data ignored".
Now why is this? Where did the mandrill go? Why does changing the second component of the input to XData from 10 to 100 scare the primate away?
axes('XScale', 'log');
image('CData', X, 'XData', [0.1 100]);
The third code snippet is to show how things gradually fail. First, I create an axes where the scaling of the x axis ranges from 1e-2 to 1e3. This works fine (with or without the XLimMode set to manual). Then I try to frame the mandrill on the plot, so that it does not occupy the whole area but rather is squeezed in between values 1e0 to 1e2. On my computer the mandrill now cooperates and happily fills the space it was allotted.
axes('XScale', 'log', 'XLim', [0.01 1000], 'XLimMode', 'manual');
image('CData', X, 'XData', [1 100]);
One little mistake from my side, however, will again make the mandrill misbehave. Suppose I want to give it some more space, extending it to the right. I think this could be done by changing the second component of XData from 100 to, say, 950. Try the the following:
axes('XScale', 'log', 'XLim', [0.01 1000], 'XLimMode', 'manual');
image('CData', X, 'XData', [1 950]);
Not so! The mandrill now extends farther to the right, as I wanted, but also extends farther to the left, as I did not want. Try to give the mandrill some breathing room and it takes over the whole plot! Also, as I would not expect (and therefore call it strange behavior), the data cursor has no connection to the data displayed (try this!).
I therefore have two problems at hand: How to position the image correctly on the logarithmic plot, and How to get the data cursor to display information about the pixel it seemingly is centered above? Both these problems can be solved with creative programming but I have higher expectations on my Mandrill. The version is this:
MATLAB Version (R2010a)
MATLAB License Number: xxxxxx
Operating System: Microsoft Windows XP Version 5.1 (Build 2600: Service Pack 3)
Java VM Version: Java 1.6.0_12-b04 with Sun Microsystems Inc. Java HotSpot(TM) Client VM mixed mode
Doug Hull
Doug Hull on 20 Jan 2011
What is the result you want? I have found various things that do what I think you want, but I would rather be clear of your goals.

Sign in to comment.

Answers (2)

Walter Roberson
Walter Roberson on 20 Jan 2011
The warnings about negative data go away if you set XLimMode to 'manual'
The odd graphics you see have to do with the positioning method for images. Recall that for images, the XData gives the position of the center of the pixel, but that pixels are fixed size. When the fixed half pixel outside margin is translated to coordinates in log space, the result can be outside of the current XLim. When that happens, the image is largely clipped out. If you set the XLim manually and then adjust the XData to be close to but not quite at the XLim, the image will occupy most of the plot space, disappearing if the margin would project over the XLim.

Cris Luengo
Cris Luengo on 21 Jan 2011
This is quite interesting, as it shows how MATLAB operates internally.
When you do
image('CData', X, 'XData', [0.1 100]);
the image is positioned so that the center of the first pixel is on 0.1, and the center of the last one at 100. That makes each pixel approx. 0.2 wide. However, this is now internally translated to the image patches laying between -0.1 and 100.2. This is apparently calculated in the same way, no matter what mode (lin/log) the axis is in.
When you set the 'XData' to [1 100], in your example above, there are 11 pixels to the left of 1 in log mode. In lin mode you can see the leftmost pixel centered around 1, stretching between 0.9 and 1.1.
This is very weird behaviour, but then gain, probably nobody before has thought of displaying an image in log mode... :)
Cheers, Cris.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!