2013-10-10 2 views
1

저는 프로그래밍과 Python을 처음 접했고 DLPOLY HISTORY 파일을 arc 파일로 변환하려고합니다. 내가해야할 일은 격자 벡터 (3x3 배열의 단어 timestep), x, y 및 z 좌표 (각 요소 아래의 줄에있는 세 항목) 및 요금 (선의 네 번째 항목은 요소).파이썬에서 텍스트 파일의 반복되는 반복 섹션의 경우

이상적으로는 결국 임의의 크기와 프레임 길이의 파일을 변환 할 수 있기를 바랍니다. 다음과 같습니다

두 향하고 라인과 DLPOLY 기록 파일의 처음 두 프레임 :

File Title 
     0   3   5     136     1906 
timestep   0   5 0 3   0.000500   0.000000 
     3.5853000000  0.0000000000  0.0000000000 
     -1.7926500000  3.1049600000  0.0000000000 
     0.0000000000  0.0000000000  4.8950000000 
Ca    1 40.078000 1.050000 0.000000 
    0.000000000   0.000000000   0.000000000 
O    2 15.999400 -0.950000 0.000000 
    1.792650000  -1.034986100   1.140535000 
H    3 1.007940 0.425000 0.000000 
    1.792650000  -1.034986100   1.933525000 
O    4 15.999400 -0.950000 0.000000 
    -1.792650000   1.034987000  -1.140535000 
H    5 1.007940 0.425000 0.000000 
    -1.792650000   1.034987000  -1.933525000 
timestep  10   5 0 3   0.000500   0.005000 
     3.5853063513  0.0000000000  0.0000000000 
     -1.7926531756  3.1049655004  0.0000000000 
     0.0000000000  0.0000000000  4.8950086714 
Ca    1 40.078000 1.050000 0.020485 
    -0.1758475885E-01 0.1947928245E-04 -0.1192033544E-01 
O    2 15.999400 -0.950000 0.051020 
    1.841369991  -1.037431082   1.120698646 
H    3 1.007940 0.425000 0.416965 
    1.719029690  -1.029327936   2.355541077 
O    4 15.999400 -0.950000 0.045979 
    -1.795057186   1.034993005  -1.093028694 
H    5 1.007940 0.425000 0.373772 
    -1.754959531   1.067269072  -2.320776528 

지금까지 내가 가지고있는 코드는 다음과 같습니다

fileList = history_file.readlines() 
number_of_frames = int(fileList[1].split()[3]) 
number_of_lines = int(fileList[1].split()[4]) 
frame_length = (number_of_lines - 2)/number_of_frames 
number_of_atoms = int(fileList[1].split()[2]) 
lines_per_atom = frame_length/number_of_atoms 

for i in range(3, number_of_lines+1, frame_length): 

#maths for converting lattice vectors 
#print statement to write out converted lattice vectors 

    for j in range(i+3, frame_length+1, lines_per_atom): 
      atom_type = fileList[j].split()[0] 
      atom_x = fileList[j+1].split()[0] 
      atom_y = fileList[j+1].split()[1] 
      atom_z = fileList[j+1].split()[2] 
      charge = fileList[j].split()[3] 
      print atom_type, atom_x, atom_y, atom_z, charge 

내가 추출 할 수 있습니다했는데 그게 문제가되지 않도록 격자 벡터를 변환하십시오. 그것이 한 번만 실행 루프에 대한 두 번째에 관해서 그러나 때, 내 범위

frame_length+1 

가 잘못된 문을 종료 있다고 생각하지만, 나는 다음과 같은 오류가

i+3+frame_length+1 

로 변경하는 경우 :

charge = fileList[j].split()[3] 
IndexError: list index out of range 

나는 내가 배열의 끝으로 가고 있다는 것을 의미한다고 생각한다.

나는 아주 단순한 것을 간과 했으리라 확신하지만, 어떤 도움이라도 대단히 감사하겠습니다.

readline이 전체 파일을 메모리로 읽어 들이고 HISTORY 파일이 수 GB 크기에 쉽게 도달 할 수 있기 때문에 파일을 더 효율적으로 읽을 수 있는지 궁금합니다.

답변

1

좋아, 우리가 제공 한 샘플 값을 사용하여 상당히 간단한 확인을하는이 문제를 찾을 수 있습니다. 우리는 다음과 같은 코드

for i in range(3,1907,136): 
    for j in range(i+3,137,2): 
     print i,j 

를 입력하면 우리는이를 얻을 :

3 6 
3 8 
3 10 
... 
3 132 
3 134 
3 136 

이렇게하면 발생하는 오류입니다. 루프는 한 번만 반복하는 것으로 보입니다. 그러나 코드를 약간 변경하면 문제의 원인을 알 수 있습니다.

i: 3 j: 6 
j: 8 
j: 10 
j: 12 
... 
j: 134 
j: 136 
i: 139 i: 275 i: 411 i: 547 i: 683 i: 819 i: 955 i: 1091 i: 1227 i: 1363 i: 1499 
i: 1635 i: 1771 

그래서 당신은 내부 루프 (J 루프)를 참조 처음 실행 할 수 있으며, 그 수행하면, 외부 루프 (내가 루프)를 실행합니다 : 우리는

for i in range(3,1907,136): 
    print "i:", i, 
    for j in range(i+3,137,2): 
     print "j:", j 

를 실행하면 우리는이를 얻을 수 내면의 고리에 가야하지 않고 끝까지 가야합니다. 이는 range이 내부 루프에 설정된 방식 때문입니다. 첫 번째 실행에서는 range(3,137,2)으로 평가되지만 두 번째 실행에서는 이 두 번째 실행시 139에서 시작하기 때문에 range(142,137,2)으로 나옵니다. 시작하기 전에 이미 종료되었습니다.

는이 내부 루프에 대한 당신이 원하는 (또는 당신이 원하는 것을 생각)으로 활용하려면 다음

for j in range(4,frame_length,line_per_atom): 
    atom_type = fileList[j+i].split()[0] 

이 있습니다 j 4 라인 과거 각 프레임 라인의 반복자

그러나 내가 알아 내지 못한 것은 코드가 전혀 작동하지 않는 것입니다. 나는 당신의 예제에서 값을 수표처럼 계산했다. 2.8의

frame_length = (1906 - 2)/136 = 14 
lines_per_atom = 14/5 = 2.8 

lines_per_atom 불법, 그것은 정수 여야합니다 나는 당신이 TypeError을받지 방법을 모른다. lines_per_atom에 대한 계산은 lines_per_atom = (frame_length - 4)/number_of_atoms이어야합니다.

어쨌든,이 작품 희망!

내가 lines_per_atom 계산에 실수를 잡을하지 않았다

+0

감사합니다 (또한, 내 의견을 입력, 그래서 lines_per_atomlinesPerAtom가된다. 대신 밑줄의 미래에 변수 이름을 낙타 케이스를 사용하여 훨씬 쉽게 시도). 이상한 점은 교정이 있든 없든 여전히 예상했던 2의 결과를 준다는 것입니다. 왜 이런지 궁금해? –

+0

또한 두 번째 루프에 제안 된 수정을 시도했지만 다음 오류가 발생합니다. charge = fileList [j + i] .split() [3] IndexError : 목록 인덱스가 범위를 벗어났습니다. –

+0

두 번째 루프를 범위 (i + 3, frame_length + i-2, lines_per_atom)의 j에 대해 변경했습니다. 이제는 원하는대로 할 것입니다. 다른 크기의 입력 파일을 가지고 놀아서 기대했던대로 작동하는지 확인해야 할 것입니다. –

관련 문제