帮助我的代码更快:我的
python代码需要生成一个二维格点的落在一个有界的矩形内.我汇集了一些生成这个格子的代码(如下所示).然而,这个功能被称为很多次,并且已经成为我的应用程序的严重瓶颈.
我确定有一个更快的方式来做到这一点,可能涉及到numpy数组而不是列表.有什么建议,以更快,更优雅的方式做到这一点?
功能描述:
我有两个2D矢量v1和v2.这些矢量define a lattice.在我的情况下,我的矢量定义了一个格子,几乎是六边形,但不完全相同.我想在这个格子上生成一些在一些边界矩形中的所有2D点的集合.在我的情况下,矩形的一个角是(0,0),其他角是正坐标.
例:
如果我的边框的最远的角落在(3,3),我的格子矢量是:
v1 = (1.2,0.1) v2 = (0.2,1.1)
我想要我的功能返回点数:
(1.2,0.1) #v1 (2.4,0.2) #2*v1 (0.2,1.1) #v2 (0.4,2.2) #2*v2 (1.4,1.2) #v1 + v2 (2.6,1.3) #2*v1 + v2 (1.6,2.3) #v1 + 2*v2 (2.8,2.4) #2*v1 + 2*v2
我不关心边缘病例;例如,函数返回(0,0)并不重要.
我目前做的这个缓慢的方式:
import numpy,pylab def generate_lattice( #Help me speed up this function,please! image_shape,lattice_vectors,center_pix='image',edge_buffer=2): ##Preprocessing. Not much of a bottleneck: if center_pix == 'image': center_pix = numpy.array(image_shape) // 2 else: ##Express the center pixel in terms of the lattice vectors center_pix = numpy.array(center_pix) - (numpy.array(image_shape) // 2) lattice_components = numpy.linalg.solve( numpy.vstack(lattice_vectors[:2]).T,center_pix) lattice_components -= lattice_components // 1 center_pix = (lattice_vectors[0] * lattice_components[0] + lattice_vectors[1] * lattice_components[1] + numpy.array(image_shape)//2) num_vectors = int( ##Estimate how many lattice points we need max(image_shape) / numpy.sqrt(lattice_vectors[0]**2).sum()) lattice_points = [] lower_bounds = numpy.array((edge_buffer,edge_buffer)) upper_bounds = numpy.array(image_shape) - edge_buffer ##SLOW LOOP HERE. 'num_vectors' is often quite large. for i in range(-num_vectors,num_vectors): for j in range(-num_vectors,num_vectors): lp = i * lattice_vectors[0] + j * lattice_vectors[1] + center_pix if all(lower_bounds < lp) and all(lp < upper_bounds): lattice_points.append(lp) return lattice_points ##Test the function and display the output. ##No optimization needed past this point. lattice_vectors = [ numpy.array([-40.,-1.]),numpy.array([ 18.,-37.])] image_shape = (1000,1000) spots = generate_lattice(image_shape,lattice_vectors) fig=pylab.figure() pylab.plot([p[1] for p in spots],[p[0] for p in spots],'.') pylab.axis('equal') fig.show()
解决方法
如果你想对整个事物进行矢量化,生成一个方形格子然后剪切.然后把你的盒子外面的边缘切断.
这是我想出来的还有很多改进可以做,但这是基本的想法.
def generate_lattice(image_shape,lattice_vectors) : center_pix = numpy.array(image_shape) // 2 # Get the lower limit on the cell size. dx_cell = max(abs(lattice_vectors[0][0]),abs(lattice_vectors[1][0])) dy_cell = max(abs(lattice_vectors[0][1]),abs(lattice_vectors[1][1])) # Get an over estimate of how many cells across and up. nx = image_shape[0]//dx_cell ny = image_shape[1]//dy_cell # Generate a square lattice,with too many points. # Here I generate a factor of 4 more points than I need,which ensures # coverage for highly sheared lattices. If your lattice is not highly # sheared,than you can generate fewer points. x_sq = np.arange(-nx,nx,dtype=float) y_sq = np.arange(-ny,dtype=float) x_sq.shape = x_sq.shape + (1,) y_sq.shape = (1,) + y_sq.shape # Now shear the whole thing using the lattice vectors x_lattice = lattice_vectors[0][0]*x_sq + lattice_vectors[1][0]*y_sq y_lattice = lattice_vectors[0][1]*x_sq + lattice_vectors[1][1]*y_sq # Trim to fit in Box. mask = ((x_lattice < image_shape[0]/2.0) & (x_lattice > -image_shape[0]/2.0)) mask = mask & ((y_lattice < image_shape[1]/2.0) & (y_lattice > -image_shape[1]/2.0)) x_lattice = x_lattice[mask] y_lattice = y_lattice[mask] # Translate to the centre pix. x_lattice += center_pix[0] y_lattice += center_pix[1] # Make output compatible with original version. out = np.empty((len(x_lattice),2),dtype=float) out[:,0] = y_lattice out[:,1] = x_lattice return out