summaryrefslogtreecommitdiff
path: root/sim/src/tests/scripts/MmpFile.py
blob: 29447f079328f3eb840638b3140f97851976d4c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/python

"""Grab one of Damian's minimized MMP files, perturb each atom's
position by some fraction of an angstrom, write out the result as
another MMP file, which becomes an input file for the test.

$Id$
"""

__author__ = "Will"

import re
import os
import sys
import string
import Atom

class MmpFile:
    """This is meant to be a Python class representing a MMP file. It
    is not intended to represent ALL the information in a MMP file,
    although it might do that in some distant-future version. Right
    now, its biggest strength is that it allows us to easily modify
    the positions of the atoms in an MMP file, and write out the
    resulting modified MMP file."""
    class _Line:
        def fromMmp(self, line):
            self._str = line
        def str(self):
            return self._str
    class _AtomHolder:
        """Atom holders are indices into the MmpFile.atoms list,
        and that's done so that MmpFiles are easier to clone.
        """
        def __init__(self, owner):
            self._owner = owner
        def fromMmp(self, line):
            atoms = self._owner.atoms
            n = len(atoms)
            a = Atom.Atom()
            try:
                a.fromMmp(line)
            except Atom.NotAtomException:
                del a
                return False
            self._index = n
            atoms.append(a)
            return True
        def mmpBonds(self, line):
            return self._owner.atoms[self._index].mmpBonds(line)
        def str(self):
            a = self._owner.atoms[self._index]
            return a.toMmpString()
    def __init__(self):
        self.atoms = [ ]
        self.lines = [ ]
    def clone(self):
        other = MmpFile()
        other.lines = self.lines[:]
        other.atoms = [ ]
        for a in self.atoms:
            other.atoms.append(a.clone())
        return other
    def getAtom(self, i):
        return self.atoms[i]
    def __getitem__(self, i):
        a = self.atoms[i]
        return (a.x, a.y, a.z)
    def __setitem__(self, i, xyz):
        a = self.atoms[i]
        a.x, a.y, a.z = xyz
    def __len__(self):
        return len(self.atoms)
    def read(self, filename):
        inf = open(filename)
        self.readstring(inf.read())
        inf.close()
    def readstring(self, lines):
        lines = Atom.FileLineIterator(lines.split(os.linesep))
        try:
            while True:
                line = lines.next()
                atm = MmpFile._AtomHolder(self)
                if atm.fromMmp(line):
                    self.lines.append(atm)
                    line = lines.next()
                    if atm.mmpBonds(line):
                        x = MmpFile._Line()
                        x.fromMmp(line)
                        self.lines.append(x)
                    else:
                        lines.backup()
                else:
                    x = MmpFile._Line()
                    x.fromMmp(line)
                    self.lines.append(x)
        except StopIteration:
            pass
    def write(self, outf=None):
        if outf == None:
            outf = sys.stdout
        for ln in self.lines:
            outf.write(ln.str() + "\n")
    def convertToXyz(self):
        import XyzFile
        xyz = XyzFile.XyzFile()
        for a in self.atoms:
            xyz.atoms.append(a)
        return xyz
    def perturb(self):
        import random
        A = 0.5   # some small number of angstroms
        A = A / (3 ** .5)   # amount in one dimension
        for i in range(len(self)):
            x, y, z = self[i]
            x += random.normalvariate(0.0, A)
            y += random.normalvariate(0.0, A)
            z += random.normalvariate(0.0, A)
            self[i] = (x, y, z)

if __name__ == "__main__":
    """What follows is a specific usage of the MmpFile class. It's not
    the only way it could be used, but it demonstrates something we're
    going to want to do very soon as we generate test cases from
    Damian's MMP files."""
    m = MmpFile()
    #input = "C14H20.mmp"
    input = "C3H8.mmp"
    m.read(input)
    m.perturb()
    if False:
        outf = open("results", "w")
        m.write(outf)
        outf.close()
    if False:
        for a in m.atoms:
            print a.bonds
    outf = os.popen("diff -u - %s" % input, "w")
    m.write(outf)
    outf.close()