2009-11-05 12 views
8

Matplotlibのy値が2の累乗に比例する画像として2D配列をプロットするにはどうすればよいですか?imshowを使ってMatplotlibで非線形y軸の画像をプロットする方法は?

例えば、私の配列の最初の行は1の画像に高さを持ち、2番目の行は4などの高さを持ちます。(単位は無関係です) 言葉で説明するのは簡単ではありませんこのイメージしてください(つまり、結果のようなものだ、私が欲しい):

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

あなたが最初の行はように2上位1倍より小さく、かつある見ることができるように。私はこれを行うにしようとしていますなぜに興味のある人のための

私は離散ウェーブレットサウンドファイルの変換係数を表すfloatの非常に大きな配列を(10、700000)、持っています。これらの係数を使ってスカログラムをプロットしようとしています。 私は希望の画像の行サイズを取得するまでx回配列をコピーすることができますが、メモリは多くの情報を保持することはできません...

答えて

8

軸を変換しようとしましたか?たとえば:だけではなく、リスト(試したことがない)の変換機能を提供する方法がない限り、

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

これは、存在しない座標のデータにギャップが存在しなければならないことを意味します。

編集

私はそれだけで、鉛、ない完全なソリューションでした認めます。ここで私がもっと詳しく述べたことがあります。

あなたのデータが配列aであるとします。それは自家製ですLOG2の簡素化など - 基本的に、それは最初のあなたが望むようにあなたが変換できること(mylog2機能を配列またはリストの座標変換されます

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) 

:あなたはこの1のような変換を使用することができます)。利点は、必要に応じて別のトランスフォームで再利用することができ、簡単に制御できることです。例えば、

b = arr(a) 

は今、あなたはそれを表示することができます:

は、次にコピーが、インスタンス内のローカル参照を作成していない、この1のために、配列をマッピング

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

+0

-1:y軸に表示されるティックを選択しても元の質問は解決されません。 set_ticks()を使用すると、y軸は線形のままであり、imshow()は配列を直線的に描画します。元のポスターは「可変サイズの長方形のピクセル」を望んでいます。 – EOL

+0

だから私は、データを適応させなければならないと言いました。 – RedGlyph

+0

@ EOL:...そして今正しいプロットもあります。私はあなたが何を意味したのか理解していますが、時には一緒に作品をまとめることが助けになります;-) – RedGlyph

3

matplotlib.image.NonUniformImageから見ることができます。しかし、それは軸が不均一であることを助けるだけです - 私はあなたが望むように適応的にプロットすることができないだろうと考えています(イメージの各ポイントは常に同じエリアを持つと思います。より広い行を複数回持たなければならない)。あなたは完全な配列をプロットする必要がある何らかの理由はありますか?明らかに、詳細はすべてのプロットに表示されません - 元の行列を大幅にダウンサンプリングして、必要に応じて行をコピーしてメモリを使い果たすことなくイメージを取得できるようにすることをお勧めします。

+0

はい私はdownsamplingに苦しんでいますが、時には最後のディテール係数をかなり深くズームしなければならず、精度の低下はしばしば高すぎます。 とにかくNonUniformImageを見ていきますが、私はそれを知らなかったので感謝しています。 – attwad

+0

私はこれが元のポスターが望むイメージを描くためには効果があり、これは行の複製を通して "ピクセル"を複製するより効率的だと思います。しかし、対応する軸の目盛りを取得することは未だに未解決の問題です。 – EOL

2

を両方ともズームできるようにしたい場合は、 "手作業で"図面を作成することができます。 matplotlibのは、あなたが(彼らはあなたの「長方形ピクセル」になります)四角形を描画することができます:軸のエクステントがadd_patch()によって設定されていないことを

from matplotlib import patches 
axes = subplot(111) 
axes.add_patch(patches.Rectangle((0.2, 0.2), 0.5, 0.5)) 

ますが、あなたが望む値にそれらを自分で設定することができます(axes.set_xlim、...)。

PS:thropeの応答(matplotlib.image.NonUniformImage)が実際にあなたが望むことを、より簡単な方法で、ここで説明した方法で行うことができますように私に見えます!

+0

+1効率的な代替案の場合、もう少し作業してもレンダリングがスピードアップします(他の解決策で説明したように)。 – RedGlyph

+0

@RedGlyphありがとう!私はthropeの解決策がこれのような矩形を引くのではないかと推測しますが、これはMatplotlibを直接経由します。 – EOL

3

matplotlibを使用してスカログラムを作成する最良の方法は、specgramの実装と同様にimshowを使用することです。矩形を使用するのは遅くなります。なぜなら、各値に対して別々のグリフを作成する必要があるからです。同様に、均一な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に公開されたので、私はここで回答すると思いました。

関連する問題