2013-04-02 154 views
4

我想讀取包含線段的XY端點和與線段關聯的值的文件,然後繪製由給定值着色的線段。我遇到的問題是可能會有幾十萬到幾百萬的線段,當我試圖讀取這些較大的文件時,我遇到了內存錯誤。有沒有更高效的內存管理方式?Python - 繪製大量線條

import matplotlib.pyplot as plt 
import matplotlib.colors as colors 
import matplotlib.cm as cmx 
import sys 
import csv 

if len(sys.argv) > 1: 
    flofile = sys.argv[1] 
else: 
    flofile = "GU3\GU3.flo" 

fig = plt.figure() 
ax = fig.add_subplot(111) 
jet = cm = plt.get_cmap('jet') 
cNorm = colors.Normalize(vmin=0) 
scalarMap = cmx.ScalarMappable(norm=cNorm,cmap=jet) 
with open(flofile) as FLO: 
    title = FLO.readline() 
    limits = [float(tp) for tp in FLO.readline().split()] 
    FLO.readline()#headers 
    for line in FLO: 
     if 'WELLS' in line: break   
     frac = ([float(tp) for tp in line.split()]) 
     ax.plot([frac[0],frac[2]],[frac[1],frac[3]],color=colorVal) 


#ax.plot(*call_list) 
scalarMap._A = [] 
plt.colorbar(scalarMap) 
plt.xlim([0,limits[0]]) 
plt.ylim([0,limits[1]]) 

plt.show() 

此代碼適用於小文件。謝謝。

+0

你希望看到什麼?要麼你的圖像是巨大的,所以你可以區分數以百萬計的線段,或者你的數百萬線段在合理大小的圖像上重疊。你可以通過計算類似密度的東西來減少問題的程度,從而將數百萬條線段減少到幾百或幾千個數據點? – Daan

+0

下面是我希望生成的一個例子:[鏈接](http://s10.postimg.org/gihylk9ih/Fracout_0000.png),這個例子有超過100,000條線段。我真的不能降低密度,因爲線的方向以及它與其他線連接的方式如何影響空間位置的值。我有一個過時的Fortran/C++/OpenGL代碼,我只是希望更新,並且可能會在程序中添加一個GUI。 – user2236411

回答

4

我會去了解一下LineCollection(doc)

s = (600,400) 
N = 100000 

segs = [] 
colors = [] 
my_cmap = plt.get_cmap('jet') 
for i in range(N): 
    x1 = random.random() * s[0] 
    y1 = random.random() * s[1] 
    x2 = random.random() * s[0] 
    y2 = random.random() * s[1] 
    c = random.random() 
    colors.append(my_cmap(c)) 
    segs.append(((x1, y1), (x2, y2))) 

ln_coll = matplotlib.collections.LineCollection(segs, colors=colors) 

ax = plt.gca() 
ax.add_collection(ln_coll) 
ax.set_xlim(0, 600)  
ax.set_ylim(0, 400) 
plt.draw() 

它也將採取numpy陣列的第一個論據清單。

+0

感謝你們,我以前曾經看過LineCollection,但沒有製作多個線條集合,最終導致相同的內存錯誤。儘管你的解決方案很好。 – user2236411

+0

@ user2236411很高興幫助。歡迎來到SO! – tacaswell

4

您可能會考慮先對位圖圖像進行繪圖,但不會出現內存問題,然後用matplotlib微調繪圖/圖像。舉個例子:

from PIL import Image 
from PIL import ImageDraw 
import random 
import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.image as mpimg 

s = (500,500) 
N = 100000 

im = Image.new('RGBA', s, (255,255,255,255)) 
draw = ImageDraw.Draw(im) 

for i in range(N): 
    x1 = random.random() * s[0] 
    y1 = random.random() * s[1] 
    x2 = random.random() * s[0] 
    y2 = random.random() * s[1] 
    c = random.random() * 256 
    draw.line(((x1,y1),(x2,y2)), fill=(0, 255 - int(c), int(c), 255), width=1) 

plt.imshow(np.asarray(im), extent=(-1,1,-1,1), aspect='equal', origin='lower') 
plt.show() 
+0

感謝您的解決方案,我最終使用LineCollection代替了它,因爲它更適合我的需求,但是此解決方案也可以工作。但是,如果有人使用這種解決方案,我相信位圖圖像會將原點移動到左上角,而不是左下角的圖形;所以你需要翻譯y值或者你的圖像將被鏡像在x軸上。 – user2236411

+0

@ user2236411你是對的,圖像被鏡像在x軸上,這可以通過'imshow'的關鍵字參數'origin'修復。我修復和編輯了這個和其他一些東西的腳本(im.save和mpimg.imread不是必需的)。 tcaswell的解決方案更好,因爲它只使用一個座標系,而只使用matplotlib。 –

+1

這是一個非常好的方法來處理大量數據和比其他任何事情都要快得多的數字 –