1
2
3
4
5 import CIF
6 import Structure
7 import StructureBuilder
8 from ConsoleOutput import warning
9
11 try:
12 v = table.get_value(column, row)
13 if v in ('', '?', '.'):
14 return False
15 m[key] = str(v)
16 return True
17 except (IndexError, KeyError):
18 return False
19 return False
20
22 try:
23 v = table.get_value(column, row)
24 if v in ('', '?', '.'):
25 return False
26 m[key] = CIF.makeNumber(v)
27 return True
28 except (IndexError, KeyError, ValueError):
29 return False
30
32 """Builds a new Structure object by loading a CIF file.
33 """
34
36
37 cif_file = CIF.CIFFile()
38 cif_file.load_file(filobj)
39 if len(cif_file.data_blocks) != 1:
40 warning("read_start: only single-structure CIF files supported")
41 self.halt = True
42 return
43 self.cif = cif_file.data_blocks[0]
44 self.get_cell_parameters()
45 self.atom_site_name_map = {}
46
48 """Read unit information form various tags and compute
49 the fractional-to-Cartesian conversion matrix.
50 """
51 a = CIF.makeNumber(self.cif.tags["cell_length_a"])
52 b = CIF.makeNumber(self.cif.tags["cell_length_b"])
53 c = CIF.makeNumber(self.cif.tags["cell_length_c"])
54 alpha_degrees = CIF.makeNumber(self.cif.tags["cell_angle_alpha"])
55 beta_degrees = CIF.makeNumber(self.cif.tags["cell_angle_beta"])
56 gamma_degrees = CIF.makeNumber(self.cif.tags["cell_angle_gamma"])
57 z = self.cif.tags["cell_formula_units_z"]
58 space_group = self.cif.tags.get("symmetry_space_group_name_h-m", None)
59 unit_cell = {
60 "length_a": a,
61 "length_b": b,
62 "length_c": c,
63 "angle_alpha": alpha_degrees,
64 "angle_beta": beta_degrees,
65 "angle_gamma": gamma_degrees,
66 "z": z,
67 "space_group": space_group
68 }
69 self.load_unit_cell(unit_cell)
70
71
72
73
74
75 import math
76 alpha = math.radians(alpha_degrees)
77 cosa = math.cos(alpha)
78 sina = math.sin(alpha)
79 beta = math.radians(beta_degrees)
80 cosb = math.cos(beta)
81 sinb = math.sin(beta)
82 gamma = math.radians(gamma_degrees)
83 cosg = math.cos(gamma)
84 sing = math.sin(gamma)
85 V = a * b * c * math.sqrt(1 - cosa * cosa - cosb * cosb
86 - cosg * cosg + 2 * cosa * cosb * cosg)
87 self.xform = [
88 [ a, b * cosg, c * cosb ],
89 [ 0, b * sing, c * (cosa - cosb * cosg) / sing ],
90 [ 0, 0, V / (a * b * sing) ],
91 ]
92
94 """Read atom information form the atom_site section.
95 """
96 for t in self.cif.tables:
97 if "atom_site_label" in t.columns:
98 table = t
99 break
100 else:
101 warning("read_atoms: no atom_site section found")
102 self.halt = True
103 return
104
105 for i in range(len(table.rows)):
106 atm_map = {
107 "res_name": self.cif.name,
108 "fragment_id": "1",
109 "chain_id": " ",
110 }
111 add_string(atm_map, "name", table, "atom_site_label", i)
112 add_string(atm_map, "element", table, "atom_site_type_symbol", i)
113 add_number(atm_map, "fractx", table, "atom_site_fract_x", i)
114 add_number(atm_map, "fracty", table, "atom_site_fract_y", i)
115 add_number(atm_map, "fractz", table, "atom_site_fract_z", i)
116 add_number(atm_map, "temp_factor",
117 table, "atom_site_U_iso_or_equiv", i)
118 add_number(atm_map, "occupancy", table, "atom_site_occupancy", i)
119 try:
120 fx = atm_map["fractx"]
121 fy = atm_map["fracty"]
122 fz = atm_map["fractz"]
123 except KeyError:
124 warning("read_atoms: missing coordinates")
125 else:
126 fc = [ fx, fy, fz ]
127 xyz = [ 0.0, 0.0, 0.0 ]
128 for i in range(3):
129 sum = 0.0
130 for j in range(3):
131 sum += self.xform[i][j] * fc[j]
132 xyz[i] = sum
133 atm_map["x"] = xyz[0]
134 atm_map["y"] = xyz[1]
135 atm_map["z"] = xyz[2]
136 atm = self.load_atom(atm_map)
137 self.atom_site_name_map[atm_map["name"]] = atm
138
139
140
141 bond_map = {}
142 self.read_geom_bond(bond_map)
143 self.read_geom_angle(bond_map)
144 self.load_bonds(bond_map)
145
146
148 """Read bond information form the geom_bond section.
149 """
150 for t in self.cif.tables:
151 if "geom_bond_atom_site_label_1" in t.columns:
152 table = t
153 break
154 else:
155 warning("read_atoms: no geom_bond section found")
156 return
157
158 for row in range(len(table.rows)):
159 name1 = table.get_value("geom_bond_atom_site_label_1", row)
160 try:
161 atom1 = self.atom_site_name_map[name1]
162 except KeyError:
163 warning("read_atoms: bond references non-existent atom '%s'"
164 % name1)
165 continue
166 name2 = table.get_value("geom_bond_atom_site_label_2", row)
167 try:
168 atom2 = self.atom_site_name_map[name2]
169 except KeyError:
170 warning("read_atoms: bond references non-existent atom '%s'"
171 % name2)
172 continue
173
174 if id(atom1) < id(atom2):
175 bnd = (atom1, atom2)
176 else:
177 bnd = (atom2, atom1)
178 bond_map[bnd] = {}
179
181 """Read bond information form the geom_angle section.
182 """
183 for t in self.cif.tables:
184 if "geom_angle_atom_site_label_1" in t.columns:
185 table = t
186 break
187 else:
188 warning("read_atoms: no geom_angle section found")
189 return
190
191 for row in range(len(table.rows)):
192 name1 = table.get_value("geom_angle_atom_site_label_1", row)
193 atom1 = self.atom_site_name_map[name1]
194 name2 = table.get_value("geom_angle_atom_site_label_2", row)
195 atom2 = self.atom_site_name_map[name2]
196 name3 = table.get_value("geom_angle_atom_site_label_3", row)
197 atom3 = self.atom_site_name_map[name3]
198
199 if id(atom1) < id(atom2):
200 bnd = (atom1, atom2)
201 else:
202 bnd = (atom2, atom1)
203 bond_map[bnd] = {}
204
205 if id(atom2) < id(atom3):
206 bnd = (atom2, atom3)
207 else:
208 bnd = (atom3, atom2)
209 bond_map[bnd] = {}
210
214
216 """Read the PDB ID.
217 """
218 name_tags = [
219 "chemical_name_common",
220 "database_code_depnum_ccdc_archive",
221 "chemical_name_systematic",
222 ]
223 for tag in name_tags:
224 try:
225 entry_id = self.cif.tags[tag].strip()
226 except KeyError:
227 pass
228 else:
229 if entry_id != '.' and entry_id != '?':
230 self.load_structure_id(entry_id)
231 break
232
233 if __name__ == "__main__":
238 builder_test("ccd.cif")
239