Files
2026-08-03 18:42:47 +08:00

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()