1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """The structure user function definitions."""
24
25
26 from numpy import eye
27 from os import sep
28 import dep_check
29 if dep_check.wx_module:
30 from wx import FD_OPEN, FD_SAVE
31 else:
32 FD_OPEN = -1
33 FD_SAVE = -1
34
35
36 import generic_fns.structure.geometric
37 import generic_fns.structure.main
38 from graphics import WIZARD_IMAGE_PATH
39 from user_functions.data import Uf_info; uf_info = Uf_info()
40 from user_functions.data import Uf_tables; uf_tables = Uf_tables()
41 from user_functions.objects import Desc_container
42
43
44
45 uf_class = uf_info.add_class('structure')
46 uf_class.title = "Class containing the structural related functions."
47 uf_class.menu_text = "&structure"
48 uf_class.gui_icon = "relax.structure"
49
50
51
52 uf = uf_info.add_uf('structure.add_atom')
53 uf.title = "Add an atom."
54 uf.title_short = "Atom creation."
55 uf.add_keyarg(
56 name = "atom_name",
57 py_type = "str",
58 desc_short = "atom name",
59 desc = "The atom name."
60 )
61 uf.add_keyarg(
62 name = "res_name",
63 py_type = "str",
64 desc_short = "residue name",
65 desc = "The residue name."
66 )
67 uf.add_keyarg(
68 name = "res_num",
69 py_type = "int",
70 min = -10000,
71 max = 10000,
72 desc_short = "residue number",
73 desc = "The residue number."
74 )
75 uf.add_keyarg(
76 name = "pos",
77 default = [None, None, None],
78 py_type = "float_array",
79 dim = 3,
80 desc_short = "atomic position",
81 desc = "The atomic coordinates."
82 )
83 uf.add_keyarg(
84 name = "element",
85 py_type = "str",
86 desc_short = "element",
87 desc = "The element name.",
88 wiz_element_type = "combo",
89 wiz_combo_choices = ["N", "C", "H", "O", "P"],
90 can_be_none = True
91 )
92 uf.add_keyarg(
93 name = "atom_num",
94 py_type = "int",
95 desc_short = "atom number",
96 desc = "The optional atom number.",
97 can_be_none = True
98 )
99 uf.add_keyarg(
100 name = "chain_id",
101 py_type = "str",
102 desc_short = "optional chain ID",
103 desc = "The optional chain ID string.",
104 can_be_none = True
105 )
106 uf.add_keyarg(
107 name = "segment_id",
108 py_type = "str",
109 desc_short = "optional segment ID",
110 desc = "The optional segment ID string.",
111 can_be_none = True
112 )
113 uf.add_keyarg(
114 name = "pdb_record",
115 py_type = "str",
116 desc_short = "optional PDB record name",
117 desc = "The optional PDB record name, e.g. 'ATOM' or 'HETATM'.",
118 can_be_none = True
119 )
120
121 uf.desc.append(Desc_container())
122 uf.desc[-1].add_paragraph("This allows atoms to be added to the internal structural object.")
123 uf.backend = generic_fns.structure.main.add_atom
124 uf.menu_text = "&add_atom"
125 uf.gui_icon = "oxygen.actions.list-add-relax-blue"
126 uf.wizard_size = (800, 600)
127 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
128
129
130
131 uf = uf_info.add_uf('structure.connect_atom')
132 uf.title = "Connect two atoms."
133 uf.title_short = "Atom connection."
134 uf.add_keyarg(
135 name = "index1",
136 py_type = "int",
137 max = 10000,
138 desc_short = "index 1",
139 desc = "The global index of the first atom."
140 )
141 uf.add_keyarg(
142 name = "index2",
143 py_type = "int",
144 max = 10000,
145 desc_short = "index 2",
146 desc = "The global index of the second atom."
147 )
148
149 uf.desc.append(Desc_container())
150 uf.desc[-1].add_paragraph("This allows atoms to be connected in the internal structural object. The global index is normally equal to the PDB atom number minus 1.")
151 uf.backend = generic_fns.structure.main.connect_atom
152 uf.menu_text = "co&nnect_atom"
153 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
154
155
156
157 uf = uf_info.add_uf('structure.create_diff_tensor_pdb')
158 uf.title = "Create a PDB file to represent the diffusion tensor."
159 uf.title_short = "Diffusion tensor PDB file creation."
160 uf.add_keyarg(
161 name = "scale",
162 default = 1.8e-6,
163 py_type = "num",
164 desc_short = "scaling factor",
165 desc = "Value for scaling the diffusion rates."
166 )
167 uf.add_keyarg(
168 name = "file",
169 default = "tensor.pdb",
170 py_type = "str",
171 arg_type = "file sel",
172 desc_short = "file name",
173 desc = "The name of the PDB file.",
174 wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB",
175 wiz_filesel_style = FD_SAVE
176 )
177 uf.add_keyarg(
178 name = "dir",
179 py_type = "str",
180 arg_type = "dir",
181 desc_short = "directory name",
182 desc = "The directory to place the file into.",
183 can_be_none = True
184 )
185 uf.add_keyarg(
186 name = "force",
187 default = False,
188 py_type = "bool",
189 desc_short = "force flag",
190 desc = "A flag which, if set to True, will overwrite the any pre-existing file."
191 )
192
193 uf.desc.append(Desc_container())
194 uf.desc[-1].add_paragraph("This creates a PDB file containing an artificial geometric structure to represent the diffusion tensor. A structure must have previously been read into relax. The diffusion tensor is represented by an ellipsoidal, spheroidal, or spherical geometric object with its origin located at the centre of mass (of the selected residues). This diffusion tensor PDB file can subsequently read into any molecular viewer.")
195 uf.desc[-1].add_paragraph("There are four different types of residue within the PDB. The centre of mass of the selected residues is represented as a single carbon atom of the residue 'COM'. The ellipsoidal geometric shape consists of numerous H atoms of the residue 'TNS'. The axes of the tensor, when defined, are presented as the residue 'AXS' and consist of carbon atoms: one at the centre of mass and one at the end of each eigenvector. Finally, if Monte Carlo simulations were run and the diffusion tensor parameters were allowed to vary then there will be multiple 'SIM' residues, one for each simulation. These are essentially the same as the 'AXS' residue, representing the axes of the simulated tensors, and they will appear as a distribution.")
196 uf.desc[-1].add_paragraph("As the Brownian rotational diffusion tensor is a measure of the rate of rotation about different axes - the larger the geometric object, the faster the diffusion of a molecule. For example the diffusion tensor of a water molecule is much larger than that of a macromolecule.")
197 uf.desc[-1].add_paragraph("The effective global correlation time experienced by an XH bond vector, not to be confused with the Lipari and Szabo parameter tau_e, will be approximately proportional to the component of the diffusion tensor parallel to it. The approximation is not exact due to the multiexponential form of the correlation function of Brownian rotational diffusion. If an XH bond vector is parallel to the longest axis of the tensor, it will be unaffected by rotations about that axis, which are the fastest rotations of the molecule, and therefore its effective global correlation time will be maximal.")
198 uf.desc[-1].add_paragraph("To set the size of the diffusion tensor within the PDB frame the unit vectors used to generate the geometric object are first multiplied by the diffusion tensor (which has the units of inverse seconds) then by the scaling factor (which has the units of second Angstroms and has the default value of 1.8e-6 s.Angstrom). Therefore the rotational diffusion rate per Angstrom is equal the inverse of the scale value (which defaults to 5.56e5 s^-1.Angstrom^-1). Using the default scaling value for spherical diffusion, the correspondence between global correlation time, Diso diffusion rate, and the radius of the sphere for a number of discrete cases will be:")
199 table = uf_tables.add_table(label="table: diff tensor PDB scaling", caption="Diffusion tensor PDB representation sizes using the default scaling for different diffusion tensors", caption_short="Diffusion tensor PDB scaling.")
200 table.add_headings(["tm (ns)", "Diso (s^-1)", "Radius (Angstrom)"])
201 table.add_row(["1", "1.67e8", "300"])
202 table.add_row(["3", "5.56e7", "100"])
203 table.add_row(["10", "1.67e7", "30"])
204 table.add_row(["30", "5.56e6", "10"])
205 uf.desc[-1].add_table(table.label)
206 uf.desc[-1].add_paragraph("The scaling value has been fixed to facilitate comparisons within or between publications, but can be changed to vary the size of the tensor geometric object if necessary. Reporting the rotational diffusion rate per Angstrom within figure legends would be useful.")
207 uf.desc[-1].add_paragraph("To create the tensor PDB representation, a number of algorithms are utilised. Firstly the centre of mass is calculated for the selected residues and is represented in the PDB by a C atom. Then the axes of the diffusion are calculated, as unit vectors scaled to the appropriate length (multiplied by the eigenvalue Dx, Dy, Dz, Dpar, Dper, or Diso as well as the scale value), and a C atom placed at the position of this vector plus the centre of mass. Finally a uniform distribution of vectors on a sphere is generated using spherical coordinates. By incrementing the polar angle using an arccos distribution, a radial array of vectors representing latitude are created while incrementing the azimuthal angle evenly creates the longitudinal vectors. These unit vectors, which are distributed within the PDB frame and are of 1 Angstrom in length, are first rotated into the diffusion frame using a rotation matrix (the spherical diffusion tensor is not rotated). Then they are multiplied by the diffusion tensor matrix to extend the vector out to the correct length, and finally multiplied by the scale value so that the vectors reasonably superimpose onto the macromolecular structure. The last set of algorithms place all this information into a PDB file. The distribution of vectors are represented by H atoms and are all connected using PDB CONECT records. Each H atom is connected to its two neighbours on the both the longitude and latitude. This creates a geometric PDB object with longitudinal and latitudinal lines.")
208 uf.backend = generic_fns.structure.geometric.create_diff_tensor_pdb
209 uf.menu_text = "&create_diff_tensor_pdb"
210 uf.gui_icon = "oxygen.actions.list-add-relax-blue"
211 uf.wizard_height_desc = 450
212 uf.wizard_size = (1000, 750)
213 uf.wizard_apply_button = False
214 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'create_diff_tensor_pdb.png'
215
216
217
218 uf = uf_info.add_uf('structure.create_vector_dist')
219 uf.title = "Create a PDB file representation of the distribution of XH bond vectors."
220 uf.title_short = "XH vector distribution PDB representation."
221 uf.add_keyarg(
222 name = "length",
223 default = 2e-9,
224 py_type = "num",
225 desc_short = "vector length",
226 desc = "The length of the vectors in the PDB representation (meters)."
227 )
228 uf.add_keyarg(
229 name = "file",
230 default = "XH_dist.pdb",
231 py_type = "str",
232 arg_type = "file sel",
233 desc_short = "file name",
234 desc = "The name of the PDB file.",
235 wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB",
236 wiz_filesel_style = FD_SAVE
237 )
238 uf.add_keyarg(
239 name = "dir",
240 py_type = "str",
241 arg_type = "dir",
242 desc_short = "directory name",
243 desc = "The directory to place the file into.",
244 can_be_none = True
245 )
246 uf.add_keyarg(
247 name = "symmetry",
248 default = True,
249 py_type = "bool",
250 desc_short = "symmetry flag",
251 desc = "A flag which if True will create a second chain with reversed XH bond orientations."
252 )
253 uf.add_keyarg(
254 name = "force",
255 default = False,
256 py_type = "bool",
257 desc_short = "force flag",
258 desc = "A flag which if True will overwrite the file if it already exists."
259 )
260
261 uf.desc.append(Desc_container())
262 uf.desc[-1].add_paragraph("This creates a PDB file containing an artificial vectors, the length of which default to 20 Angstrom. A structure must have previously been read into relax. The origin of the vector distribution is located at the centre of mass (of the selected residues). This vector distribution PDB file can subsequently be read into any molecular viewer.")
263 uf.desc[-1].add_paragraph("Because of the symmetry of the diffusion tensor reversing the orientation of the XH bond vector has no effect. Therefore by setting the symmetry flag two chains 'A' and 'B' will be added to the PDB file whereby chain 'B' is chain 'A' with the XH bonds reversed.")
264 uf.backend = generic_fns.structure.geometric.create_vector_dist
265 uf.menu_text = "cr&eate_vector_dist"
266 uf.gui_icon = "oxygen.actions.list-add-relax-blue"
267 uf.wizard_height_desc = 400
268 uf.wizard_size = (900, 700)
269 uf.wizard_apply_button = False
270 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'create_vector_dist.png'
271
272
273
274 uf = uf_info.add_uf('structure.get_pos')
275 uf.title = "Extract the atomic positions from the loaded structures for the given spins."
276 uf.title_short = "Atomic position extraction."
277 uf.add_keyarg(
278 name = "spin_id",
279 py_type = "str",
280 desc_short = "spin ID string",
281 desc = "The spin identification string.",
282 can_be_none = True
283 )
284 uf.add_keyarg(
285 name = "ave_pos",
286 default = True,
287 py_type = "bool",
288 desc_short = "average position flag",
289 desc = "A flag specifying if the position of the atom is to be averaged across models."
290 )
291
292 uf.desc.append(Desc_container())
293 uf.desc[-1].add_paragraph("This allows the atomic positions of the spins to be extracted from the loaded structures. This is automatically performed by the structure.load_spins user function, but if the sequence information is generated in other ways, this user function allows the structural information to be obtained.")
294 uf.desc[-1].add_paragraph("If averaging the atomic positions, then average position of all models will be loaded into the spin container. Otherwise the positions from all models will be loaded separately.")
295
296 uf.desc.append(Desc_container("Prompt examples"))
297 uf.desc[-1].add_paragraph("For a model-free backbone amide nitrogen analysis whereby the N spins have already been created, to obtain the backbone N positions from the file '1F3Y.pdb' (which is a single protein), type the following two user functions:")
298 uf.desc[-1].add_prompt("relax> structure.read_pdb('1F3Y.pdb')")
299 uf.desc[-1].add_prompt("relax> structure.get_pos(spin_id='@N')")
300 uf.backend = generic_fns.structure.main.get_pos
301 uf.menu_text = "&get_pos"
302 uf.wizard_height_desc = 300
303 uf.wizard_size = (800, 600)
304 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
305
306
307
308 uf = uf_info.add_uf('structure.delete')
309 uf.title = "Delete all structural information."
310 uf.title_short = "Structure deletion."
311
312 uf.desc.append(Desc_container())
313 uf.desc[-1].add_paragraph("This will delete all the structural information from the current data pipe. All spin and sequence information loaded from these structures will be preserved - this only affects the structural data.")
314
315 uf.desc.append(Desc_container("Prompt examples"))
316 uf.desc[-1].add_paragraph("Simply type:")
317 uf.desc[-1].add_prompt("relax> structure.delete()")
318 uf.backend = generic_fns.structure.main.delete
319 uf.menu_text = "&delete"
320 uf.gui_icon = "oxygen.actions.list-remove"
321 uf.wizard_size = (600, 400)
322 uf.wizard_apply_button = False
323 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
324
325
326
327 uf = uf_info.add_uf('structure.displacement')
328 uf.title = "Determine the rotational and translational displacement between a set of models."
329 uf.title_short = "Rotational and translational displacement."
330 uf.add_keyarg(
331 name = "model_from",
332 py_type = "int",
333 desc_short = "model from",
334 desc = "The optional model number for the starting position of the displacement.",
335 can_be_none = True
336 )
337 uf.add_keyarg(
338 name = "model_to",
339 py_type = "int",
340 desc_short = "model to",
341 desc = "The optional model number for the ending position of the displacement.",
342 can_be_none = True
343 )
344 uf.add_keyarg(
345 name = "atom_id",
346 py_type = "str",
347 desc_short = "atom identification string",
348 desc = "The atom identification string.",
349 can_be_none = True
350 )
351 uf.add_keyarg(
352 name = "centroid",
353 py_type = "float_array",
354 desc_short = "centroid position",
355 desc = "The alternative position of the centroid.",
356 can_be_none = True
357 )
358
359 uf.desc.append(Desc_container())
360 uf.desc[-1].add_paragraph("This user function allows the rotational and translational displacement between two models of the same structure to be calculated. The information will be printed out in various formats and held in the relax data store. This is directional, so there is a starting and ending position for each displacement. If the starting and ending models are not specified, then the displacements in all directions between all models will be calculated.")
361 uf.desc[-1].add_paragraph("The atom ID, which uses the same notation as the spin ID strings, can be used to restrict the displacement calculation to certain molecules, residues, or atoms. This is useful if studying domain motions, secondary structure rearrangements, amino acid side chain rotations, etc.")
362 uf.desc[-1].add_paragraph("By supplying the position of the centroid, an alternative position than the standard rigid body centre is used as the focal point of the motion. The allows, for example, a pivot of a rotational domain motion to be specified. This is not a formally correct algorithm, all translations will be zero, but does give an indication to the amplitude of the pivoting angle.")
363
364 uf.desc.append(Desc_container("Prompt examples"))
365 uf.desc[-1].add_paragraph("To determine the rotational and translational displacements between all sets of models, type:")
366 uf.desc[-1].add_prompt("relax> structure.displacement()")
367 uf.desc[-1].add_paragraph("To determine the displacement from model 5 to all other models, type:")
368 uf.desc[-1].add_prompt("relax> structure.displacement(model_from=5)")
369 uf.desc[-1].add_paragraph("To determine the displacement of all models to model 5, type:")
370 uf.desc[-1].add_prompt("relax> structure.displacement(model_to=5)")
371 uf.desc[-1].add_paragraph("To determine the displacement of model 2 to model 3, type one of:")
372 uf.desc[-1].add_prompt("relax> structure.displacement(2, 3)")
373 uf.desc[-1].add_prompt("relax> structure.displacement(model_from=2, model_to=3)")
374 uf.backend = generic_fns.structure.main.displacement
375 uf.menu_text = "displace&ment"
376 uf.wizard_height_desc = 400
377 uf.wizard_size = (900, 700)
378 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
379
380
381
382 uf = uf_info.add_uf('structure.find_pivot')
383 uf.title = "Find the pivot point of the motion of a set of structures."
384 uf.title_short = "Pivot search."
385 uf.add_keyarg(
386 name = "models",
387 py_type = "int_list",
388 desc_short = "model list",
389 desc = "The list of models to use.",
390 can_be_none = True
391 )
392 uf.add_keyarg(
393 name = "atom_id",
394 py_type = "str",
395 desc_short = "atom ID string",
396 desc = "The atom identification string.",
397 can_be_none = True
398 )
399 uf.add_keyarg(
400 name = "init_pos",
401 py_type = "float_array",
402 desc_short = "initial pivot position",
403 desc = "The initial position of the pivot.",
404 can_be_none = True
405 )
406
407 uf.desc.append(Desc_container())
408 uf.desc[-1].add_paragraph("This is used to find pivot point of motion between a set of structural models. If the list of models is not supplied, then all models will be used.")
409 uf.desc[-1].add_paragraph("The atom ID, which uses the same notation as the spin ID strings, can be used to restrict the search to certain molecules, residues, or atoms. For example to only use backbone heavy atoms in a protein, use the atom ID of '@N,C,CA,O', assuming those are the names of the atoms from the structural file.")
410 uf.desc[-1].add_paragraph("By supplying the position of the centroid, an alternative position than the standard rigid body centre is used as the focal point of the superimposition. The allows, for example, the superimposition about a pivot point.")
411 uf.backend = generic_fns.structure.main.find_pivot
412 uf.menu_text = "&find_pivot"
413 uf.wizard_height_desc = 400
414 uf.wizard_size = (900, 700)
415 uf.wizard_apply_button = False
416 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
417
418
419
420 uf = uf_info.add_uf('structure.load_spins')
421 uf.title = "Load spins from the structure into the relax data store."
422 uf.title_short = "Loading spins from structure."
423 uf.add_keyarg(
424 name = "spin_id",
425 py_type = "str",
426 arg_type = "spin ID",
427 desc_short = "spin ID string",
428 desc = "The spin identification string for the selective loading of certain spins into the relax data store.",
429 wiz_combo_choices = ["@N", "@C", "@H", "@O", "@P", "@NE1", "@HE1", ":A@C2", ":A@C8", ":G@N1", ":G@C8", ":C@C5", ":C@C5", ":U@N3", ":U@C5", ":U@C6"],
430 can_be_none = True
431 )
432 uf.add_keyarg(
433 name = "ave_pos",
434 default = True,
435 py_type = "bool",
436 desc_short = "average position flag",
437 desc = "A flag specifying if the position of the atom is to be averaged across models."
438 )
439
440 uf.desc.append(Desc_container())
441 uf.desc[-1].add_paragraph("This allows a sequence to be generated within the relax data store using the atomic information from the structure already associated with this data pipe. The spin ID string is used to select which molecules, which residues, and which atoms will be recognised as spin systems within relax. If the spin ID is left unspecified, then all molecules, residues, and atoms will be placed within the data store (and all atoms will be treated as spins).")
442 uf.desc[-1].add_paragraph("If averaging the atomic positions, then average position of all models will be loaded into the spin container. Otherwise the positions from all models will be loaded separately.")
443
444 uf.desc.append(Desc_container("Prompt examples"))
445 uf.desc[-1].add_paragraph("For a model-free backbone amide nitrogen analysis, to load just the backbone N sequence from the file '1F3Y.pdb' (which is a single protein), type the following two user functions:")
446 uf.desc[-1].add_prompt("relax> structure.read_pdb('1F3Y.pdb')")
447 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id='@N')")
448 uf.desc[-1].add_paragraph("For an RNA analysis of adenine C8 and C2, guanine C8 and N1, cytidine C5 and C6, and uracil N3, C5, and C6, type the following series of commands (assuming that the PDB file with this atom naming has already been read):")
449 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":A@C8\")")
450 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":A@C2\")")
451 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":G@C8\")")
452 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":G@N1\")")
453 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":C@C5\")")
454 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":C@C6\")")
455 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":U@N3\")")
456 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":U@C5\")")
457 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":U@C6\")")
458 uf.desc[-1].add_paragraph("Alternatively using some Python programming:")
459 uf.desc[-1].add_prompt("relax> for id in [\":A@C8\", \":A@C2\", \":G@C8\", \":G@N1\", \":C@C5\", \":C@C6\", \":U@N3\", \":U@C5\", \":U@C6\"]:")
460 uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=id)")
461 uf.backend = generic_fns.structure.main.load_spins
462 uf.menu_text = "&load_spins"
463 uf.gui_icon = "relax.spin"
464 uf.wizard_height_desc = 300
465 uf.wizard_size = (800, 600)
466 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'load_spins.png'
467
468
469
470 uf = uf_info.add_uf('structure.read_pdb')
471 uf.title = "Reading structures from PDB files."
472 uf.title_short = "PDB reading."
473 uf.add_keyarg(
474 name = "file",
475 py_type = "str",
476 arg_type = "file sel",
477 desc_short = "file name",
478 desc = "The name of the PDB file.",
479 wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB",
480 wiz_filesel_style = FD_OPEN
481 )
482 uf.add_keyarg(
483 name = "dir",
484 py_type = "str",
485 arg_type = "dir",
486 desc_short = "directory name",
487 desc = "The directory where the file is located.",
488 can_be_none = True
489 )
490 uf.add_keyarg(
491 name = "read_mol",
492 py_type = "int_or_int_list",
493 desc_short = "molecule number to read",
494 desc = "If set, only the given molecule(s) will be read. The molecules are determined differently by the different parsers, but are numbered consecutively from 1. If unset, then all molecules will be loaded. By providing a list of numbers such as [1, 2], multiple molecules will be read.",
495 can_be_none = True
496 )
497 uf.add_keyarg(
498 name = "set_mol_name",
499 py_type = "str_or_str_list",
500 desc_short = "setting of molecule names",
501 desc = "Set the names of the read molecules. If unset, then the molecules will be automatically labelled based on the file name or other information. This can either be a single name or a list of names.",
502 can_be_none = True
503 )
504 uf.add_keyarg(
505 name = "read_model",
506 py_type = "int_or_int_list",
507 desc_short = "model to read",
508 desc = "If set, only the given model number(s) from the PDB file will be read. Otherwise all models will be read. This can be a single number or list of numbers.",
509 can_be_none = True
510 )
511 uf.add_keyarg(
512 name = "set_model_num",
513 py_type = "int_or_int_list",
514 desc_short = "setting of model numbers",
515 desc = "Set the model numbers of the loaded molecules. If unset, then the PDB model numbers will be preserved if they exist. This can be a single number or list of numbers.",
516 can_be_none = True
517 )
518 uf.add_keyarg(
519 name = "parser",
520 default = "internal",
521 py_type = "str",
522 desc_short = "PDB parser",
523 desc = "The PDB parser used to read the file.",
524 wiz_element_type = "combo",
525 wiz_combo_choices = ["Fast internal PDB parser", "Scientific Python PDB parser"],
526 wiz_combo_data = ["internal", "scientific"],
527 wiz_read_only = True
528 )
529
530 uf.desc.append(Desc_container())
531 uf.desc[-1].add_paragraph("The reading of PDB files into relax is quite a flexible procedure allowing for both models, defined as an ensemble of the same molecule but with different atomic positions, and different molecules within the same model. One of more molecules can exist in one or more models. The flexibility allows PDB models to be converted into different molecules and different PDB files loaded as the same molecule but as different models.")
532 uf.desc[-1].add_paragraph("A few different PDB parsers can be used to read the structural data. The choice of which to use depends on whether your PDB file is supported by that reader. These are selected by setting the parser to one of:")
533 uf.desc[-1].add_item_list_element("'internal'", "A fast PDB parser built into relax.")
534 uf.desc[-1].add_item_list_element("'scientific'", "The Scientific Python PDB parser.")
535 uf.desc[-1].add_paragraph("In a PDB file, the models are specified by the MODEL PDB record. All the supported PDB readers in relax recognise this. The molecule level is quite different between the Scientific Python and internal readers. For how Scientific Python defines molecules, please see its documentation. The internal reader is far simpler as it defines molecules using the TER PDB record. In both cases, the molecules will be numbered consecutively from 1.")
536 uf.desc[-1].add_paragraph("Setting the molecule name allows the molecule within the PDB (within one model) to have a custom name. If not set, then the molecules will be named after the file name, with the molecule number appended if more than one exists.")
537 uf.desc[-1].add_paragraph("Note that relax will complain if it cannot work out what to do.")
538 uf.desc[-1].add_paragraph("This is able to handle uncompressed, bzip2 compressed files, or gzip compressed files automatically. The full file name including extension can be supplied, however, if the file cannot be found, this function will search for the file name with '.bz2' appended followed by the file name with '.gz' appended.")
539
540 uf.desc.append(Desc_container("Prompt examples"))
541 uf.desc[-1].add_paragraph("To load all structures from the PDB file 'test.pdb' in the directory '~/pdb', including all models and all molecules, type one of:")
542 uf.desc[-1].add_prompt("relax> structure.read_pdb('test.pdb', '~/pdb')")
543 uf.desc[-1].add_prompt("relax> structure.read_pdb(file='test.pdb', dir='pdb')")
544 uf.desc[-1].add_paragraph("To load the 10th model from the file 'test.pdb' using the Scientific Python PDB parser and naming it 'CaM', use one of:")
545 uf.desc[-1].add_prompt("relax> structure.read_pdb('test.pdb', read_model=10, set_mol_name='CaM', parser='scientific')")
546 uf.desc[-1].add_prompt("relax> structure.read_pdb(file='test.pdb', read_model=10, set_mol_name='CaM', parser='scientific')")
547 uf.desc[-1].add_paragraph("To load models 1 and 5 from the file 'test.pdb' as two different structures of the same model, type one of:")
548 uf.desc[-1].add_prompt("relax> structure.read_pdb('test.pdb', read_model=[1, 5], set_model_num=[1, 1])")
549 uf.desc[-1].add_prompt("relax> structure.read_pdb('test.pdb', set_mol_name=['CaM_1', 'CaM_2'], read_model=[1, 5], set_model_num=[1, 1])")
550 uf.desc[-1].add_paragraph("To load the files 'lactose_MCMM4_S1_1.pdb', 'lactose_MCMM4_S1_2.pdb', 'lactose_MCMM4_S1_3.pdb' and 'lactose_MCMM4_S1_4.pdb' as models, type the following sequence of commands:")
551 uf.desc[-1].add_prompt("relax> structure.read_pdb('lactose_MCMM4_S1_1.pdb', set_mol_name='lactose_MCMM4_S1', set_model_num=1)")
552 uf.desc[-1].add_prompt("relax> structure.read_pdb('lactose_MCMM4_S1_2.pdb', set_mol_name='lactose_MCMM4_S1', set_model_num=2)")
553 uf.desc[-1].add_prompt("relax> structure.read_pdb('lactose_MCMM4_S1_3.pdb', set_mol_name='lactose_MCMM4_S1', set_model_num=3)")
554 uf.desc[-1].add_prompt("relax> structure.read_pdb('lactose_MCMM4_S1_4.pdb', set_mol_name='lactose_MCMM4_S1', set_model_num=4)")
555 uf.backend = generic_fns.structure.main.read_pdb
556 uf.menu_text = "read_&pdb"
557 uf.gui_icon = "oxygen.actions.document-open"
558 uf.wizard_height_desc = 400
559 uf.wizard_size = (1000, 750)
560 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'read_pdb.png'
561
562
563
564 uf = uf_info.add_uf('structure.read_xyz')
565 uf.title = "Reading structures from XYZ files."
566 uf.title_short = "XYZ reading."
567 uf.add_keyarg(
568 name = "file",
569 py_type = "str",
570 arg_type = "file sel",
571 desc_short = "file name",
572 desc = "The name of the XYZ file.",
573 wiz_filesel_wildcard = "XYZ files (*.xyz)|*.xyz;*.XYZ",
574 wiz_filesel_style = FD_OPEN
575 )
576 uf.add_keyarg(
577 name = "dir",
578 py_type = "str",
579 arg_type = "dir",
580 desc_short = "directory name",
581 desc = "The directory where the file is located.",
582 can_be_none = True
583 )
584 uf.add_keyarg(
585 name = "read_mol",
586 py_type = "int_or_int_list",
587 desc_short = "molecule number to read",
588 desc = "If set, only the given molecule(s) will be read. The molecules are determined differently by the different parsers, but are numbered consecutively from 1. If unset, then all molecules will be loaded. By providing a list of numbers such as [1, 2], multiple molecules will be read.",
589 can_be_none = True
590 )
591 uf.add_keyarg(
592 name = "set_mol_name",
593 py_type = "str_or_str_list",
594 desc_short = "setting of molecule names",
595 desc = "Set the names of the read molecules. If unset, then the molecules will be automatically labelled based on the file name or other information. This can either be a single name or a list of names.",
596 can_be_none = True
597 )
598 uf.add_keyarg(
599 name = "read_model",
600 py_type = "int_or_int_list",
601 desc_short = "model to read",
602 desc = "If set, only the given model number(s) from the PDB file will be read. Otherwise all models will be read. This can be a single number or list of numbers.",
603 can_be_none = True
604 )
605 uf.add_keyarg(
606 name = "set_model_num",
607 py_type = "int_or_int_list",
608 desc_short = "setting of model numbers",
609 desc = "Set the model numbers of the loaded molecules. If unset, then the PDB model numbers will be preserved if they exist. This can be a single number or list of numbers.",
610 can_be_none = True
611 )
612
613 uf.desc.append(Desc_container())
614 uf.desc[-1].add_paragraph("The XYZ files with different models, which defined as an ensemble of the same molecule but with different atomic positions, can be read into relax. If there are several molecules in one xyz file, please separate them into different files and then load them individually. Loading different models and different molecules is controlled by specifying the molecule number read, setting the molecule names, specifying which model to read, and setting the model numbers.")
615 uf.desc[-1].add_paragraph("The setting of molecule names is used to name the molecules within the XYZ (within one model). If not set, then the molecules will be named after the file name, with the molecule number appended if more than one exists.")
616 uf.desc[-1].add_paragraph("Note that relax will complain if it cannot work out what to do.")
617
618 uf.desc.append(Desc_container("Prompt examples"))
619 uf.desc[-1].add_paragraph("To load all structures from the XYZ file 'test.xyz' in the directory '~/xyz', including all models and all molecules, type one of:")
620 uf.desc[-1].add_prompt("relax> structure.read_xyz('test.xyz', '~/xyz')")
621 uf.desc[-1].add_prompt("relax> structure.read_xyz(file='test.xyz', dir='xyz')")
622 uf.desc[-1].add_paragraph("To load the 10th model from the file 'test.xyz' and naming it 'CaM', use one of:")
623 uf.desc[-1].add_prompt("relax> structure.read_xyz('test.xyz', read_model=10, set_mol_name='CaM')")
624 uf.desc[-1].add_prompt("relax> structure.read_xyz(file='test.xyz', read_model=10, set_mol_name='CaM')")
625 uf.desc[-1].add_paragraph("To load models 1 and 5 from the file 'test.xyz' as two different structures of the same model, type one of:")
626 uf.desc[-1].add_prompt("relax> structure.read_xyz('test.xyz', read_model=[1, 5], set_model_num=[1, 1])")
627 uf.desc[-1].add_prompt("relax> structure.read_xyz('test.xyz', set_mol_name=['CaM_1', 'CaM_2'], read_model=[1, 5], set_model_num=[1, 1])")
628 uf.desc[-1].add_paragraph("To load the files 'test_1.xyz', 'test_2.xyz', 'test_3.xyz' and 'test_4.xyz' as models, type the following sequence of commands:")
629 uf.desc[-1].add_prompt("relax> structure.read_xyz('test_1.xyz', set_mol_name='test_1', set_model_num=1)")
630 uf.desc[-1].add_prompt("relax> structure.read_xyz('test_2.xyz', set_mol_name='test_2', set_model_num=2)")
631 uf.desc[-1].add_prompt("relax> structure.read_xyz('test_3.xyz', set_mol_name='test_3', set_model_num=3)")
632 uf.desc[-1].add_prompt("relax> structure.read_xyz('test_4.xyz', set_mol_name='test_4', set_model_num=4)")
633 uf.backend = generic_fns.structure.main.read_xyz
634 uf.menu_text = "read_&xyz"
635 uf.gui_icon = "oxygen.actions.document-open"
636 uf.wizard_height_desc = 400
637 uf.wizard_size = (900, 700)
638 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'read_xyz.png'
639
640
641
642 uf = uf_info.add_uf('structure.rotate')
643 uf.title = "Rotate the internal structural object about the given origin by the rotation matrix."
644 uf.title_short = "Structure rotation."
645 uf.add_keyarg(
646 name = "R",
647 py_type = "float_matrix",
648 default = eye(3),
649 dim = (3, 3),
650 desc_short = "rotation matrix",
651 desc = "The rotation matrix in forwards rotation notation."
652 )
653 uf.add_keyarg(
654 name = "origin",
655 py_type = "float_array",
656 dim = 3,
657 desc_short = "origin of rotation",
658 desc = "The origin or pivot of the rotation.",
659 can_be_none = True
660 )
661 uf.add_keyarg(
662 name = "model",
663 py_type = "int",
664 desc_short = "model",
665 desc = "The model to rotate (which if not set will cause all models to be rotated).",
666 can_be_none = True
667 )
668 uf.add_keyarg(
669 name = "atom_id",
670 py_type = "str",
671 desc_short = "atom ID string",
672 desc = "The atom identification string.",
673 can_be_none = True
674 )
675
676 uf.desc.append(Desc_container())
677 uf.desc[-1].add_paragraph("This is used to rotate the internal structural data by the given rotation matrix. If the origin is supplied, then this will act as the pivot of the rotation. Otherwise, all structural data will be rotated about the point [0, 0, 0]. The rotation can be restricted to one specific model.")
678 uf.backend = generic_fns.structure.main.rotate
679 uf.menu_text = "&rotate"
680 uf.wizard_height_desc = 300
681 uf.wizard_size = (800, 600)
682 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
683
684
685
686 uf = uf_info.add_uf('structure.superimpose')
687 uf.title = "Superimpose a set of models of the same structure."
688 uf.title_short = "Structural superimposition."
689 uf.add_keyarg(
690 name = "models",
691 py_type = "int_list",
692 desc_short = "model list",
693 desc = "The list of models to superimpose.",
694 can_be_none = True
695 )
696 uf.add_keyarg(
697 name = "method",
698 default = "fit to mean",
699 py_type = "str",
700 desc_short = "superimposition method",
701 desc = "The superimposition method.",
702 wiz_element_type = "combo",
703 wiz_combo_choices = ["fit to mean", "fit to first"],
704 wiz_read_only = True
705 )
706 uf.add_keyarg(
707 name = "atom_id",
708 py_type = "str",
709 desc_short = "atom ID string",
710 desc = "The atom identification string.",
711 can_be_none = True
712 )
713 uf.add_keyarg(
714 name = "centroid",
715 py_type = "float_array",
716 desc_short = "centroid position",
717 desc = "The alternative position of the centroid.",
718 can_be_none = True
719 )
720
721 uf.desc.append(Desc_container())
722 uf.desc[-1].add_paragraph("This allows a set of models of the same structure to be superimposed to each other. Two superimposition methods are currently supported:")
723 uf.desc[-1].add_item_list_element("'fit to mean'", "All models are fit to the mean structure. This is the default and most accurate method for an ensemble description. It is an iterative method which first calculates a mean structure and then fits each model to the mean structure using the Kabsch algorithm. This is repeated until convergence.")
724 uf.desc[-1].add_item_list_element("'fit to first'", "This is quicker but is not as accurate for an ensemble description. The Kabsch algorithm is used to rotate and translate each model to be superimposed onto the first model.")
725 uf.desc[-1].add_paragraph("If the list of models is not supplied, then all models will be superimposed.")
726 uf.desc[-1].add_paragraph("The atom ID, which uses the same notation as the spin ID strings, can be used to restrict the superimpose calculation to certain molecules, residues, or atoms. For example to only superimpose backbone heavy atoms in a protein, use the atom ID of '@N,C,CA,O', assuming those are the names of the atoms from the structural file.")
727 uf.desc[-1].add_paragraph("By supplying the position of the centroid, an alternative position than the standard rigid body centre is used as the focal point of the superimposition. The allows, for example, the superimposition about a pivot point.")
728
729 uf.desc.append(Desc_container("Prompt examples"))
730 uf.desc[-1].add_paragraph("To superimpose all sets of models, type one of:")
731 uf.desc[-1].add_prompt("relax> structure.superimpose()")
732 uf.desc[-1].add_prompt("relax> structure.superimpose(method='fit to mean')")
733 uf.desc[-1].add_paragraph("To superimpose the models 1, 2, 3, 5 onto model 4, type:")
734 uf.desc[-1].add_prompt("relax> structure.superimpose(models=[4, 1, 2, 3, 5], method='fit to first')")
735 uf.desc[-1].add_paragraph("To superimpose an ensemble of protein structures using only the backbone heavy atoms, type one of:")
736 uf.desc[-1].add_prompt("relax> structure.superimpose(atom_id='@N,C,CA,O')")
737 uf.desc[-1].add_prompt("relax> structure.superimpose(method='fit to mean', atom_id='@N,C,CA,O')")
738 uf.desc[-1].add_paragraph("To superimpose model 2 onto model 3 using backbone heavy atoms, type one of:")
739 uf.desc[-1].add_prompt("relax> structure.superimpose([3, 2], 'fit to first', '@N,C,CA,O')")
740 uf.desc[-1].add_prompt("relax> structure.superimpose(models=[3, 2], method='fit to first', atom_id='@N,C,CA,O')")
741 uf.backend = generic_fns.structure.main.superimpose
742 uf.menu_text = "&superimpose"
743 uf.wizard_apply_button = False
744 uf.wizard_height_desc = 450
745 uf.wizard_size = (1000, 750)
746 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
747
748
749
750 uf = uf_info.add_uf('structure.translate')
751 uf.title = "Laterally displace the internal structural object by the translation vector."
752 uf.title_short = "Structure translation."
753 uf.add_keyarg(
754 name = "T",
755 py_type = "float_array",
756 dim = 3,
757 desc_short = "translation vector",
758 desc = "The translation vector."
759 )
760 uf.add_keyarg(
761 name = "model",
762 py_type = "int",
763 desc_short = "model",
764 desc = "The model to translate (which if not set will cause all models to be translate).",
765 can_be_none = True
766 )
767 uf.add_keyarg(
768 name = "atom_id",
769 py_type = "str",
770 desc_short = "atom ID string",
771 desc = "The atom identification string.",
772 can_be_none = True
773 )
774
775 uf.desc.append(Desc_container())
776 uf.desc[-1].add_paragraph("This is used to translate the internal structural data by the given translation vector. The translation can be restricted to one specific model.")
777 uf.backend = generic_fns.structure.main.translate
778 uf.menu_text = "&translate"
779 uf.wizard_size = (750, 500)
780 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png'
781
782
783
784 uf = uf_info.add_uf('structure.write_pdb')
785 uf.title = "Writing structures to a PDB file."
786 uf.title_short = "PDB writing."
787 uf.add_keyarg(
788 name = "file",
789 py_type = "str",
790 arg_type = "file sel",
791 desc_short = "file name",
792 desc = "The name of the PDB file.",
793 wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB",
794 wiz_filesel_style = FD_SAVE
795 )
796 uf.add_keyarg(
797 name = "dir",
798 py_type = "str",
799 arg_type = "dir",
800 desc_short = "directory name",
801 desc = "The directory where the file is located.",
802 can_be_none = True
803 )
804 uf.add_keyarg(
805 name = "model_num",
806 py_type = "int",
807 desc_short = "model number",
808 desc = "Restrict the writing of structural data to a single model in the PDB file.",
809 can_be_none = True
810 )
811 uf.add_keyarg(
812 name = "compress_type",
813 default = 0,
814 py_type = "int",
815 desc_short = "compression type",
816 desc = "The type of compression to use when creating the file.",
817 wiz_element_type = "combo",
818 wiz_combo_choices = [
819 "No compression",
820 "bzip2 compression",
821 "gzip compression"
822 ],
823 wiz_combo_data = [
824 0,
825 1,
826 2
827 ],
828 wiz_read_only = True
829 )
830 uf.add_keyarg(
831 name = "force",
832 default = False,
833 py_type = "bool",
834 desc_short = "force flag",
835 desc = "A flag which if set to True will cause any pre-existing files to be overwritten."
836 )
837
838 uf.desc.append(Desc_container())
839 uf.desc[-1].add_paragraph("This will write all of the structural data loaded in the current data pipe to be converted to the PDB format and written to file. Specifying the model number allows single models to be output.")
840 uf.desc[-1].add_paragraph("The default behaviour of this function is to not compress the file. The compression can, however, be changed to either bzip2 or gzip compression. If the '.bz2' or '.gz' extension is not included in the file name, it will be added. This behaviour is controlled by the compression type which can be set to")
841 uf.desc[-1].add_item_list_element("0", "No compression (no file extension).")
842 uf.desc[-1].add_item_list_element("1", "bzip2 compression ('.bz2' file extension).")
843 uf.desc[-1].add_item_list_element("2", "gzip compression ('.gz' file extension).")
844
845 uf.desc.append(Desc_container("Prompt examples"))
846 uf.desc[-1].add_paragraph("To write all models and molecules to the PDB file 'ensemble.pdb' within the directory '~/pdb', type one of:")
847 uf.desc[-1].add_prompt("relax> structure.write_pdb('ensemble.pdb', '~/pdb')")
848 uf.desc[-1].add_prompt("relax> structure.write_pdb(file='ensemble.pdb', dir='pdb')")
849 uf.desc[-1].add_paragraph("To write model number 3 into the new file 'test.pdb', use one of:")
850 uf.desc[-1].add_prompt("relax> structure.write_pdb('test.pdb', model_num=3)")
851 uf.desc[-1].add_prompt("relax> structure.write_pdb(file='test.pdb', model_num=3)")
852 uf.backend = generic_fns.structure.main.write_pdb
853 uf.menu_text = "&write_pdb"
854 uf.gui_icon = "oxygen.actions.document-save"
855 uf.wizard_height_desc = 400
856 uf.wizard_size = (900, 700)
857 uf.wizard_apply_button = False
858 uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'write_pdb.png'
859