如何将2D数组绘制为具有Matplotlib的图像,其y比例相对于y值的两个幂?
例如,我的数组的第一行在图像中的高度为1,第二行的高度为4,等等(单位无关紧要) 用文字解释并不简单,所以请看这个图像(这就是我想要的结果):
alt text http://support.sas.com/rnd/app/da/new/802ce/iml/chap1/images/wavex1k.gif
如您所见,第一行比上一行小2倍,依此类推。
对于那些对我为什么要这样做感兴趣的人:
我有一个非常大的浮点阵列(10,700000),表示声音文件的离散小波变换系数。我试图用这些系数绘制尺度图。 我可以复制数组x次,直到我得到所需的图像行大小,但内存不能容纳如此多的信息...
答案 0 :(得分:8)
您是否尝试过转换轴?例如:
ax = subplot(111)
ax.yaxis.set_ticks([0, 2, 4, 8])
imshow(data)
这意味着不存在坐标的数据必须存在间隙,除非有办法提供转换函数而不仅仅是列表(从未尝试过)。
修改强>:
我承认这只是一个领导,而不是一个完整的解决方案。这是我在更多细节中的意思。
假设您将数据放在数组a
中。你可以使用像这样的变换:
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)
基本上它会使用mylog2
函数转换数组或列表的第一个坐标(您可以根据需要进行转换 - 它是自制的,作为log2的简化)。优点是,您可以根据需要重新使用它进行另一次转换,并且您也可以轻松控制它。
然后将您的数组映射到此数组,该数组不会复制,而是实例中的本地引用:
b = arr(a)
现在您可以显示它,例如:
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")
这是一个示例(包含随机值的数组):
alt text http://img691.imageshack.us/img691/8883/clipboard01f.png
答案 1 :(得分:3)
您可以查看matplotlib.image.NonUniformImage。但这只会助长轴的非均匀性 - 我不认为你能够像你想的那样自适应地绘图(我认为图像中的每个点总是会有相同的区域 - 所以你要去必须多次拥有更宽的行)。你有什么理由需要绘制完整的阵列吗?显然,完整的细节不会出现在任何情节中 - 因此我建议对原始矩阵进行大量下采样,以便您可以根据需要复制行以获得图像,而不会耗尽内存。
答案 2 :(得分:3)
我发现使用matplotlib制作尺度图的最佳方法是使用imshow
,类似于specgram
的实现。使用矩形很慢,因为您必须为每个值创建单独的字形。同样地,你不想把东西都烧成一个统一的NumPy数组,因为你可能会快速耗尽内存,因为你的最高级别大约是信号的一半。
以下是使用SciPy和PyWavelets的示例:
from pylab import *
import pywt
import scipy.io.wavfile as wavfile
# Find the highest power of two less than or equal to the input.
def lepow2(x):
return 2 ** floor(log2(x))
# Make a scalogram given an MRA tree.
def scalogram(data):
bottom = 0
vmin = min(map(lambda x: min(abs(x)), data))
vmax = max(map(lambda x: max(abs(x)), data))
gca().set_autoscale_on(False)
for row in range(0, len(data)):
scale = 2.0 ** (row - len(data))
imshow(
array([abs(data[row])]),
interpolation = 'nearest',
vmin = vmin,
vmax = vmax,
extent = [0, 1, bottom, bottom + scale])
bottom += scale
# Load the signal, take the first channel, limit length to a power of 2 for simplicity.
rate, signal = wavfile.read('kitten.wav')
signal = signal[0:lepow2(len(signal)),0]
tree = pywt.wavedec(signal, 'db5')
# Plotting.
gray()
scalogram(tree)
show()
您可能还希望按级别自适应地缩放值。
这对我来说效果很好。我唯一的问题是matplotlib在关卡之间创建了一个细线。我还在寻找解决这个问题的方法。
P.S。 - 虽然这个问题现在很老了,但我想我会在这里做出回应,因为当我在寻找使用MPL创建尺度图的方法时,这个页面出现在Google上。
答案 3 :(得分:2)
如果您希望两者都能够缩放和节省内存,则可以“手动”进行绘图。 Matplotlib允许您绘制矩形(它们将是您的“矩形像素”):
from matplotlib import patches
axes = subplot(111)
axes.add_patch(patches.Rectangle((0.2, 0.2), 0.5, 0.5))
请注意,轴的范围不是由add_patch()设置的,但您可以将它们自己设置为您想要的值(axes.set_xlim,...)。
PS:我认为thrope的响应(matplotlib.image.NonUniformImage)实际上可以做你想要的,用这里描述的“手动”方法更简单!