2013-04-02 110 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

这是一个非常好的方法来处理大量数据和比其他任何事情都要快得多的数字 –