2015-10-16 29 views
13

イメージであるため、私は大規模にプロットしたい中型の配列(1500x3000など)を持っています。しかし、垂直と水平のスケールは非常に異なります。簡略化のため、1メートル/行と10 /列があるとします。次に、プロットはcである画像を生成すべきである。 1500x30000。私はスケールのためにkwargエクステントを使用し、変形を避けるためにaspect = 1を使用します。 プロットウィンドウ(QT4)とimshow()を使用するか、またはsavefig()を使用して、スケールとフル解像度で画像を生成することができませんでした。それはバグだった場合にはherehere、またはherethereまたはthereに示すようにmatplotlib.pyplot、imshow()、savefig()でフル解像度でプロットする?

私は多く提案されたソリューションを見てきました。私は私のmatplotlibrcを変更し、〜/ .config/matplotlibに置いて、自分のdisplay/savefigオプションを強制しようとしましたが、役に立たないようにしました。私もpcolormesh()を試しましたが、成功しませんでした。私は、バックエンドとしてUbuntu 14.04とQT4AggのリポジトリからPython 2.7とmatplotlib 1.3を使用しています。私もTkAggを試しましたが、遅くて同じ結果が得られます。私は、x軸では解像度は正しいが、垂直方向に確実にダウンサンプリングされているという印象を持っている。ここに私の問題をシミュレートするコードがあります。 imshowを()で

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.colors 

R, C = 1500, 3000 
DATA = np.random.random((R, C)) 
DATA[::2, :] *= -1 # make every other line negative 
Yi, Xi = 1, 10 # increment 
CMP = 'seismic' 
ImageFormat ='pdf' 
Name = 'Image' 


DataRange = (np.absolute(DATA)).max() # I want my data centred on 0 
EXTENT = [0, Xi*C, 0 ,Yi*R] 
NORM = matplotlib.colors.Normalize(vmin =-DataRange, vmax= DataRange, clip =True) 

for i in range(1,4): 
    Fig=plt.figure(figsize=(45, 10), dpi = 100*i, tight_layout=True) 
    Fig.suptitle(Name+str(i)+'00DPI') 
    ax = Fig.add_subplot(1, 1, 1) 
    Plot = ax.imshow(DATA, cmap=plt.get_cmap(CMP), norm = NORM, extent = EXTENT, aspect = 1, interpolation='none') 
    ax.set_xlabel('metres') 
    ax.set_ylabel('metres') 
    Fig.savefig(Name+str(i)+'00DPI.'+ImageFormat, format = ImageFormat, dpi = Fig.dpi) 
plt.close() 

、補間=「なし」または「最寄り」または私はショーを行う場合、私はそれは少なくともQt4をウィンドウになっていると思いますが、「バイリニア」何らかの理由で解像度を変更しません。 ()をsavefig()の代わりに使用します。 plt.figure(dpi =)で設定した値が保存された数値と同じ解像度であることに注意してください。

私はこのシステムでどのように動作するのか、私の理解の限界から考えています。どんな助けも大歓迎です。

ありがとうございます。

+1

オプションをSVGとして保存していますか? 'plt.savefig(" test.svg ")' – Eric

+0

私は垂直解像度に関してsvgとしての改善を見逃していません。 – Boorhin

+0

イメージが正と負の値を垂直に交互に表示するようにコードを修正しました。主なアイデアは、イメージが完全に解決された場合、青と赤の水平ストライプを区別できることです。 – Boorhin

答えて

1

例を実行すると、ズーム後にすべてが良好に見えます。解像度に関係なく、結果は同じで、1軸単位で1ピクセルが表示されます。 また、より小さな配列を試してみると、pdfs(または他の形式)がうまくいきます。

これは私の説明です:figure dpiを設定すると、図全体のdpi(データ領域だけでなく)を設定しています。私のシステムでは、プロット領域が全体の約20%を占めています。 300 dpiと10の高さを設定すると、縦軸のデータ軸は合計300x10x0.2 = 600ピクセルになりますが、これは1500ポイントを表現するには不十分です。なぜ出力を再サンプリングする必要があるのか​​がわかります。データプロットが占める図の割合を変更するため、幅を縮小することがうまく機能することがあります。

次に、dpiを増やして、補間= 'なし'を設定する必要があります(解像度が完全に設定されているかどうかは関係ありませんが、十分に近い場合は重要です)。 図の大部分を占めるようにプロットの位置とサイズを調整することもできますが、最適な解像度設定に戻って、理想的には、軸上に複数のデータポイントがあるピクセル数補間のいくつかの種類が発生する必要があります(どのように3ピクセル上の2つの点をプロットすることができますか、またはviceversa)。次はそれを行うための最善の方法である場合、私は知らない

、そこmatplotlibの中に、より適切なメソッドとプロパティかもしれませんが、私は、最適な解像度を計算するために、このような何かをしようとするだろう:

vsize=ax.get_position().size[1] #fraction of figure occupied by axes 
axesdpi= int((Fig.get_size_inches()[1]*vsize)/R) #(or Yi*R according to what you want to do) 

は、次に(最初のループに減少)あなたのコードは、次のようになります。

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.colors 

R, C = 1500, 3000 
DATA = np.random.random((R, C)) 
DATA[::2, :] *= -1 # make every other line negative 
Yi, Xi = 1, 10 # increment 
CMP = 'seismic' 
ImageFormat ='pdf' 
Name = 'Image' 


DataRange = (np.absolute(DATA)).max() # I want my data centred on 0 
EXTENT = [0, Xi*C, 0 ,Yi*R] 
NORM = matplotlib.colors.Normalize(vmin =-DataRange, vmax= DataRange, clip =True) 

for i in (1,): 
    print i 
    Fig=plt.figure(figsize=(45, 10), dpi = 100*i, tight_layout=True) 
    Fig.suptitle(Name+str(i)+'00DPI') 
    ax = Fig.add_subplot(1, 1, 1) 
    Plot = ax.imshow(DATA, cmap=plt.get_cmap(CMP), norm = NORM, extent = EXTENT, aspect = 1, interpolation='none') 
    ax.set_xlabel('metres') 
    ax.set_ylabel('metres') 
    vsize=ax.get_position().size[1] #fraction of figure occupied by axes 
    axesdpi= int((Fig.get_size_inches()[1]*vsize)/R) #(or Yi*R according to what you want to do) 
    Fig.savefig(Name+str(axesdpi)+'DPI.'+ImageFormat, format = ImageFormat, dpi = axesdpi) 
    #plt.close() 

は、これは私のために合理的に動作します。

1

最初に、.pdfとして保存している場合、オプションで他のバックエンドを指定している場合でも、暗黙的にpdfバックエンドを使用しています。これはあなたのイメージがベクトル形式で保存されていることを意味し、したがってdpiはかなり無意味です。どの解像度でも、私はまともなビューアでPDFを読み込むと(私はinkscapeを使用し、他のものは利用可能です)、ストライプをはっきりと見ることができます - 2行おきに0を設定すると、生成されたすべてのPDFには、ストライプを再現するための完全な情報が含まれているため、実質的に同一です。 figsize=(45, 10)と指定すると、生成されたすべてのPDFは、表示サイズを45インチx 10インチにすることを推奨しています。

イメージタイプをpngと指定した場合は、dpiパラメータに基づいてファイルサイズが異なることがわかります。これはあなたが期待していると思います。 100 dpiの画像を見ると4500000、200 dpiの画像は18000000ピクセル(4倍)、300 dpiの画像は40500000(9倍)です。 4500000 == 1500 x 3000、つまり元の配列のメンバーあたり1ピクセルです。大きなdpi設定では実際にはそれ以上の定義が得られません。代わりに1の代わりにそれぞれ2または3ピクセル幅のストライプが使用されます。

I あなたがしたいことは効果的ですすべての列を10回プロットすると、1500 x 30000ピクセルの画像が得られます。すべて独自のコードを使用して、これを行うには、次のような何かをするnp.repeatを使用することができます。

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.colors 

R, C = 1500, 3000 
DATA = np.random.random((R, C)) 
DATA[::2, :] = 0 # make every other line plain white 
Yi, Xi = 1, 10 # increment 
DATA = np.repeat(DATA, Xi, axis=1) 
DATA = np.repeat(DATA, Yi) 

CMP = 'seismic' 
ImageFormat ='pdf' 
Name = 'Image' 


DataRange = (np.absolute(DATA)).max() # I want my data centred on 0 
EXTENT = [0, Xi*C, 0 ,Yi*R] 
NORM = matplotlib.colors.Normalize(vmin =-DataRange, vmax= DataRange, clip =True) 

for i in range(1,4): 
    Fig=plt.figure(figsize=(45, 10), dpi = 100*i, tight_layout=True) 
    Fig.suptitle(Name+str(i)+'00DPI') 
    ax = Fig.add_subplot(1, 1, 1) 
    Plot = ax.imshow(DATA, cmap=plt.get_cmap(CMP), norm = NORM, extent = EXTENT, aspect = 1, interpolation='none') 
    ax.set_xlabel('metres') 
    ax.set_ylabel('metres') 
    Fig.savefig(Name+str(i)+'00DPI.'+ImageFormat, format = ImageFormat, dpi = Fig.dpi) 
plt.close() 

警告:このメモリ集約ソリューションを - そこより良い方法があるかもしれません。あなたがpdfのベクトルグラフィックス出力を必要としない場合、あなたはpng


にごImageFormat変数を変更することができますそれはあなたが心配されるかもしれない他の事は(絵に適切なアスペクト比を与えることであることを私を打ちますすなわち、それが高さの20倍の幅)。これはあなたがすでにやっていることです。したがって、pdfのピクセルの各表示を見ると、正方形ではなく長方形(背の高さの10倍の幅)です。

+0

明確にするために、増分はメートル単位の縮尺です。データは、メートルごとに垂直方向に10メートルごとにサンプリングされます。だから私は本当に値を繰り返すことを望んでいない、私は補間(中央値のフィルタのような)を好む。しかし、現時点での私のコードはそのために設計されていないことを理解しています(私は単純化のためにその部分を削除しました)。説明をありがとう、私はnp.repeat関数を知らなかった。私はラスター形式も使用しますが、より意味があります。 PDFのフォント/軸のレンダリングが好きなので、出版用にInkscapeで編集することができます。 – Boorhin

関連する問題