Package user_functions :: Module structure
[hide private]
[frames] | no frames]

Source Code for Module user_functions.structure

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2012 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax.                                     # 
  6  #                                                                             # 
  7  # relax is free software; you can redistribute it and/or modify               # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation; either version 2 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # relax is distributed in the hope that it will be useful,                    # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with relax; if not, write to the Free Software                        # 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """The structure user function definitions.""" 
 25   
 26  # Python module imports. 
 27  from numpy import eye 
 28  from os import sep 
 29  import wx 
 30   
 31  # relax module imports. 
 32  import generic_fns.structure.geometric 
 33  import generic_fns.structure.main 
 34  from graphics import WIZARD_IMAGE_PATH 
 35  from user_functions.data import Uf_info; uf_info = Uf_info() 
 36  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
 37  from user_functions.objects import Desc_container 
 38   
 39   
 40  # The user function class. 
 41  uf_class = uf_info.add_class('structure') 
 42  uf_class.title = "Class containing the structural related functions." 
 43  uf_class.menu_text = "&structure" 
 44  uf_class.gui_icon = "relax.structure" 
 45   
 46   
 47  # The structure.add_atom user function. 
 48  uf = uf_info.add_uf('structure.add_atom') 
 49  uf.title = "Add an atom." 
 50  uf.title_short = "Atom creation." 
 51  uf.add_keyarg( 
 52      name = "atom_name", 
 53      py_type = "str", 
 54      desc_short = "atom name", 
 55      desc = "The atom name." 
 56  ) 
 57  uf.add_keyarg( 
 58      name = "res_name", 
 59      py_type = "str", 
 60      desc_short = "residue name", 
 61      desc = "The residue name." 
 62  ) 
 63  uf.add_keyarg( 
 64      name = "res_num", 
 65      py_type = "int", 
 66      min = -10000, 
 67      max = 10000, 
 68      desc_short = "residue number", 
 69      desc = "The residue number." 
 70  ) 
 71  uf.add_keyarg( 
 72      name = "pos", 
 73      default = [None, None, None], 
 74      py_type = "float_array", 
 75      dim = 3, 
 76      desc_short = "atomic position", 
 77      desc = "The atomic coordinates." 
 78  ) 
 79  uf.add_keyarg( 
 80      name = "element", 
 81      py_type = "str", 
 82      desc_short = "element", 
 83      desc = "The element name.", 
 84      wiz_element_type = "combo", 
 85      wiz_combo_choices = ["N", "C", "H", "O", "P"], 
 86      can_be_none = True 
 87  ) 
 88  uf.add_keyarg( 
 89      name = "atom_num", 
 90      py_type = "int", 
 91      desc_short = "atom number", 
 92      desc = "The optional atom number.", 
 93      can_be_none = True 
 94  ) 
 95  uf.add_keyarg( 
 96      name = "chain_id", 
 97      py_type = "str", 
 98      desc_short = "optional chain ID", 
 99      desc = "The optional chain ID string.", 
100      can_be_none = True 
101  ) 
102  uf.add_keyarg( 
103      name = "segment_id", 
104      py_type = "str", 
105      desc_short = "optional segment ID", 
106      desc = "The optional segment ID string.", 
107      can_be_none = True 
108  ) 
109  uf.add_keyarg( 
110      name = "pdb_record", 
111      py_type = "str", 
112      desc_short = "optional PDB record name", 
113      desc = "The optional PDB record name, e.g. 'ATOM' or 'HETATM'.", 
114      can_be_none = True 
115  ) 
116  # Description. 
117  uf.desc.append(Desc_container()) 
118  uf.desc[-1].add_paragraph("This allows atoms to be added to the internal structural object.") 
119  uf.backend = generic_fns.structure.main.add_atom 
120  uf.menu_text = "&add_atom" 
121  uf.gui_icon = "oxygen.actions.list-add-relax-blue" 
122  uf.wizard_size = (800, 600) 
123  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
124   
125   
126  # The structure.connect_atom user function. 
127  uf = uf_info.add_uf('structure.connect_atom') 
128  uf.title = "Connect two atoms." 
129  uf.title_short = "Atom connection." 
130  uf.add_keyarg( 
131      name = "index1", 
132      py_type = "int", 
133      max = 10000, 
134      desc_short = "index 1", 
135      desc = "The global index of the first atom." 
136  ) 
137  uf.add_keyarg( 
138      name = "index2", 
139      py_type = "int", 
140      max = 10000, 
141      desc_short = "index 2", 
142      desc = "The global index of the second atom." 
143  ) 
144  # Description. 
145  uf.desc.append(Desc_container()) 
146  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.") 
147  uf.backend = generic_fns.structure.main.connect_atom 
148  uf.menu_text = "co&nnect_atom" 
149  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
150   
151   
152  # The structure.create_diff_tensor_pdb user function. 
153  uf = uf_info.add_uf('structure.create_diff_tensor_pdb') 
154  uf.title = "Create a PDB file to represent the diffusion tensor." 
155  uf.title_short = "Diffusion tensor PDB file creation." 
156  uf.add_keyarg( 
157      name = "scale", 
158      default = 1.8e-6, 
159      py_type = "num", 
160      desc_short = "scaling factor", 
161      desc = "Value for scaling the diffusion rates." 
162  ) 
163  uf.add_keyarg( 
164      name = "file", 
165      default = "tensor.pdb", 
166      py_type = "str", 
167      arg_type = "file sel", 
168      desc_short = "file name", 
169      desc = "The name of the PDB file.", 
170      wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB", 
171      wiz_filesel_style = wx.FD_SAVE 
172  ) 
173  uf.add_keyarg( 
174      name = "dir", 
175      py_type = "str", 
176      arg_type = "dir", 
177      desc_short = "directory name", 
178      desc = "The directory to place the file into.", 
179      can_be_none = True 
180  ) 
181  uf.add_keyarg( 
182      name = "force", 
183      default = False, 
184      py_type = "bool", 
185      desc_short = "force flag", 
186      desc = "A flag which, if set to True, will overwrite the any pre-existing file." 
187  ) 
188  # Description. 
189  uf.desc.append(Desc_container()) 
190  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.") 
191  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.") 
192  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.") 
193  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.") 
194  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:") 
195  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.") 
196  table.add_headings(["tm (ns)", "Diso (s^-1)", "Radius (Angstrom)"]) 
197  table.add_row(["1", "1.67e8", "300"]) 
198  table.add_row(["3", "5.56e7", "100"]) 
199  table.add_row(["10", "1.67e7", "30"]) 
200  table.add_row(["30", "5.56e6", "10"]) 
201  uf.desc[-1].add_table(table.label) 
202  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.") 
203  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.") 
204  uf.backend = generic_fns.structure.geometric.create_diff_tensor_pdb 
205  uf.menu_text = "&create_diff_tensor_pdb" 
206  uf.gui_icon = "oxygen.actions.list-add-relax-blue" 
207  uf.wizard_height_desc = 450 
208  uf.wizard_size = (1000, 750) 
209  uf.wizard_apply_button = False 
210  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'create_diff_tensor_pdb.png' 
211   
212   
213  # The structure.create_vector_dist user function. 
214  uf = uf_info.add_uf('structure.create_vector_dist') 
215  uf.title = "Create a PDB file representation of the distribution of XH bond vectors." 
216  uf.title_short = "XH vector distribution PDB representation." 
217  uf.add_keyarg( 
218      name = "length", 
219      default = 2e-9, 
220      py_type = "num", 
221      desc_short = "vector length", 
222      desc = "The length of the vectors in the PDB representation (meters)." 
223  ) 
224  uf.add_keyarg( 
225      name = "file", 
226      default = "XH_dist.pdb", 
227      py_type = "str", 
228      arg_type = "file sel", 
229      desc_short = "file name", 
230      desc = "The name of the PDB file.", 
231      wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB", 
232      wiz_filesel_style = wx.FD_SAVE 
233  ) 
234  uf.add_keyarg( 
235      name = "dir", 
236      py_type = "str", 
237      arg_type = "dir", 
238      desc_short = "directory name", 
239      desc = "The directory to place the file into.", 
240      can_be_none = True 
241  ) 
242  uf.add_keyarg( 
243      name = "symmetry", 
244      default = True, 
245      py_type = "bool", 
246      desc_short = "symmetry flag", 
247      desc = "A flag which if True will create a second chain with reversed XH bond orientations." 
248  ) 
249  uf.add_keyarg( 
250      name = "force", 
251      default = False, 
252      py_type = "bool", 
253      desc_short = "force flag", 
254      desc = "A flag which if True will overwrite the file if it already exists." 
255  ) 
256  # Description. 
257  uf.desc.append(Desc_container()) 
258  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.") 
259  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.") 
260  uf.backend = generic_fns.structure.geometric.create_vector_dist 
261  uf.menu_text = "cr&eate_vector_dist" 
262  uf.gui_icon = "oxygen.actions.list-add-relax-blue" 
263  uf.wizard_height_desc = 400 
264  uf.wizard_size = (900, 700) 
265  uf.wizard_apply_button = False 
266  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'create_vector_dist.png' 
267   
268   
269  # The structure.get_pos user function. 
270  uf = uf_info.add_uf('structure.get_pos') 
271  uf.title = "Extract the atomic positions from the loaded structures for the given spins." 
272  uf.title_short = "Atomic position extraction." 
273  uf.add_keyarg( 
274      name = "spin_id", 
275      py_type = "str", 
276      desc_short = "spin ID string", 
277      desc = "The spin identification string.", 
278      can_be_none = True 
279  ) 
280  uf.add_keyarg( 
281      name = "ave_pos", 
282      default = True, 
283      py_type = "bool", 
284      desc_short = "average position flag", 
285      desc = "A flag specifying if the position of the atom is to be averaged across models." 
286  ) 
287  # Description. 
288  uf.desc.append(Desc_container()) 
289  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.") 
290  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.") 
291  # Prompt examples. 
292  uf.desc.append(Desc_container("Prompt examples")) 
293  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:") 
294  uf.desc[-1].add_prompt("relax> structure.read_pdb('1F3Y.pdb')") 
295  uf.desc[-1].add_prompt("relax> structure.get_pos(spin_id='@N')") 
296  uf.backend = generic_fns.structure.main.get_pos 
297  uf.menu_text = "&get_pos" 
298  uf.wizard_height_desc = 300 
299  uf.wizard_size = (800, 600) 
300  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
301   
302   
303  # The structure.delete user function. 
304  uf = uf_info.add_uf('structure.delete') 
305  uf.title = "Delete all structural information." 
306  uf.title_short = "Structure deletion." 
307  # Description. 
308  uf.desc.append(Desc_container()) 
309  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.") 
310  # Prompt examples. 
311  uf.desc.append(Desc_container("Prompt examples")) 
312  uf.desc[-1].add_paragraph("Simply type:") 
313  uf.desc[-1].add_prompt("relax> structure.delete()") 
314  uf.backend = generic_fns.structure.main.delete 
315  uf.menu_text = "&delete" 
316  uf.gui_icon = "oxygen.actions.list-remove" 
317  uf.wizard_size = (600, 400) 
318  uf.wizard_apply_button = False 
319  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
320   
321   
322  # The structure.displacement user function. 
323  uf = uf_info.add_uf('structure.displacement') 
324  uf.title = "Determine the rotational and translational displacement between a set of models." 
325  uf.title_short = "Rotational and translational displacement." 
326  uf.add_keyarg( 
327      name = "model_from", 
328      py_type = "int", 
329      desc_short = "model from", 
330      desc = "The optional model number for the starting position of the displacement.", 
331      can_be_none = True 
332  ) 
333  uf.add_keyarg( 
334      name = "model_to", 
335      py_type = "int", 
336      desc_short = "model to", 
337      desc = "The optional model number for the ending position of the displacement.", 
338      can_be_none = True 
339  ) 
340  uf.add_keyarg( 
341      name = "atom_id", 
342      py_type = "str", 
343      desc_short = "atom identification string", 
344      desc = "The atom identification string.", 
345      can_be_none = True 
346  ) 
347  uf.add_keyarg( 
348      name = "centroid", 
349      py_type = "float_array", 
350      desc_short = "centroid position", 
351      desc = "The alternative position of the centroid.", 
352      can_be_none = True 
353  ) 
354  # Description. 
355  uf.desc.append(Desc_container()) 
356  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.") 
357  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.") 
358  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.") 
359  # Prompt examples. 
360  uf.desc.append(Desc_container("Prompt examples")) 
361  uf.desc[-1].add_paragraph("To determine the rotational and translational displacements between all sets of models, type:") 
362  uf.desc[-1].add_prompt("relax> structure.displacement()") 
363  uf.desc[-1].add_paragraph("To determine the displacement from model 5 to all other models, type:") 
364  uf.desc[-1].add_prompt("relax> structure.displacement(model_from=5)") 
365  uf.desc[-1].add_paragraph("To determine the displacement of all models to model 5, type:") 
366  uf.desc[-1].add_prompt("relax> structure.displacement(model_to=5)") 
367  uf.desc[-1].add_paragraph("To determine the displacement of model 2 to model 3, type one of:") 
368  uf.desc[-1].add_prompt("relax> structure.displacement(2, 3)") 
369  uf.desc[-1].add_prompt("relax> structure.displacement(model_from=2, model_to=3)") 
370  uf.backend = generic_fns.structure.main.displacement 
371  uf.menu_text = "displace&ment" 
372  uf.wizard_height_desc = 400 
373  uf.wizard_size = (900, 700) 
374  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
375   
376   
377  # The structure.find_pivot user function. 
378  uf = uf_info.add_uf('structure.find_pivot') 
379  uf.title = "Find the pivot point of the motion of a set of structures." 
380  uf.title_short = "Pivot search." 
381  uf.add_keyarg( 
382      name = "models", 
383      py_type = "int_list", 
384      desc_short = "model list", 
385      desc = "The list of models to use.", 
386      can_be_none = True 
387  ) 
388  uf.add_keyarg( 
389      name = "atom_id", 
390      py_type = "str", 
391      desc_short = "atom ID string", 
392      desc = "The atom identification string.", 
393      can_be_none = True 
394  ) 
395  uf.add_keyarg( 
396      name = "init_pos", 
397      py_type = "float_array", 
398      desc_short = "initial pivot position", 
399      desc = "The initial position of the pivot.", 
400      can_be_none = True 
401  ) 
402  # Description. 
403  uf.desc.append(Desc_container()) 
404  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.") 
405  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.") 
406  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.") 
407  uf.backend = generic_fns.structure.main.find_pivot 
408  uf.menu_text = "&find_pivot" 
409  uf.wizard_height_desc = 400 
410  uf.wizard_size = (900, 700) 
411  uf.wizard_apply_button = False 
412  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
413   
414   
415  # The structure.load_spins user function. 
416  uf = uf_info.add_uf('structure.load_spins') 
417  uf.title = "Load spins from the structure into the relax data store." 
418  uf.title_short = "Loading spins from structure." 
419  uf.add_keyarg( 
420      name = "spin_id", 
421      py_type = "str", 
422      arg_type = "spin ID", 
423      desc_short = "spin ID string", 
424      desc = "The spin identification string for the selective loading of certain spins into the relax data store.", 
425      can_be_none = True 
426  ) 
427  uf.add_keyarg( 
428      name = "ave_pos", 
429      default = True, 
430      py_type = "bool", 
431      desc_short = "average position flag", 
432      desc = "A flag specifying if the position of the atom is to be averaged across models." 
433  ) 
434  # Description. 
435  uf.desc.append(Desc_container()) 
436  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).") 
437  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.") 
438  # Prompt examples. 
439  uf.desc.append(Desc_container("Prompt examples")) 
440  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:") 
441  uf.desc[-1].add_prompt("relax> structure.read_pdb('1F3Y.pdb')") 
442  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id='@N')") 
443  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):") 
444  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":A@C8\")") 
445  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":A@C2\")") 
446  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":G@C8\")") 
447  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":G@N1\")") 
448  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":C@C5\")") 
449  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":C@C6\")") 
450  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":U@N3\")") 
451  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":U@C5\")") 
452  uf.desc[-1].add_prompt("relax> structure.load_spins(spin_id=\":U@C6\")") 
453  uf.desc[-1].add_paragraph("Alternatively using some Python programming:") 
454  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\"]:") 
455  uf.desc[-1].add_prompt("relax>     structure.load_spins(spin_id=id)") 
456  uf.backend = generic_fns.structure.main.load_spins 
457  uf.menu_text = "&load_spins" 
458  uf.gui_icon = "relax.spin" 
459  uf.wizard_height_desc = 300 
460  uf.wizard_size = (800, 600) 
461  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'load_spins.png' 
462   
463   
464  # The structure.read_pdb user function. 
465  uf = uf_info.add_uf('structure.read_pdb') 
466  uf.title = "Reading structures from PDB files." 
467  uf.title_short = "PDB reading." 
468  uf.add_keyarg( 
469      name = "file", 
470      py_type = "str", 
471      arg_type = "file sel", 
472      desc_short = "file name", 
473      desc = "The name of the PDB file.", 
474      wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB", 
475      wiz_filesel_style = wx.FD_OPEN 
476  ) 
477  uf.add_keyarg( 
478      name = "dir", 
479      py_type = "str", 
480      arg_type = "dir", 
481      desc_short = "directory name", 
482      desc = "The directory where the file is located.", 
483      can_be_none = True 
484  ) 
485  uf.add_keyarg( 
486      name = "read_mol", 
487      py_type = "int_or_int_list", 
488      desc_short = "read molecule number", 
489      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.", 
490      can_be_none = True 
491  ) 
492  uf.add_keyarg( 
493      name = "set_mol_name", 
494      py_type = "str_or_str_list", 
495      desc_short = "set molecule names", 
496      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.", 
497      can_be_none = True 
498  ) 
499  uf.add_keyarg( 
500      name = "read_model", 
501      py_type = "int_or_int_list", 
502      desc_short = "read model", 
503      desc = "If set, only the given model number(s) from the PDB file will be read.  This can be a single number or list of numbers.", 
504      can_be_none = True 
505  ) 
506  uf.add_keyarg( 
507      name = "set_model_num", 
508      py_type = "int_or_int_list", 
509      desc_short = "set model numbers", 
510      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.", 
511      can_be_none = True 
512  ) 
513  uf.add_keyarg( 
514      name = "parser", 
515      default = "internal", 
516      py_type = "str", 
517      desc_short = "PDB parser", 
518      desc = "The PDB parser used to read the file.", 
519      wiz_element_type = "combo", 
520      wiz_combo_choices = ["Fast internal PDB parser", "Scientific Python PDB parser"], 
521      wiz_combo_data = ["internal", "scientific"], 
522      wiz_read_only = True 
523  ) 
524  # Description. 
525  uf.desc.append(Desc_container()) 
526  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.") 
527  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:") 
528  uf.desc[-1].add_item_list_element("'internal'", "A fast PDB parser built into relax.") 
529  uf.desc[-1].add_item_list_element("'scientific'", "The Scientific Python PDB parser.") 
530  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.") 
531  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.") 
532  uf.desc[-1].add_paragraph("Note that relax will complain if it cannot work out what to do.") 
533  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.") 
534  # Prompt examples. 
535  uf.desc.append(Desc_container("Prompt examples")) 
536  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:") 
537  uf.desc[-1].add_prompt("relax> structure.read_pdb('test.pdb', '~/pdb')") 
538  uf.desc[-1].add_prompt("relax> structure.read_pdb(file='test.pdb', dir='pdb')") 
539  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:") 
540  uf.desc[-1].add_prompt("relax> structure.read_pdb('test.pdb', read_model=10, set_mol_name='CaM', parser='scientific')") 
541  uf.desc[-1].add_prompt("relax> structure.read_pdb(file='test.pdb', read_model=10, set_mol_name='CaM', parser='scientific')") 
542  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:") 
543  uf.desc[-1].add_prompt("relax> structure.read_pdb('test.pdb', read_model=[1, 5], set_model_num=[1, 1])") 
544  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])") 
545  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:") 
546  uf.desc[-1].add_prompt("relax> structure.read_pdb('lactose_MCMM4_S1_1.pdb', set_mol_name='lactose_MCMM4_S1', set_model_num=1)") 
547  uf.desc[-1].add_prompt("relax> structure.read_pdb('lactose_MCMM4_S1_2.pdb', set_mol_name='lactose_MCMM4_S1', set_model_num=2)") 
548  uf.desc[-1].add_prompt("relax> structure.read_pdb('lactose_MCMM4_S1_3.pdb', set_mol_name='lactose_MCMM4_S1', set_model_num=3)") 
549  uf.desc[-1].add_prompt("relax> structure.read_pdb('lactose_MCMM4_S1_4.pdb', set_mol_name='lactose_MCMM4_S1', set_model_num=4)") 
550  uf.backend = generic_fns.structure.main.read_pdb 
551  uf.menu_text = "read_&pdb" 
552  uf.gui_icon = "oxygen.actions.document-open" 
553  uf.wizard_height_desc = 400 
554  uf.wizard_size = (1000, 750) 
555  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'read_pdb.png' 
556   
557   
558  # The structure.read_xyz user function. 
559  uf = uf_info.add_uf('structure.read_xyz') 
560  uf.title = "Reading structures from XYZ files." 
561  uf.title_short = "XYZ reading." 
562  uf.add_keyarg( 
563      name = "file", 
564      py_type = "str", 
565      arg_type = "file sel", 
566      desc_short = "file name", 
567      desc = "The name of the XYZ file.", 
568      wiz_filesel_wildcard = "XYZ files (*.xyz)|*.xyz;*.XYZ", 
569      wiz_filesel_style = wx.FD_OPEN 
570  ) 
571  uf.add_keyarg( 
572      name = "dir", 
573      py_type = "str", 
574      arg_type = "dir", 
575      desc_short = "directory name", 
576      desc = "The directory where the file is located.", 
577      can_be_none = True 
578  ) 
579  uf.add_keyarg( 
580      name = "read_mol", 
581      py_type = "int_or_int_list", 
582      desc_short = "read molecule number", 
583      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.", 
584      can_be_none = True 
585  ) 
586  uf.add_keyarg( 
587      name = "set_mol_name", 
588      py_type = "str_or_str_list", 
589      desc_short = "set molecule names", 
590      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.", 
591      can_be_none = True 
592  ) 
593  uf.add_keyarg( 
594      name = "read_model", 
595      py_type = "int_or_int_list", 
596      desc_short = "read model", 
597      desc = "If set, only the given model number(s) from the PDB file will be read.  This can be a single number or list of numbers.", 
598      can_be_none = True 
599  ) 
600  uf.add_keyarg( 
601      name = "set_model_num", 
602      py_type = "int_or_int_list", 
603      desc_short = "set model numbers", 
604      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.", 
605      can_be_none = True 
606  ) 
607  # Description. 
608  uf.desc.append(Desc_container()) 
609  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.") 
610  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.") 
611  uf.desc[-1].add_paragraph("Note that relax will complain if it cannot work out what to do.") 
612  # Prompt examples. 
613  uf.desc.append(Desc_container("Prompt examples")) 
614  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:") 
615  uf.desc[-1].add_prompt("relax> structure.read_xyz('test.xyz', '~/xyz')") 
616  uf.desc[-1].add_prompt("relax> structure.read_xyz(file='test.xyz', dir='xyz')") 
617  uf.desc[-1].add_paragraph("To load the 10th model from the file 'test.xyz' and naming it 'CaM', use one of:") 
618  uf.desc[-1].add_prompt("relax> structure.read_xyz('test.xyz', read_model=10, set_mol_name='CaM')") 
619  uf.desc[-1].add_prompt("relax> structure.read_xyz(file='test.xyz', read_model=10, set_mol_name='CaM')") 
620  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:") 
621  uf.desc[-1].add_prompt("relax> structure.read_xyz('test.xyz', read_model=[1, 5], set_model_num=[1, 1])") 
622  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])") 
623  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:") 
624  uf.desc[-1].add_prompt("relax> structure.read_xyz('test_1.xyz', set_mol_name='test_1', set_model_num=1)") 
625  uf.desc[-1].add_prompt("relax> structure.read_xyz('test_2.xyz', set_mol_name='test_2', set_model_num=2)") 
626  uf.desc[-1].add_prompt("relax> structure.read_xyz('test_3.xyz', set_mol_name='test_3', set_model_num=3)") 
627  uf.desc[-1].add_prompt("relax> structure.read_xyz('test_4.xyz', set_mol_name='test_4', set_model_num=4)") 
628  uf.backend = generic_fns.structure.main.read_xyz 
629  uf.menu_text = "read_&xyz" 
630  uf.gui_icon = "oxygen.actions.document-open" 
631  uf.wizard_height_desc = 400 
632  uf.wizard_size = (900, 700) 
633  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'read_xyz.png' 
634   
635   
636  # The structure.rotate user function. 
637  uf = uf_info.add_uf('structure.rotate') 
638  uf.title = "Rotate the internal structural object about the given origin by the rotation matrix." 
639  uf.title_short = "Structure rotation." 
640  uf.add_keyarg( 
641      name = "R", 
642      py_type = "float_matrix", 
643      default = eye(3), 
644      dim = (3, 3), 
645      desc_short = "rotation matrix", 
646      desc = "The rotation matrix in forwards rotation notation." 
647  ) 
648  uf.add_keyarg( 
649      name = "origin", 
650      py_type = "float_array", 
651      dim = 3, 
652      desc_short = "origin of rotation", 
653      desc = "The origin or pivot of the rotation.", 
654      can_be_none = True 
655  ) 
656  uf.add_keyarg( 
657      name = "model", 
658      py_type = "int", 
659      desc_short = "model", 
660      desc = "The model to rotate (which if not set will cause all models to be rotated).", 
661      can_be_none = True 
662  ) 
663  uf.add_keyarg( 
664      name = "atom_id", 
665      py_type = "str", 
666      desc_short = "atom ID string", 
667      desc = "The atom identification string.", 
668      can_be_none = True 
669  ) 
670  # Description. 
671  uf.desc.append(Desc_container()) 
672  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.") 
673  uf.backend = generic_fns.structure.main.rotate 
674  uf.menu_text = "&rotate" 
675  uf.wizard_height_desc = 300 
676  uf.wizard_size = (800, 600) 
677  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
678   
679   
680  # The structure.superimpose user function. 
681  uf = uf_info.add_uf('structure.superimpose') 
682  uf.title = "Superimpose a set of models of the same structure." 
683  uf.title_short = "Structural superimposition." 
684  uf.add_keyarg( 
685      name = "models", 
686      py_type = "int_list", 
687      desc_short = "model list", 
688      desc = "The list of models to superimpose.", 
689      can_be_none = True 
690  ) 
691  uf.add_keyarg( 
692      name = "method", 
693      default = "fit to mean", 
694      py_type = "str", 
695      desc_short = "superimposition method", 
696      desc = "The superimposition method.", 
697      wiz_element_type = "combo", 
698      wiz_combo_choices = ["fit to mean", "fit to first"], 
699      wiz_read_only = True 
700  ) 
701  uf.add_keyarg( 
702      name = "atom_id", 
703      py_type = "str", 
704      desc_short = "atom ID string", 
705      desc = "The atom identification string.", 
706      can_be_none = True 
707  ) 
708  uf.add_keyarg( 
709      name = "centroid", 
710      py_type = "float_array", 
711      desc_short = "centroid position", 
712      desc = "The alternative position of the centroid.", 
713      can_be_none = True 
714  ) 
715  # Description. 
716  uf.desc.append(Desc_container()) 
717  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:") 
718  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.") 
719  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.") 
720  uf.desc[-1].add_paragraph("If the list of models is not supplied, then all models will be superimposed.") 
721  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.") 
722  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.") 
723  # Prompt examples. 
724  uf.desc.append(Desc_container("Prompt examples")) 
725  uf.desc[-1].add_paragraph("To superimpose all sets of models, type one of:") 
726  uf.desc[-1].add_prompt("relax> structure.superimpose()") 
727  uf.desc[-1].add_prompt("relax> structure.superimpose(method='fit to mean')") 
728  uf.desc[-1].add_paragraph("To superimpose the models 1, 2, 3, 5 onto model 4, type:") 
729  uf.desc[-1].add_prompt("relax> structure.superimpose(models=[4, 1, 2, 3, 5], method='fit to first')") 
730  uf.desc[-1].add_paragraph("To superimpose an ensemble of protein structures using only the backbone heavy atoms, type one of:") 
731  uf.desc[-1].add_prompt("relax> structure.superimpose(atom_id='@N,C,CA,O')") 
732  uf.desc[-1].add_prompt("relax> structure.superimpose(method='fit to mean', atom_id='@N,C,CA,O')") 
733  uf.desc[-1].add_paragraph("To superimpose model 2 onto model 3 using backbone heavy atoms, type one of:") 
734  uf.desc[-1].add_prompt("relax> structure.superimpose([3, 2], 'fit to first', '@N,C,CA,O')") 
735  uf.desc[-1].add_prompt("relax> structure.superimpose(models=[3, 2], method='fit to first', atom_id='@N,C,CA,O')") 
736  uf.backend = generic_fns.structure.main.superimpose 
737  uf.menu_text = "&superimpose" 
738  uf.wizard_apply_button = False 
739  uf.wizard_height_desc = 450 
740  uf.wizard_size = (1000, 750) 
741  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
742   
743   
744  # The structure.translate user function. 
745  uf = uf_info.add_uf('structure.translate') 
746  uf.title = "Laterally displace the internal structural object by the translation vector." 
747  uf.title_short = "Structure translation." 
748  uf.add_keyarg( 
749      name = "T", 
750      py_type = "float_array", 
751      dim = 3, 
752      desc_short = "translation vector", 
753      desc = "The translation vector." 
754  ) 
755  uf.add_keyarg( 
756      name = "model", 
757      py_type = "int", 
758      desc_short = "model", 
759      desc = "The model to translate (which if not set will cause all models to be translate).", 
760      can_be_none = True 
761  ) 
762  uf.add_keyarg( 
763      name = "atom_id", 
764      py_type = "str", 
765      desc_short = "atom ID string", 
766      desc = "The atom identification string.", 
767      can_be_none = True 
768  ) 
769  # Description. 
770  uf.desc.append(Desc_container()) 
771  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.") 
772  uf.backend = generic_fns.structure.main.translate 
773  uf.menu_text = "&translate" 
774  uf.wizard_size = (750, 500) 
775  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
776   
777   
778  # The structure.vectors user function. 
779  uf = uf_info.add_uf('structure.vectors') 
780  uf.title = "Extract and store the bond vectors from the loaded structures in the spin container." 
781  uf.title_short = "Bond vector extraction." 
782  uf.add_keyarg( 
783      name = "attached", 
784      default = "H", 
785      py_type = "str", 
786      desc_short = "attached atom", 
787      desc = "The name of the second atom which attached to the spin of interest.  Regular expression is allowed, for example 'H*'." 
788  ) 
789  uf.add_keyarg( 
790      name = "spin_id", 
791      default = "@N", 
792      py_type = "str", 
793      arg_type = "spin ID", 
794      desc_short = "spin ID string", 
795      desc = "The spin identification string for restricting the loading of vectors to certain spins.", 
796      can_be_none = True 
797  ) 
798  uf.add_keyarg( 
799      name = "model", 
800      py_type = "int", 
801      desc_short = "model", 
802      desc = "The model to extract bond vectors from (which if not set will cause the vectors of all models to be extracted).", 
803      can_be_none = True 
804  ) 
805  uf.add_keyarg( 
806      name = "verbosity", 
807      default = 1, 
808      py_type = "int", 
809      desc_short = "verbosity level", 
810      desc = "The amount of information to print to screen.  Zero corresponds to minimal output while higher values increase the amount of output.  The default value is 1." 
811  ) 
812  uf.add_keyarg( 
813      name = "ave", 
814      default = True, 
815      py_type = "bool", 
816      desc_short = "average vector flag", 
817      desc = "A flag which if True will cause the bond vectors from all models to be averaged.  If vectors from only one model is extracted, this will have no effect." 
818  ) 
819  uf.add_keyarg( 
820      name = "unit", 
821      default = True, 
822      py_type = "bool", 
823      desc_short = "unit vector flag", 
824      desc = "A flag which if True will cause the unit vector to calculated rather than the full length bond vector." 
825  ) 
826  # Description. 
827  uf.desc.append(Desc_container()) 
828  uf.desc[-1].add_paragraph("For a number of types of analysis, bond vectors or unit bond vectors are required for the calculations.  This user function allows these vectors to be extracted from the loaded structures.  The bond vector will be that from the atom associated with the spin system loaded in relax to the specified attached atom.  For example if the attached atom is set to 'H' and the protein backbone amide spins 'N' are loaded, the all 'N-H' vectors will be extracted.  But if set to 'CA', all atoms named 'CA' in the structures will be searched for and all 'N-Ca' bond vectors will be extracted.") 
829  uf.desc[-1].add_paragraph("The extraction of vectors can occur in a number of ways.  For example if an NMR structure with N models is loaded or if multiple molecules, from any source, of the same compound are loaded as different models, there are three options for extracting the bond vector.  Firstly the bond vector of a single model can be extracted by setting the model number. Secondly the bond vectors from all models can be extracted if the model number is not set and the average vector flag is not set.  Thirdly, if the model number is not set and the average vector flag is set, then a single vector which is the average for all models will be calculated.") 
830  # Prompt examples. 
831  uf.desc.append(Desc_container("Prompt examples")) 
832  uf.desc[-1].add_paragraph("To extract the XH vectors of the backbone amide nitrogens where in the PDB file the backbone nitrogen is called 'N' and the attached atom is called 'H', assuming multiple types of spin have already been loaded, type one of:") 
833  uf.desc[-1].add_prompt("relax> structure.vectors(spin_id='@N')") 
834  uf.desc[-1].add_prompt("relax> structure.vectors('H', spin_id='@N')") 
835  uf.desc[-1].add_prompt("relax> structure.vectors(attached='H', spin_id='@N')") 
836  uf.desc[-1].add_paragraph("If the attached atom is called 'HN', type:") 
837  uf.desc[-1].add_prompt("relax> structure.vectors(attached='HN', spin_id='@N')") 
838  uf.desc[-1].add_paragraph("For the 'CA' spin bonded to the 'HA' proton, type:") 
839  uf.desc[-1].add_prompt("relax> structure.vectors(attached='HA', spin_id='@CA')") 
840  uf.desc[-1].add_paragraph("If you are working with RNA, you can use the residue name identifier to calculate the vectors for each residue separately.  For example to calculate the vectors for all possible spins in the bases, type:") 
841  uf.desc[-1].add_prompt("relax> structure.vectors('H2', spin_id=':A')") 
842  uf.desc[-1].add_prompt("relax> structure.vectors('H8', spin_id=':A')") 
843  uf.desc[-1].add_prompt("relax> structure.vectors('H1', spin_id=':G')") 
844  uf.desc[-1].add_prompt("relax> structure.vectors('H8', spin_id=':G')") 
845  uf.desc[-1].add_prompt("relax> structure.vectors('H5', spin_id=':C')") 
846  uf.desc[-1].add_prompt("relax> structure.vectors('H6', spin_id=':C')") 
847  uf.desc[-1].add_prompt("relax> structure.vectors('H3', spin_id=':U')") 
848  uf.desc[-1].add_prompt("relax> structure.vectors('H5', spin_id=':U')") 
849  uf.desc[-1].add_prompt("relax> structure.vectors('H6', spin_id=':U')") 
850  uf.desc[-1].add_paragraph("Alternatively, assuming the desired spins have been loaded, regular expression can be used:") 
851  uf.desc[-1].add_prompt("relax> structure.vectors('H*')") 
852  uf.backend = generic_fns.structure.main.vectors 
853  uf.menu_text = "&vectors" 
854  uf.wizard_height_desc = 400 
855  uf.wizard_size = (1000, 750) 
856  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + '2JK4.png' 
857   
858   
859  # The structure.write_pdb user function. 
860  uf = uf_info.add_uf('structure.write_pdb') 
861  uf.title = "Writing structures to a PDB file." 
862  uf.title_short = "PDB writing." 
863  uf.add_keyarg( 
864      name = "file", 
865      py_type = "str", 
866      arg_type = "file sel", 
867      desc_short = "file name", 
868      desc = "The name of the PDB file.", 
869      wiz_filesel_wildcard = "PDB files (*.pdb)|*.pdb;*.PDB", 
870      wiz_filesel_style = wx.FD_SAVE 
871  ) 
872  uf.add_keyarg( 
873      name = "dir", 
874      py_type = "str", 
875      arg_type = "dir", 
876      desc_short = "directory name", 
877      desc = "The directory where the file is located.", 
878      can_be_none = True 
879  ) 
880  uf.add_keyarg( 
881      name = "model_num", 
882      py_type = "int", 
883      desc_short = "model number", 
884      desc = "Restrict the writing of structural data to a single model in the PDB file.", 
885      can_be_none = True 
886  ) 
887  uf.add_keyarg( 
888      name = "compress_type", 
889      default = 0, 
890      py_type = "int", 
891      desc_short = "compression type", 
892      desc = "The type of compression to use when creating the file.", 
893      wiz_element_type = "combo", 
894      wiz_combo_choices = [ 
895          "No compression", 
896          "bzip2 compression", 
897          "gzip compression" 
898      ], 
899      wiz_combo_data = [ 
900          0, 
901          1, 
902          2 
903      ], 
904      wiz_read_only = True 
905  ) 
906  uf.add_keyarg( 
907      name = "force", 
908      default = False, 
909      py_type = "bool", 
910      desc_short = "force flag", 
911      desc = "A flag which if set to True will cause any pre-existing files to be overwritten." 
912  ) 
913  # Description. 
914  uf.desc.append(Desc_container()) 
915  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.") 
916  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") 
917  uf.desc[-1].add_item_list_element("0", "No compression (no file extension).") 
918  uf.desc[-1].add_item_list_element("1", "bzip2 compression ('.bz2' file extension).") 
919  uf.desc[-1].add_item_list_element("2", "gzip compression ('.gz' file extension).") 
920  # Prompt examples. 
921  uf.desc.append(Desc_container("Prompt examples")) 
922  uf.desc[-1].add_paragraph("To write all models and molecules to the PDB file 'ensemble.pdb' within the directory '~/pdb', type one of:") 
923  uf.desc[-1].add_prompt("relax> structure.write_pdb('ensemble.pdb', '~/pdb')") 
924  uf.desc[-1].add_prompt("relax> structure.write_pdb(file='ensemble.pdb', dir='pdb')") 
925  uf.desc[-1].add_paragraph("To write model number 3 into the new file 'test.pdb', use one of:") 
926  uf.desc[-1].add_prompt("relax> structure.write_pdb('test.pdb', model_num=3)") 
927  uf.desc[-1].add_prompt("relax> structure.write_pdb(file='test.pdb', model_num=3)") 
928  uf.backend = generic_fns.structure.main.write_pdb 
929  uf.menu_text = "&write_pdb" 
930  uf.gui_icon = "oxygen.actions.document-save" 
931  uf.wizard_height_desc = 400 
932  uf.wizard_size = (900, 700) 
933  uf.wizard_apply_button = False 
934  uf.wizard_image = WIZARD_IMAGE_PATH + 'structure' + sep + 'write_pdb.png' 
935