Hm, was mir so auffällt ist, dass Du Daten in eine Datei 'ethan.tinker.tmp' schreibst, ``analyze`` dann aber mit 'input.tmp' fütterst. Ausserdem machst Du nichts mit dem Rückgabewert von `getEnergy()` und die Funktion müsste eine Ausnahme auslösen wenn die Datei wirklich leer ist. Du greifst auf Zeile 27 bzw. 28 zu, das gibt einen `IndexError` wenn in `content` nicht genug Zeilen wären.
Edit: Und noch ein paar Anmerkungen
Es gibt zwei Stellen bei denen die Einrückung fehlerhaft ist und *viele* bei denen die Einrückung inkonsistent ist. Empfohlen sind 4 Leerzeichen pro Ebene und keine Tab-Zeichen in der Datei.
Ein paar Zeilen sind länger als 80 Zeichen. Und der Style-Guide empfielt Leerzeichen um Operatoren und Zuweisungen und Namen im kleine_worte_mit_unterstrichen-Stil für alles ausser Klassen und Konstanten.
Sternchen-``import`` ist böse. In `Numeric` ist zum Beispiel eine Funktion `sum()` die beim Sternchen-``import`` die gleichnamige eingebaute ersetzt. So etwas kann zu unangenehmen Überraschungen führen. In `Numeric` sind ca. 170 Namen definiert von denen nur drei benutzt werden.
Auf Modulebene werden Programmcode mit Funktionsdefinitionen vermischt. Das ist unübersichtlich. Und Code auf Modulebene wird immer ausgeführt wenn man das Modul importiert. Man kann es also nicht im Interpretierer importieren um einzelne Funktionen zu testen.
Einen Index zu benutzen um über die Elemente einer oder mehrerer Listen zu iterieren ist "unpythonisch". In Python iteriert man stattdessen direkt über die Elemente. Falls man zusätzlich einen Index benötigt, kann man `enumerate()` benutzen. Der Quelltext wird dadurch in den meisten Fällen verständlicher weil anstelle eines Index ein (hoffentlich) aussagekräftiger Name tritt.
Beim Einlesen in `readCoordsTinker()` wird die erste Zeile anders behandelt, das kann man lösen indem man sich einen Iterator geben lässt und vor der Schleife die erste Zeile mit der `next()`-Methode holt. `info` wird übrigens unnötigerweise in eine Liste gesteckt. Man könnte die Schleife so schreiben, und an der Stelle schon alle Zeichenketten in die entsprechenden Typen umwandeln:
Code: Alles auswählen
lines = iter(lines)
nat = lines.next().split()[0]
for line in lines:
elements = line.split()
coords.append(map(float, elements[2:5]))
symbols.append(elements[1])
attype.append(map(int, elements[5]))
conn.append(map(int, elements[6:]))
Die ganzen Listen werden immer zusammen im Programm herumgereicht, was ein gutes Zeichen dafür ist, dass es keine unabhängigen Daten sind. Im Grunde scheinen die Elemente an einem Index zusammen zu gehören. Statt diese in "parallelen" Listen zu speichern, könnte man sie zu einem Objekt zusammenfassen und das dann in einer Liste speichern und kann diese Liste zurückgeben bzw. als Argumente übergeben.
Was soll eigentlich passieren wenn die Information über die Anzahl der Datensätze nicht mit der Information in der ersten Zeile übereinstimmt? Wenn die Anzahlen übereinstimmen, dann ist die Information in `nat` redundant, weil ``nat == len(coords)`` oder `len()` von einer der anderen Listen gilt.
Angenommen man hätte eine Liste mit einem Objekt pro Zeile (Atom?) dann könnte die Schleife beim Schreiben in eine Datei so aussehen:
Code: Alles auswählen
for i, atom in enumerate(atoms):
coord_str = ' '.join('%12.8f' % c for c in atom.coords)
conn_str = ' '.join('%4i' % c for c in atom.conn)
out.write('%5i %s %s %3i %s\n'
% (i + 1, atom.symbol, coord_str, atom.attype, conn_str))
Zum Umrechnen von Grad in Radians gibt's `math.radians()`.
Je grösser die Schrittanzahl um so ungenauer wird der jeweilige Winkel weil sich bei jeder Addition eine kleine Ungenauigkeit akkumuliert. Anstelle immer einen `Schritt` zu addieren kann man `Schritt` mit der aktuellen Schrittnummer multiplizieren.