168 lines
5.0 KiB
Python
168 lines
5.0 KiB
Python
#A* -------------------------------------------------------------------
|
|
#B* This file contains source code for the PyMOL computer program
|
|
#C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific.
|
|
#D* -------------------------------------------------------------------
|
|
#E* It is unlawful to modify or remove this copyright notice.
|
|
#F* -------------------------------------------------------------------
|
|
#G* Please see the accompanying LICENSE file for further information.
|
|
#H* -------------------------------------------------------------------
|
|
#I* Additional authors of this source file include:
|
|
#-*
|
|
#-*
|
|
#-*
|
|
#Z* -------------------------------------------------------------------
|
|
|
|
import re
|
|
import copy
|
|
|
|
from chempy import io
|
|
|
|
class SDFRec:
|
|
|
|
def __init__(self,sdflist):
|
|
getkee = re.compile(r"^>\s+<([^>]*)>")
|
|
gettag = re.compile(r"^>\s+<[^>]*>\s+\((.*)\)")
|
|
ll = len(sdflist)
|
|
if ll<4:
|
|
print(" SDFRec: invalid SDF record format #1")
|
|
raise RuntimeError
|
|
self.kees = ['MOL'] # separate key list to preserve order
|
|
self.data = {}
|
|
self.ref_code = {}
|
|
self.data['MOL'] = []
|
|
mol = self.data['MOL']
|
|
l = 0
|
|
while l<ll:
|
|
mol.append(sdflist[l])
|
|
if (sdflist[l][0:6]=='M END') or (sdflist[l][0:5]=='M END'):
|
|
break;
|
|
if sdflist[l][0:1]=='>':
|
|
mol[len(mol)-1]='M END\n'
|
|
sdflist.insert(l,'M END\n')
|
|
ll=len(sdflist)
|
|
break;
|
|
l = l + 1
|
|
if l>=ll:
|
|
print(" SDFRec: invalid SDF record format #2")
|
|
raise RuntimeError
|
|
while l<ll:
|
|
if sdflist[l][0]=='>':
|
|
sl = sdflist[l]
|
|
kee_match = getkee.match(sl)
|
|
if not kee_match:
|
|
print(" SDFRec: invalid SDF record format #3")
|
|
raise RuntimeError
|
|
kee = kee_match.group(1)
|
|
self.kees.append(kee)
|
|
ref_code_match = gettag.match(sl)
|
|
if ref_code_match:
|
|
self.ref_code[kee] = ref_code_match.group(1)
|
|
else:
|
|
self.ref_code[kee] = ''
|
|
self.data[kee] = []
|
|
sd = self.data[kee]
|
|
l = l + 1
|
|
while l<ll:
|
|
if sdflist[l].strip():
|
|
sd.append(sdflist[l])
|
|
l = l + 1
|
|
else:
|
|
break;
|
|
else:
|
|
l = l + 1
|
|
|
|
def toList(self):
|
|
r = []
|
|
for k in self.kees:
|
|
if k!='MOL':
|
|
if self.ref_code[k]!='':
|
|
r.append("> <"+k+"> ("+self.ref_code[k]+")\n")
|
|
else:
|
|
r.append("> <"+k+">\n")
|
|
for a in self.data[k]:
|
|
r.append(a)
|
|
if k!='MOL':
|
|
r.append("\n")
|
|
return r
|
|
|
|
def get(self,kee):
|
|
if kee in self.data:
|
|
return self.data[kee]
|
|
else:
|
|
return None
|
|
|
|
def get_single(self,kee): # automatic stripping
|
|
if kee in self.data:
|
|
sdk = self.data[kee]
|
|
if len(sdk):
|
|
return sdk[0].strip()
|
|
else:
|
|
return None
|
|
else:
|
|
return None
|
|
|
|
def set_single(self,kee,data,ref_code=None): # adds LF
|
|
self.set(kee,[data+'\n'],ref_code)
|
|
|
|
def get_model(self):
|
|
return io.mol.fromList(self.get('MOL'))
|
|
|
|
def set_model(self,model):
|
|
self.set('MOL',io.mol.toList(model))
|
|
|
|
def set(self,kee,data,ref_code=None):
|
|
if kee not in self.kees:
|
|
self.kees.append(kee)
|
|
self.ref_code[kee]=''
|
|
if ref_code is not None:
|
|
self.ref_code[kee]=ref_code
|
|
self.data[kee] = copy.deepcopy(data)
|
|
|
|
def delete(self,kee):
|
|
self.kees.remove(kee)
|
|
del self.data[kee]
|
|
|
|
class SDF:
|
|
|
|
def __init__(*args):
|
|
mode = 'r'
|
|
if len(args)<2:
|
|
raise ValueError
|
|
self = args[0]
|
|
fname = args[1]
|
|
if len(args)==3:
|
|
mode = args[2]
|
|
self.mode = mode
|
|
self.at_eof = 0
|
|
if mode not in ('w','r','wa','pf','url'):
|
|
print(" SDF: bad mode")
|
|
return None
|
|
if mode=='pf': # pseudofile
|
|
self.file = fname
|
|
elif mode[0:1] == 'r' and '://' in fname:
|
|
# does this look like a URL? (but not a DOS path)
|
|
from urllib.request import urlopen
|
|
self.file = urlopen(fname)
|
|
else:
|
|
self.file = open(fname,mode)
|
|
|
|
def write(self,rec):
|
|
lst = rec.toList()
|
|
for a in lst:
|
|
self.file.write(a)
|
|
self.file.write('$$$$\n')
|
|
|
|
def read(self): # returns SDFRec or None at end of file
|
|
cur = []
|
|
while 1:
|
|
s = self.file.readline()
|
|
if not s:
|
|
return None
|
|
elif s[0:4]==r'$$$$':
|
|
return SDFRec(cur)
|
|
else:
|
|
cur.append(s)
|
|
|
|
def close(self):
|
|
self.file.close()
|