24小时热门版块排行榜    

查看: 2055  |  回复: 9
当前只显示满足指定条件的回帖,点击这里查看本话题的所有回帖

yjcmwgk

禁虫 (文坛精英)

密度泛函·小卒

优秀版主

[求助] 用Python读Gaussian的cube文件,速度很慢,怎么破?谢谢!!! 已有4人参与

向各位python大侠求教一个问题,谢谢各位!
我正在用python读一个由Gaussian生成的cube文件。但是读文件读得非常慢,读一个6M多的cube文件,居然用了3分钟!

具体问题如下:
用cubefile来打开某个cube文件。然后继续
CODE:
    tmpcubedata = [] !先设一个空列表,待会儿用来存储数据
    tmpcubedata = tmpcubedata + tmpline.split() !tmpline是用来存储某一行的数据的。由于先前已经经过了多次tmpline.split()之后,实际上现在的tmpline存储的就是我已经想要的那些数据的第一行了。所以,先读一下并存入tmpcubedata中。
    i = 1 !这是个计数器。每读一行数据就加1
    tmplines=cubefile.readlines() !把剩下的行全读进来
    for i in range(1,linecount): !linecount就是应该读入的cube文件中数据部分的总行数,一般来说,Gaussian生成的cube文件中,如果生成过程全默认,那么cube文件的数据部分应该是8-9万行的样子。大部分行,每行有6个数字(大概95%的行是这样的),但也不排除只有1-5个数字的情况(大概5%的行是这样的)。
        tmpline = tmplines[i-1] !从tmplines中获得某一行
        if tmpline == 'EOF' : break
        if tmpline == [] : break
        if tmpline == None : break
        if i == linecount: break !如果计数器i达到了总行数,就不读了
        if i%10000 == 0: print "Converting", cubefilename, "......  ", int(100.0*float(i)/float(linecount)), "%" !每读一万行数据,就显示一个进度百分比
        if i == linecount-1 : print "Converting", cubefilename, "...... ", "100 %" !读到最后一行数据的时候,就显示一个百分之百
        i = i+1
        tmpcubedata = tmpcubedata + tmpline.split() !将读进来的数据存入tmpcubedata中

我怀疑tmpline = tmplines[i-1]这句话拖累的速度?应该如何修改?非常感谢高手帮助!!
感谢!!
回复此楼

» 收录本帖的淘帖专辑推荐

SOB 集锦 经验 杂书

» 猜你喜欢

» 本主题相关价值贴推荐,对您同样有帮助:

已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

两粒一起吃

金虫 (初入文坛)

【答案】应助回帖

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
感谢参与,应助指数 +1
yjcmwgk: 金币+10, 有帮助, 非常感谢,我后来用tmpp = ((' '.join(cubefile.readlines())).replace("/n"," ")).split()解决了 2014-10-05 16:10:53
gmy1990: 金币+3 2014-10-05 18:50:03
你的代码不pythonic,不易读也很低效,
这里给个例子,不知道是不是你要的功能

def readcube(cubefile):
    cubedata = []
    with open(cubefile) as f:
        lines = f.readlines()  #  if cubefile is large, read it in streaming or blocks
        # handle headers here
        for line in lines[2:]:
            for item in line.split():
                cubedata.append(eval(item))
    return cubedata

if __name__ == '__main__':
    testfile = 'test.cube'
    data = readcube(testfile)
    print(len(data))
    print(data[:10])
    print(data[-10:])
9楼2014-10-05 15:29:16
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
查看全部 10 个回答

yjcmwgk

禁虫 (文坛精英)

密度泛函·小卒

优秀版主

cube文件的基本结构举例如下
CODE:
Title Card Required mo=1
MO coefficients
   -1   -2.916225   -2.916225   -2.916225
   80    0.073828    0.000000    0.000000
   80    0.000000    0.073828    0.000000
   80    0.000000    0.000000    0.073828
    2    2.000000    0.000000    0.000000    0.000000
    1    1
  7.36784E-05  8.36290E-05  9.46155E-05  1.06698E-04  1.19934E-04  1.34374E-04
  1.50064E-04  1.67044E-04  1.85341E-04  2.04976E-04  2.25955E-04  2.48274E-04
  2.71913E-04  2.96838E-04  3.22995E-04  3.50318E-04  3.78721E-04  4.08098E-04
  4.38328E-04  4.69271E-04  5.00768E-04  5.32647E-04  5.64718E-04  5.96779E-04
  6.28614E-04  6.60000E-04  6.90707E-04  7.20497E-04  7.49136E-04  7.76386E-04
  8.02019E-04  8.25811E-04  8.47551E-04  8.67043E-04  8.84107E-04  8.98583E-04
  9.10334E-04  9.19248E-04  9.25239E-04  9.28250E-04  9.28250E-04  9.25239E-04
  9.19248E-04  9.10334E-04  8.98583E-04  8.84107E-04  8.67043E-04  8.47551E-04
  8.25811E-04  8.02019E-04  7.76386E-04  7.49136E-04  7.20497E-04  6.90707E-04
  6.60000E-04  6.28614E-04  5.96779E-04  5.64718E-04  5.32647E-04  5.00768E-04
  4.69271E-04  4.38328E-04  4.08098E-04  3.78721E-04  3.50318E-04  3.22995E-04
  2.96838E-04  2.71913E-04  2.48274E-04  2.25955E-04  2.04976E-04  1.85341E-04
  1.67044E-04  1.50064E-04  1.34374E-04  1.19934E-04  1.06698E-04  9.46155E-05
  8.36290E-05  7.36784E-05
  8.36290E-05  9.49233E-05  1.07394E-04  1.21108E-04  1.36131E-04  1.52521E-04
  1.70331E-04  1.89603E-04  2.10372E-04  2.32658E-04  2.56471E-04  2.81805E-04
  3.08636E-04  3.36926E-04  3.66617E-04  3.97630E-04  4.29868E-04  4.63213E-04
下面还有八万多行,略了

对于这个cube文件来说,从第9行开始是第一个数据行,直到文件结束。值得注意的是,绝大多数数据行,每行有6个数字,但第22行就只有2个数字了。
2楼2014-10-04 11:08:58
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

frk2008

木虫 (正式写手)

【答案】应助回帖

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
感谢参与,应助指数 +1
yjcmwgk: 金币+20, 有帮助, 非常感谢,我后来用tmpp = ((' '.join(cubefile.readlines())).replace("/n"," ")).split()解决了 2014-10-05 16:10:10
gmy1990: 金币+3 2014-10-05 18:49:03
试试这个,看看效果如何:

[ code]

tmplines = cubefile.readlines()  
tempstr = "".join(tmplines)             #把list转化为str,形式应该是'num  num  ...num\nnum  ...'
tempstr = tempstr.replace('\n','  ')    #把str中的'\n'替换为'  '
tmpcubedata = tempstr.split('  ')       #把str转为list
n=0
numcount=len(tmpcubedata)               #list的数据总数
for i in tmpcubedata:
    n+=1
    if i%60000==0:
        print "Converting", cubefilename, "......  ", int(100.0*float(i)/float(numcount)), "%"
    #if i=="":
        #tmpcubedata.remove(i)          #如果cubefile 文件中中间有空行,则需要这个功能
if tmpcubedata[-1]=="":
    del tmpcubedata[-1]                 #如果cubefile 文件以‘num\n‘结尾
print "Converting", cubefilename, "...... ", "100 %"

[ /code]
3楼2014-10-04 15:23:36
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

rh1127

捐助贵宾 (著名写手)

一名工程师@上海

【答案】应助回帖

★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★
感谢参与,应助指数 +1
yjcmwgk: 金币+20, 有帮助, 非常感谢,我后来用tmpp = ((' '.join(cubefile.readlines())).replace("/n"," ")).split()解决了 2014-10-05 16:10:21
gmy1990: 金币+2 2014-10-05 18:49:14
用numpy和pandas模块儿来处理大型数组,比只用for循环速度快几十倍不止。python自带的循环未经优化,很忌讳来处理大型数组!
希望对你有帮助。
Actionnoworachievenever!
4楼2014-10-05 09:21:10
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
信息提示
请填处理意见