1#! /usr/freeware/bin/python
2
3#
4# This is dump2trj, a program written by Keir E. Novik to convert
5# Lammps position dump files to Amber trajectory files.
6#
7# Copyright 2000 Keir E. Novik; all rights reserved.
8#
9
10#============================================================
11
12def Convert_files():
13    'Handle the whole conversion process'
14
15    print
16    print 'Welcome to dump2trj, a program to convert Lammps position dump files to\nAmber trajectory format!'
17    print
18
19    Basename_list = Find_dump_files()
20
21    for Basename in Basename_list:
22        t = Trajectory()
23        if t.Read_dump(Basename):
24            t.Write_trj(Basename)
25        del t
26        print
27
28#============================================================
29
30def Find_dump_files():
31    'Look for sets of Lammps position dump files to process'
32
33    '''If passed something on the command line, treat it as a list of
34    files to process.  Otherwise, look for *.dump in the current
35    directory.
36    '''
37
38    import os, sys
39
40    Basename_list = []
41
42    # Extract basenames from command line
43    for Name in sys.argv[1:]:
44        if Name[-5:] == '.dump':
45            Basename_list.append(Name[:-5])
46        else:
47            Basename_list.append(Name)
48
49    if Basename_list == []:
50        print 'Looking for Lammps dump files...',
51        Dir_list = os.listdir('.')
52        for Filename in Dir_list:
53            if Filename[-5:] == '.dump':
54                Basename_list.append(Filename[:-5])
55        Basename_list.sort()
56        if Basename_list != []:
57            print 'found',
58            for i in range(len(Basename_list)-1):
59                print Basename_list[i] + ',',
60            print Basename_list[-1] + '\n'
61
62    if Basename_list == []:
63        print 'none.\n'
64
65    return Basename_list
66
67#============================================================
68
69class Snapshot:
70    def __init__(self, The_trajectory):
71        'Initialize the Snapshot class'
72
73        self.atoms = The_trajectory.atoms
74        self.xlo = The_trajectory.xlo
75        self.xhi = The_trajectory.xhi
76        self.ylo = The_trajectory.ylo
77        self.yhi = The_trajectory.yhi
78        self.zlo = The_trajectory.zlo
79        self.zhi = The_trajectory.zhi
80
81    #--------------------------------------------------------
82
83    def Read_dump(self, Lines):
84        'Read a snapshot (timestep) from a Lammps position dump file'
85
86        '''Trajectory.Read_dump() will pass us only the lines we need
87        (including the timestep number).
88        '''
89
90        self.Atom_list = Lines[3:]
91
92    #--------------------------------------------------------
93
94    def Write_trj(self, F):
95        'Write a snapshot (timestep) to an Amber trajectory file'
96
97        '''The Atom_list must be sorted, as it may not be in order
98        (for example, in a parallel Lammps simulation).  The first
99        element (before the sort) is the header line.
100        '''
101
102        import string
103
104        xBOX = (self.xhi - self.xlo)
105        yBOX = (self.yhi - self.ylo)
106        zBOX = (self.zhi - self.zlo)
107
108        Min = min(self.xlo, self.ylo, self.zlo)
109        Max = max(self.xhi, self.yhi, self.zhi, xBOX, yBOX, zBOX)
110        if Min <= -1000 or Max >= 10000:
111            print '(error: coordinates too large!)'
112            return
113
114        Print_list = []
115
116        self.Atom_list = self.Atom_list[1:]
117        self.Atom_list.sort()
118
119        for Line in self.Atom_list:
120            Item_list = string.split(Line)
121            x = xBOX * Float(Item_list[2])
122            y = yBOX * Float(Item_list[3])
123            z = zBOX * Float(Item_list[4])
124            Print_list.append('%(x)8.3f' % vars())
125            Print_list.append('%(y)8.3f' % vars())
126            Print_list.append('%(z)8.3f' % vars())
127
128            if len(Print_list) > 9:
129                Line = ''
130                for j in range(10):
131                    Line = Line + Print_list[j]
132                Line = Line + '\n'
133                Print_list = Print_list[10:]
134
135                try:
136                    F.write(Line)
137                except IOError, Detail:
138                    print '(error:', Detail[1] + '!)'
139                    F.close()
140                    return
141
142        if len(Print_list) > 0:
143            Line = ''
144            for j in range(len(Print_list)):
145                Line = Line + Print_list[j]
146            Line = Line + '\n'
147
148            try:
149                F.write(Line)
150            except IOError, Detail:
151                print '(error:', Detail[1] + '!)'
152                F.close()
153                return
154
155        Line = '%(xBOX)8.3f%(yBOX)8.3f%(zBOX)8.3f\n' % vars()
156        try:
157            F.write(Line)
158        except IOError, Detail:
159            print '(error:', Detail[1] + '!)'
160            F.close()
161            return
162
163#============================================================
164
165class Trajectory:
166    #--------------------------------------------------------
167
168    def Read_dump(self, Basename):
169        'Read a Lammps position dump file'
170
171        import string, sys
172
173        Filename = Basename + '.dump'
174
175        print 'Reading', Filename + '...',
176        sys.stdout.flush()
177
178        try:
179            F = open(Filename)
180        except IOError, Detail:
181            print '(error:', Detail[1] + '!)'
182            return 0
183
184        try:
185            Lines = F.readlines()
186        except IOError, Detail:
187            print '(error:', Detail[1] + '!)'
188            F.close()
189            return 0
190
191        F.close()
192
193        # Read the number of atoms
194        self.atoms = int(Lines[1])
195
196        # Read the periodic box boundaries
197        Item_list = string.split(Lines[3])
198        self.xlo = Float(Item_list[0])
199        self.xhi = Float(Item_list[1])
200        Item_list = string.split(Lines[4])
201        self.ylo = Float(Item_list[0])
202        self.yhi = Float(Item_list[1])
203        Item_list = string.split(Lines[5])
204        self.zlo = Float(Item_list[0])
205        self.zhi = Float(Item_list[1])
206
207        # Read atom positions in each snapshot
208        Snapshots = (len(Lines) - 6) / (self.atoms + 3)
209        if int(Snapshots) != Snapshots:
210            print '(error: wrong length of dump!)'
211            return
212
213        self.Snapshot_list = []
214        for i in range(Snapshots):
215            self.Snapshot_list.append(Snapshot(self))
216            Start = 5 + i * (self.atoms + 3)
217            End = Start + (self.atoms + 3) + 1
218            self.Snapshot_list[-1].Read_dump(Lines[Start:End])
219
220        print 'done.'
221        return 1
222
223    #--------------------------------------------------------
224
225    def Write_trj(self, Basename):
226        'Write an Amber trajectory file'
227
228        import os, sys
229
230        Filename = Basename + '.x'
231
232        Dir_list = os.listdir('.')
233        i = 1
234        while Filename in Dir_list:
235            Filename = Basename + `i` + '.x'
236            i = i + 1
237        del i
238
239        print 'Writing', Filename + '...',
240        sys.stdout.flush()
241
242        try:
243            F = open(Filename, 'w')
244        except IOError, Detail:
245            print '(error:', Detail[1] + '!)'
246            return
247
248        try:
249            F.write(Basename + '\n')
250        except IOError, Detail:
251            print '(error:', Detail[1] + '!)'
252            F.close()
253            return
254
255        for S in self.Snapshot_list:
256            S.Write_trj(F)
257
258        F.close()
259        print 'done.'
260
261#============================================================
262
263def Float(s):
264    'Return the string s as a float, if possible'
265
266    try:
267        x = float(s)
268    except ValueError:
269        if s[-1] == ',':
270            s = s[:-1]
271        x = float(s)
272
273    return x
274
275#============================================================
276
277Convert_files()
278