Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
531 views
in Technique[技术] by (71.8m points)

python - How to plot an image with non-linear y-axis with Matplotlib using imshow?

How can I plot an 2D array as an image with Matplotlib having the y scale relative to the power of two of the y value?

For instance the first row of my array will have a height in the image of 1, the second row will have a height of 4, etc. (units are irrelevant) It's not simple to explain with words so look at this image please (that's the kind of result I want):

alt text http://support.sas.com/rnd/app/da/new/802ce/iml/chap1/images/wavex1k.gif

As you can see the first row is 2 times smaller that the upper one, and so on.

For those interested in why I am trying to do this:

I have a pretty big array (10, 700000) of floats, representing the discrete wavelet transform coefficients of a sound file. I am trying to plot the scalogram using those coefficients. I could copy the array x times until I get the desired image row size but the memory cannot hold so much information...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Have you tried to transform the axis? For example:

ax = subplot(111)
ax.yaxis.set_ticks([0, 2, 4, 8])
imshow(data)

This means there must be gaps in the data for the non-existent coordinates, unless there is a way to provide a transform function instead of just lists (never tried).

Edit:

I admit it was just a lead, not a complete solution. Here is what I meant in more details.

Let's assume you have your data in an array, a. You can use a transform like this one:

class arr(object):
    @staticmethod
    def mylog2(x):
        lx = 0
        while x > 1:
            x >>= 1
            lx += 1
        return lx
    def __init__(self, array):
        self.array = array
    def __getitem__(self, index):
        return self.array[arr.mylog2(index+1)]
    def __len__(self):
        return 1 << len(self.array)

Basically it will transform the first coordinate of an array or list with the mylog2 function (that you can transform as you wish - it's home-made as a simplification of log2). The advantage is, you can re-use that for another transform should you need it, and you can easily control it too.

Then map your array to this one, which doesn't make a copy but a local reference in the instance:

b = arr(a)

Now you can display it, for example:

ax = subplot(111)
ax.yaxis.set_ticks([16, 8, 4, 2, 1, 0])
axis([-0.5, 4.5, 31.5, 0.5])
imshow(b, interpolation="nearest")

Here is a sample (with an array containing random values):

alt text http://img691.imageshack.us/img691/8883/clipboard01f.png


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...