Files
LPP/src/bdump.py

284 lines
7.7 KiB
Python

# Pizza.py toolkit, www.cs.sandia.gov/~sjplimp/pizza.html
# Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
#
# Copyright (2005) Sandia Corporation. Under the terms of Contract
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
# certain rights in this software. This software is distributed under
# the GNU General Public License.
# bdump tool
oneline = "Read dump files with bond info"
docstr = """
b = bdump("dump.one") read in one or more dump files
b = bdump("dump.1 dump.2.gz") can be gzipped
b = bdump("dump.*") wildcard expands to multiple files
b = bdump("dump.*",0) two args = store filenames, but don't read
incomplete and duplicate snapshots are deleted
no column name assignment is performed
time = b.next() read next snapshot from dump files
used with 2-argument constructor to allow reading snapshots one-at-a-time
snapshot will be skipped only if another snapshot has same time stamp
return time stamp of snapshot read
return -1 if no snapshots left or last snapshot is incomplete
no column name assignment is performed
b.map(1,"id",3,"x") assign names to atom columns (1-N)
must assign id,type,atom1,atom2
time,box,atoms,bonds,tris,lines = b.viz(index) return list of viz objects
viz() returns line info for specified timestep index
can also call as viz(time,1) and will find index of preceding snapshot
time = timestep value
box = NULL
atoms = NULL
bonds = id,type,atom1,atom2 for each line as 2d array
tris = NULL
lines = NULL
"""
# History
# 11/10, Steve Plimpton (SNL): original version
# Variables
# flist = list of dump file names
# increment = 1 if reading snapshots one-at-a-time
# nextfile = which file to read from via next()
# eof = ptr into current file for where to read via next()
# nsnaps = # of snapshots
# snaps = list of snapshots
# names = dictionary of column names:
# key = "id", value = column # (0 to M-1)
# Snap = one snapshot
# time = time stamp
# natoms = # of atoms
# atoms[i][j] = 2d array of floats, i = 0 to natoms-1, j = 0 to ncols-1
# Imports and external programs
import sys, commands, re, glob, types
from os import popen
try:
import numpy as np
oldnumeric = False
except:
import Numeric as np
oldnumeric = True
try: from DEFAULTS import PIZZA_GUNZIP
except: PIZZA_GUNZIP = "gunzip"
# Class definition
class bdump:
# --------------------------------------------------------------------
def __init__(self,*list):
self.snaps = []
self.nsnaps = 0
self.names = {}
# flist = list of all dump file names
words = list[0].split()
self.flist = []
for word in words: self.flist += glob.glob(word)
if len(self.flist) == 0 and len(list) == 1:
raise StandardError,"no bdump file specified"
if len(list) == 1:
self.increment = 0
self.read_all()
else:
self.increment = 1
self.nextfile = 0
self.eof = 0
# --------------------------------------------------------------------
def read_all(self):
# read all snapshots from each file
# test for gzipped files
for file in self.flist:
if file[-3:] == ".gz":
f = popen("%s -c %s" % (PIZZA_GUNZIP,file),'r')
else: f = open(file)
snap = self.read_snapshot(f)
while snap:
self.snaps.append(snap)
print snap.time,
sys.stdout.flush()
snap = self.read_snapshot(f)
f.close()
print
# sort entries by timestep, cull duplicates
self.snaps.sort(self.compare_time)
self.cull()
self.nsnaps = len(self.snaps)
print "read %d snapshots" % self.nsnaps
# --------------------------------------------------------------------
# read next snapshot from list of files
def next(self):
if not self.increment: raise StandardError,"cannot read incrementally"
# read next snapshot in current file using eof as pointer
# if fail, try next file
# if new snapshot time stamp already exists, read next snapshot
while 1:
f = open(self.flist[self.nextfile],'rb')
f.seek(self.eof)
snap = self.read_snapshot(f)
if not snap:
self.nextfile += 1
if self.nextfile == len(self.flist): return -1
f.close()
self.eof = 0
continue
self.eof = f.tell()
f.close()
try:
self.findtime(snap.time)
continue
except: break
self.snaps.append(snap)
snap = self.snaps[self.nsnaps]
self.nsnaps += 1
return snap.time
# --------------------------------------------------------------------
# read a single snapshot from file f
# return snapshot or 0 if failed
# assign column names if not already done and file is self-describing
# convert xs,xu to x
def read_snapshot(self,f):
try:
snap = Snap()
item = f.readline()
snap.time = int(f.readline().split()[0]) # just grab 1st field
item = f.readline()
snap.natoms = int(f.readline())
item = f.readline()
if snap.natoms:
words = f.readline().split()
ncol = len(words)
for i in xrange(1,snap.natoms):
words += f.readline().split()
floats = map(float,words)
if oldnumeric: atoms = np.zeros((snap.natoms,ncol),np.Float)
else: atoms = np.zeros((snap.natoms,ncol),np.float)
start = 0
stop = ncol
for i in xrange(snap.natoms):
atoms[i] = floats[start:stop]
start = stop
stop += ncol
else: atoms = None
snap.atoms = atoms
return snap
except:
return 0
# --------------------------------------------------------------------
# map atom column names
def map(self,*pairs):
if len(pairs) % 2 != 0:
raise StandardError, "bdump map() requires pairs of mappings"
for i in range(0,len(pairs),2):
j = i + 1
self.names[pairs[j]] = pairs[i]-1
# --------------------------------------------------------------------
# return vector of snapshot time stamps
def time(self):
vec = self.nsnaps * [0]
i = 0
for snap in self.snaps:
vec[i] = snap.time
i += 1
return vec
# --------------------------------------------------------------------
# sort snapshots on time stamp
def compare_time(self,a,b):
if a.time < b.time:
return -1
elif a.time > b.time:
return 1
else:
return 0
# --------------------------------------------------------------------
# delete successive snapshots with duplicate time stamp
def cull(self):
i = 1
while i < len(self.snaps):
if self.snaps[i].time == self.snaps[i-1].time:
del self.snaps[i]
else:
i += 1
# --------------------------------------------------------------------
# return list of bonds to viz for snapshot isnap
# if called with flag, then index is timestep, so convert to snapshot index
def viz(self,index,flag=0):
if not flag: isnap = index
else:
times = self.time()
n = len(times)
i = 0
while i < n:
if times[i] > index: break
i += 1
isnap = i - 1
snap = self.snaps[isnap]
time = snap.time
id = self.names["id"]
type = self.names["type"]
atom1 = self.names["atom1"]
atom2 = self.names["atom2"]
# create line list from id,type,atom1,atom2
# abs() of type since could be negative
bonds = []
for i in xrange(snap.natoms):
atom = snap.atoms[i]
bonds.append([int(atom[id]),abs(int(atom[type])),
int(atom[atom1]),int(atom[atom2])])
return time,None,None,bonds,None,None
# --------------------------------------------------------------------
# one snapshot
class Snap:
pass