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 (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program 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 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """The structure user function definitions.""" 
 24   
 25  # Python module imports. 
 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  # relax module imports. 
 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  # The user function class. 
 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  # The structure.add_atom user function. 
 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  # Description. 
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  # The structure.connect_atom user function. 
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  # Description. 
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  # The structure.create_diff_tensor_pdb user function. 
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  # Description. 
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  # The structure.create_vector_dist user function. 
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  # Description. 
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  # The structure.get_pos user function. 
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  # Description. 
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  # Prompt examples. 
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  # The structure.delete user function. 
308  uf = uf_info.add_uf('structure.delete') 
309  uf.title = "Delete all structural information." 
310  uf.title_short = "Structure deletion." 
311  # Description. 
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  # Prompt examples. 
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  # The structure.displacement user function. 
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  # Description. 
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  # Prompt examples. 
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  # The structure.find_pivot user function. 
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  # Description. 
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  # The structure.load_spins user function. 
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  # Description. 
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  # Prompt examples. 
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  # The structure.read_pdb user function. 
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  # Description. 
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  # Prompt examples. 
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  # The structure.read_xyz user function. 
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  # Description. 
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  # Prompt examples. 
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  # The structure.rotate user function. 
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  # Description. 
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  # The structure.superimpose user function. 
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  # Description. 
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  # Prompt examples. 
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  # The structure.translate user function. 
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  # Description. 
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  # The structure.write_pdb user function. 
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  # Description. 
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  # Prompt examples. 
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