[docs]classGMSReader(base.ReaderBase):"""Reads from an GAMESS output file :Data: ts Timestep object containing coordinates of current frame :Methods: ``len(out)`` return number of frames in out ``for ts in out:`` iterate through trajectory Note ---- :class:`GMSReader` can read both uncompressed (``foo.out``) and compressed (``foo.out.bz2`` or ``foo.out.gz``) files; decompression is handled on the fly .. versionchanged:: 0.11.0 Frames now 0-based instead of 1-based. Added `dt` and `time_offset` keywords (passed to :class:`Timestep`). """format="GMS"# these are assumed!units={'time':'ps','length':'Angstrom'}def__init__(self,outfilename,**kwargs):super(GMSReader,self).__init__(outfilename,**kwargs)# the filename has been parsed to be either b(g)zipped or notself.outfile=util.anyopen(self.filename)# note that, like for xtc and trr files, _n_atoms and _n_frames are used quasi-private variables# to prevent the properties being recalculated# this is because there is no indexing so the way it measures the number of frames is to read the whole file!self._n_atoms=Noneself._n_frames=Noneself._runtyp=Noneself.ts=self._Timestep(0)# need for properties initial calculations# update runtyp propertyself.runtypifnotself.runtypin['optimize','surface']:raiseAttributeError('Wrong RUNTYP= '+self.runtyp)self.ts=self._Timestep(self.n_atoms,**self._ts_kwargs)# update n_frames propertyself.n_frames# Read in the first timestepself._read_next_timestep()@propertydefruntyp(self):"""RUNTYP property of the GAMESS run"""ifself._runtypisnotNone:# return cached valuereturnself._runtyptry:self._runtyp=self._determine_runtyp()exceptIOError:return0else:returnself._runtypdef_determine_runtyp(self):withutil.openany(self.filename)asout:forlineinout:m=re.match(r'^.*RUNTYP=([A-Z]+)\s+.*',line)ifmisnotNone:res=m.group(1).lower()breakreturnres@propertydefn_atoms(self):"""number of atoms in a frame"""ifself._n_atomsisnotNone:# return cached valuereturnself._n_atomstry:self._n_atoms=self._read_out_natoms()exceptIOError:return0else:returnself._n_atomsdef_read_out_natoms(self):withutil.openany(self.filename)asout:forlineinout:m=re.match(r'\s*TOTAL NUMBER OF ATOMS\s*=\s*([0-9]+)\s*',line)ifmisnotNone:res=int(m.group(1))breakreturnres@propertydefn_frames(self):ifself._n_framesisnotNone:# return cached valuereturnself._n_framestry:self._n_frames=self._read_out_n_frames()exceptIOError:return0else:returnself._n_framesdef_read_out_n_frames(self):ifself.runtyp=='optimize':trigger=re.compile(b'^.NSERCH=.*')elifself.runtyp=='surface':trigger=re.compile(b'^.COORD 1=.*')self._offsets=offsets=[]withutil.openany(self.filename,'rb')asout:line=Truewhilenotline==b'':# while not EOFline=out.readline()ifre.match(trigger,line):offsets.append(out.tell()-len(line))returnlen(offsets)def_read_frame(self,frame):self.outfile.seek(self._offsets[frame])self.ts.frame=frame-1# gets +1'd in _read_nextreturnself._read_next_timestep()def_read_next_timestep(self,ts=None):# check that the timestep object existsiftsisNone:ts=self.ts# check that the outfile object exists; if not reopen the trajectoryifself.outfileisNone:self.open_trajectory()x=[]y=[]z=[]flag=0counter=0forlineinself.outfile:ifself.runtyp=='optimize':if(flag==0)and(re.match(r'^.NSERCH=.*',line)isnotNone):flag=1continueif(flag==1)and(re.match(r'^ COORDINATES OF ALL ATOMS ARE ',\
line)isnotNone):flag=2continueif(flag==2)and(re.match(r'^\s*[-]+\s*',line)isnotNone):flag=3continueifflag==3andcounter<self.n_atoms:words=line.split()x.append(float(words[2]))y.append(float(words[3]))z.append(float(words[4]))counter+=1elifself.runtyp=='surface':if(flag==0)and(re.match(\
r'^.COORD 1=\s*([-]?[0-9]+\.[0-9]+).*',line)isnotNone):flag=1continueif(flag==1)and(re.match(\
r'^\s*HAS ENERGY VALUE\s*([-]?[0-9]+\.[0-9]+)\s*',line)isnotNone):flag=3continueifflag==3andcounter<self.n_atoms:words=line.split()x.append(float(words[1]))y.append(float(words[2]))z.append(float(words[3]))counter+=1# stop when the cursor has reached the end of that blockifcounter==self._n_atoms:ts._x[:]=x# more efficient to do it this way to avoid re-creating the numpy arraysts._y[:]=yts._z[:]=z#print ts.framets.frame+=1returntsraiseEOFErrordef_reopen(self):self.close()self.open_trajectory()defopen_trajectory(self):ifself.outfileisnotNone:raiseIOError(errno.EALREADY,'GMS file already opened',self.filename)ifnotos.path.exists(self.filename):# must check; otherwise might segmentation faultraiseIOError(errno.ENOENT,'GMS file not found',self.filename)self.outfile=util.anyopen(self.filename)# reset tsts=self.tsts.frame=-1returnself.outfile

[docs]defclose(self):"""Close out trajectory file if it was open."""ifself.outfileisNone:returnself.outfile.close()self.outfile=None