有效地在python中生成点的晶格

如何解决有效地在python中生成点的晶格

| 帮助提高我的代码速度:我的python代码需要生成一个落在边界矩形内的二维点阵。我将产生该晶格的一些代码(如下所示)合并在一起。但是,此函数被多次调用,并且已成为我的应用程序中的严重瓶颈。 我敢肯定有一种更快的方法,可能涉及numpy数组而不是列表。对于更快,更优雅的方式有什么建议吗? 功能说明:  我有两个2D向量,v1和v2。这些向量定义了一个晶格。在我的情况下,我的向量定义了几乎但不完全是六边形的格子。我想在此边界上的某个边界矩形中生成所有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
    ,由于
lower_bounds
upper_bounds
只是2个元素的数组,因此numpy在这里可能不是正确的选择。尝试更换
if all(lower_bounds < lp) and all(lp < upper_bounds):
基本的Python内容:
if lower1 < lp and lower2 < lp and lp < upper1 and lp < upper2:
根据timeit,第二种方法要快得多:
>>> timeit.timeit(\'all(lower < lp)\',\'import numpy\\nlp=4\\nlower = numpy.array((1,5))\') 
3.7948939800262451
>>> timeit.timeit(\'lower1 < 4 and lower2 < 4\',\'lp = 4\\nlower1,lower2 = 1,5\') 
0.074192047119140625
根据我的经验,只要您不需要处理n维数据,并且如果不需要双精度浮点数,通常使用基本的Python数据类型和构造而不是numpy会更快,这是一种在这种情况下有点过载-请看另一个问题。 另一个小的改进可能是只计算一次“ 9”,然后重新使用它。另外,您可能希望使用乘积迭代器,而不是嵌套的for循环-尽管我认为这些更改不会对性能产生重大影响。     ,可能您可以用此替换两个for循环。
i,j = numpy.mgrid[-num_vectors:num_vectors,-num_vectors:num_vectors]
numel = num_vectors ** 2;
i = i.reshape(numel,1)
j = j.reshape(numel,1)
lp = i * lattice_vectors[0] + j * lattice_vectors[1] + center_pix
valid = numpy.all(lower_bounds < lp,1) and numpy.all(lp < upper_bounds,1)
lattice_points = lp[valid]
可能会有一些小错误,但是您明白了。 编辑 我对\“ numpy.all(lower_bounds ..)\”进行了修改,以说明正确的尺寸。     ,通过用重复的加法而不是乘法替换your11 computation的计算,我得到了超过2倍的提速。
xrange
优化似乎无关紧要(尽管可能不会造成伤害)。重复加法似乎比乘法更有效。将此与上面提到的其他优化结合起来可以提高速度。但是,当然,您可以获得的最好结果是将常数加速,因为输出的大小和原始代码一样都是平方的。
lv0,lv1 = lattice_vectors[0],lattice_vectors[1]
lv0_i = -num_vectors * lv0 + center_pix
lv1_orig = -num_vectors * lv1
lv1_j = lv1_orig
for i in xrange(-num_vectors,num_vectors):
    for j in xrange(-num_vectors,num_vectors):
        lp = lv0_i + lv1_j
        if all(lower_bounds < lp) and all(lp < upper_bounds):
            lattice_points.append(lp)
        lv1_j += lv1
    lv0_i += lv0
    lv1_j = lv1_orig
计时器结果:
>>> t = Timer(\"generate_lattice(image_shape,lattice_vectors,orig=True)\",\"from __main__ import generate_lattice,image_shape\")
>>> print t.timeit(number=50)
5.20121788979
>>> t = Timer(\"generate_lattice(image_shape,orig=False)\",image_shape\")
>>> print t.timeit(number=50)
2.17463898659
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-