Python:建议改进一块一块的代码来读取数百万个点

时间:2012-10-07 13:44:30

标签: python performance coding-style matplotlib chunked-encoding

我编写了一个代码来读取Python中的*.las文件。 *las文件是特殊的ascii文件,其中每一行都是x,y,z点的值。

我的功能是N。点数并检查它们是否在points_inside_poly的多边形内。

我有以下问题:

  1. 当我到达文件末尾时,我收到此消息:LASException: LASError in "LASReader_GetPointAt": point subscript out of range因为点数在块大小之下。我无法想办法解决这个问题。
  2. a = [file_out.write(c[m]) for m in xrange(len(c))]我使用a =以避免视频打印。这是对的吗?
  3. c = [chunk[l] for l in index]我创建了一个新列表c,因为我不确定更换新块是否是智能解决方案(例如:chunk = [chunk[l] for l in index])。
  4. if else...else语句中,我使用pass。这是正确的选择吗?
  5. 真的感谢你的帮助。从专业知识改进听取建议非常重要!!!!

    import shapefile
    import numpy
    import numpy as np
    from numpy import nonzero
    from liblas import file as lasfile
    from shapely.geometry import Polygon
    from matplotlib.nxutils import points_inside_poly  
    
    
    # open shapefile (polygon)
    sf = shapefile.Reader(poly)
    shapes = sf.shapes()
    # extract vertices
    verts = np.array(shapes[0].points,float)
    
    # open las file
    f = lasfile.File(inFile,None,'r') # open LAS
    # read "header"
    h = f.header
    
    # create a file where store the points
    file_out = lasfile.File(outFile,mode='w',header= h)
    
    
    chunkSize = 100000
    for i in xrange(0,len(f), chunkSize):
        chunk = f[i:i+chunkSize]
    
        x,y = [],[]
    
        # extraxt x and y value for each points
        for p in xrange(len(chunk)):
            x.append(chunk[p].x)
            y.append(chunk[p].y)
    
        # zip all points 
        points = np.array(zip(x,y))
        # create an index where are present the points inside the polygon
        index = nonzero(points_inside_poly(points, verts))[0]
    
        # if index is not empty do this otherwise "pass"
        if len(index) != 0:
            c = [chunk[l] for l in index] #Is It correct to create a new list or i can replace chunck?
            # save points
            a = [file_out.write(c[m]) for m in xrange(len(c))] #use a = in order to avoid video print. Is it correct?
        else:
            pass #Is It correct to use pass?
    
    f.close()
    file_out.close()
    
    由@Roland Smith提出并由Gianni改变的代码

    f = lasfile.File(inFile,None,'r') # open LAS
    h = f.header
    # change the software id to libLAS
    h.software_id = "Gianni"
    file_out = lasfile.File(outFile,mode='w',header= h)
    f.close()
    sf = shapefile.Reader(poly) #open shpfile
    shapes = sf.shapes()
    for i in xrange(len(shapes)):
        verts = np.array(shapes[i].points,float)
        inside_points = [p for p in lasfile.File(inFile,None,'r') if pnpoly(p.x, p.y, verts)]
        for p in inside_points:
            file_out.write(p)
    f.close()
    file_out.close()
    

    我使用了这些解决方案: 1)读取 f = lasfile.File(inFile,None,'r'),然后读取 head ,因为我需要* .las输出文件 2)关闭文件 3)如果pnpoly(p.x,p.y,verts)] 而不是

    ,我使用 inside_points = [p for las in lasfile.File(inFile,None,'r')
    with lasfile.File(inFile, None, 'r') as f:
    ...     inside_points = [p for p in f if pnpoly(p.x, p.y, verts)]
    ...     
    

    因为我总是收到此错误消息

    追踪(最近一次通话): 文件“”,第1行,in AttributeError:_ 退出 _

1 个答案:

答案 0 :(得分:3)

关于(1):

首先,你为什么要使用块?只需使用lasfile作为迭代器(如tutorial所示),并一次处理一个点。以下内容应该通过在列表推导中使用pnpoly函数而不是points_inside_poly将多边形内的所有点写入输出文件。

from liblas import file as lasfile
import numpy as np
from matplotlib.nxutils import pnpoly

with lasfile.File(inFile, None, 'r') as f:
    inside_points = (p for p in f if pnpoly(p.x, p.y, verts))
    with lasfile.File(outFile,mode='w',header= h) as file_out:
        for p in inside_points:
            file_out.write(p)

上面的五行应该替换整个大for - 循环。我们一个接一个地讨论它们:

  • with lasfile.File(inFile ...:使用此结构意味着当with块完成时文件将自动关闭。
  • 现在是好的部分,生成所有工作的生成器表达式(()之间的部分)。它遍历输入文件(for p in f)。多边形内的每个点(if pnpoly(p.x, p.y, verts))都会添加到生成器中。
  • 我们使用另一个with块作为输出文件
  • 和所有点(for p in inside_points,这是使用的生成器)
  • 将写入输出文件(file_out.write(p)

因为此方法仅将多边形内的点添加到列表中,所以不会在不需要的点上浪费内存!

如果上面显示的方法不起作用,您应该使用块。 使用块时,您应该正确处理异常。 E.g:

from liblas import LASException

chunkSize = 100000
for i in xrange(0,len(f), chunkSize):
    try:
        chunk = f[i:i+chunkSize]
    except LASException:
        rem = len(f)-i
        chunk = f[i:i+rem]

关于(2):对不起,但我不明白你在这里想要完成什么。你是什​​么意思“视频打印”?

关于(3):由于您不再使用原始块,您可以重复使用该名称。意识到在python中“变量”只是nametag

关于(4):你没有使用else,所以完全不用它。