forked from langner/bvparm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbvparm.py
117 lines (94 loc) · 4.22 KB
/
bvparm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import os
import sys
import urllib
bvparm_cif = os.path.dirname(os.path.realpath(__file__)) + "/bvparm2013.cif"
bvparm_cif_url = "http://www.iucr.org/__data/assets/file/0006/81087/bvparm2013.cif"
class BondValenceParameters:
loop_references = ["_valence_ref_id", "_valence_ref_reference"]
loop_parameters = [ "_valence_param_atom_1", "_valence_param_atom_1_valence",
"_valence_param_atom_2", "_valence_param_atom_2_valence",
"_valence_param_Ro", "_valence_param_B",
"_valence_param_ref_id", "_valence_param_details" ]
loop_parameter_names = ["atom1", "valence1", "atom2", "valence2", "r0", "b", "ref", "details"]
loop_parameter_types = [str, int, str, int, float, float, str, str]
def __init__(self, source=None, fallback=[bvparm_cif, bvparm_cif_url]):
self.source = source
self.fallback = fallback
self.__get_cif()
self.__parse_cif()
def __get_cif(self):
if self.source:
f = urllib.urlopen(self.source)
print "Reading parameters from %s" % self.source
else:
for source in self.fallback:
try:
f = urllib.urlopen(source)
self.source = source
print "Reading parameters from %s" % source
break
except:
print "Could not open %s" % source
self.cif = f.read()
def __parse_cif(self):
self.cif_lines = self.cif.split("\n")
for il, line in enumerate(self.cif_lines):
if line.strip() == "loop_":
next = []
for i in range(1,3):
next.append(self.cif_lines[il+i].strip())
if next == self.loop_references:
self.__extract_references(il+3, self.cif_lines[il+3])
continue
for i in range(3,9):
next.append(self.cif_lines[il+i].strip())
if next == self.loop_parameters:
self.__extract_parameters(il+9, self.cif_lines[il+9])
def __extract_references(self, il, line):
self.references = {}
while not self.cif_lines[il].strip():
il += 1
while self.cif_lines[il].strip():
line = self.cif_lines[il]
lbl = line.split()[0]
ref = " ".join(line.split()[1:])
self.references[lbl] = ref
il += 1
def __extract_parameters(self, il, line):
while not self.cif_lines[il].strip():
il += 1
self.parameters = {}
while self.cif_lines[il].strip() and not "EOF" in self.cif_lines[il]:
line = self.cif_lines[il]
columns = line.split()
names = self.loop_parameter_names
types = self.loop_parameter_types
if len(columns) == 8:
data = dict([(lbl,types[i](columns[i])) for i,lbl in enumerate(names)])
else:
data = dict([(lbl,types[i](columns[i])) for i,lbl in enumerate(names[:-1])])
data['details'] = line[line.index(columns[7]):]
if not data['atom1'] in self.parameters:
self.parameters[data['atom1']] = {}
cation = self.parameters[data['atom1']]
if not data['valence1'] in cation:
cation[data['valence1']] = {}
cvalence = cation[data['valence1']]
if not data['atom2'] in cvalence:
cvalence[data['atom2']] = {}
anion = cvalence[data['atom2']]
if not data['valence2'] in anion:
anion[data['valence2']] = []
anion[data['valence2']].append({})
avalence = anion[data['valence2']][-1]
avalence['r0'] = data['r0']
avalence['b'] = data['b']
avalence['ref'] = data['ref']
avalence['details'] = data['details']
il += 1
def __getitem__(self, cation):
return self.parameters[cation]
if __name__ == '__main__':
params = BondValenceParameters(*(sys.argv[1:]))
anions_K = sorted(params.parameters['K'][1].keys())
print "BV parameters available for K bonded to: " + ", ".join(anions_K)