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

Source Code for Module user_functions.frame_order

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2009-2010,2012-2015,2018-2019 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 frame_order user function definitions.""" 
 24   
 25  # relax module imports. 
 26  from graphics import WIZARD_IMAGE_PATH 
 27  from lib.frame_order.variables import MODEL_DOUBLE_ROTOR, MODEL_FREE_ROTOR, MODEL_ISO_CONE, MODEL_ISO_CONE_FREE_ROTOR, MODEL_ISO_CONE_TORSIONLESS, MODEL_PSEUDO_ELLIPSE, MODEL_PSEUDO_ELLIPSE_FREE_ROTOR, MODEL_PSEUDO_ELLIPSE_TORSIONLESS, MODEL_RIGID, MODEL_ROTOR 
 28  from specific_analyses.frame_order.optimisation import count_sobol_points 
 29  from specific_analyses.frame_order.uf import decompose, distribute, sobol_setup, pdb_model, permute_axes, pivot, quad_int, ref_domain, select_model, simulate 
 30  from user_functions.data import Uf_info; uf_info = Uf_info() 
 31  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
 32  from user_functions.objects import Desc_container 
 33  from user_functions.wildcards import WILDCARD_STRUCT_PDB_ALL 
 34   
 35   
 36  # The user function class. 
 37  uf_class = uf_info.add_class('frame_order') 
 38  uf_class.title = "Class containing the user functions of the Frame Order theories." 
 39  uf_class.menu_text = "&frame_order" 
 40  uf_class.gui_icon = "relax.frame_order" 
 41   
 42   
 43  # The frame_order.count_sobol_points user function. 
 44  uf = uf_info.add_uf('frame_order.count_sobol_points') 
 45  uf.title = "Count the number of Sobol' points used for the current parameter values." 
 46  uf.title_short = "Used Sobol' point count." 
 47  # Description. 
 48  uf.desc.append(Desc_container()) 
 49  uf.desc[-1].add_paragraph("This allows the number of Sobol' integration points used during the Frame Order target function optimisation to be counted.  This uses the current parameter values to determine how many are used for the PCS calculation compared to the total number.") 
 50  uf.backend = count_sobol_points 
 51  uf.menu_text = "&count_sobol_points" 
 52  uf.gui_icon = "oxygen.categories.applications-education" 
 53  uf.wizard_size = (800, 400) 
 54  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
 55   
 56   
 57  # The frame_order.decompose user function. 
 58  uf = uf_info.add_uf('frame_order.decompose') 
 59  uf.title = "Structural representation of the individual frame order motional components." 
 60  uf.title_short = "Frame order motional components." 
 61  uf.add_keyarg( 
 62      name = "root", 
 63      default = "decomposed", 
 64      basic_types = ["str"], 
 65      desc_short = "PDB file root", 
 66      desc = "The file root for the PDB files created.  Each motional component will be represented by a different PDB file appended with '_mode1.pdb', '_mode2.pdb', '_mode3.pdb', etc.", 
 67      can_be_none = True 
 68  ) 
 69  uf.add_keyarg( 
 70      name = "dir", 
 71      arg_type = "dir", 
 72      desc_short = "directory name", 
 73      desc = "The directory where the files are to be saved.", 
 74      can_be_none = True 
 75  ) 
 76  uf.add_keyarg( 
 77      name = "atom_id", 
 78      basic_types = ["str"], 
 79      desc_short = "atom identification string", 
 80      desc = "The atom identification string to allow the representation to be applied to a subset of all atoms.", 
 81      can_be_none = True 
 82  ) 
 83  uf.add_keyarg( 
 84      name = "model", 
 85      default = 1, 
 86      min = 1, 
 87      basic_types = ["int"], 
 88      desc_short = "original structural model", 
 89      desc = "Only one model from an analysed ensemble of structures can be used for the representation, as the decomposition PDB files consist of one model per state.", 
 90      wiz_element_type = "spin" 
 91  ) 
 92  uf.add_keyarg( 
 93      name = "total", 
 94      default = None, 
 95      basic_types = ["int"], 
 96      desc_short = "total number of structures", 
 97      desc = "The total number of structures to distribute along the motional modes.  This overrides the fixed angle value.", 
 98      wiz_element_type = "spin", 
 99      can_be_none = True 
100  ) 
101  uf.add_keyarg( 
102      name = "reverse", 
103      default = False, 
104      basic_types = ["bool"], 
105      container_types = ["list"], 
106      dim = [(), (None,)], 
107      desc_short = "reversal of distributed models", 
108      desc = "Set this to reverse the ordering of the models distributed along the motional mode." 
109  ) 
110  uf.add_keyarg( 
111      name = "mirror", 
112      default = False, 
113      basic_types = ["bool"], 
114      desc_short = "mirror the distribution", 
115      desc = "Set this to have the models distributed along the motional mode shift from the negative angle to positive angle, and then return to the negative angle." 
116  ) 
117  uf.add_keyarg( 
118      name = "force", 
119      default = False, 
120      basic_types = ["bool"], 
121      desc_short = "force flag", 
122      desc = "A flag which, if set to True, will overwrite the any pre-existing file." 
123  ) 
124  # Description. 
125  uf.desc.append(Desc_container()) 
126  uf.desc[-1].add_paragraph("An alternative way to visualise the frame order motions is to decompose the motions and visualise each mode separately.  This user function will create a uniform distribution of structures shifted from the original position and rotated around the eigenvector for that motional mode.  Each distribution will be output to a PDB file appended with '_modeX.pdb', where X are the discrete motional modes ordered from largest to smallest.  The curved line of positions will extend over the full distribution of structures.") 
127  uf.backend = decompose 
128  uf.menu_text = "&decompose" 
129  uf.gui_icon = "oxygen.actions.document-save" 
130  uf.wizard_height_desc = 420 
131  uf.wizard_size = (900, 600) 
132  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
133   
134   
135  # The frame_order.distribute user function. 
136  uf = uf_info.add_uf('frame_order.distribute') 
137  uf.title = "Structural distribution of the frame order motions." 
138  uf.title_short = "Frame order motional distribution." 
139  uf.add_keyarg( 
140      name = "file", 
141      default = "distribution.pdb.gz", 
142      arg_type = "file sel read", 
143      desc_short = "distribution file", 
144      desc = "The PDB file for storing the frame order motional distribution.  The compression is determined automatically by the file extensions '*.pdb', '*.pdb.gz', and '*.pdb.bz2'.", 
145      wiz_filesel_wildcard = WILDCARD_STRUCT_PDB_ALL, 
146      wiz_filesel_preview = False 
147  ) 
148  uf.add_keyarg( 
149      name = "dir", 
150      arg_type = "dir", 
151      desc_short = "directory name", 
152      desc = "The directory where the files are to be located.", 
153      can_be_none = True 
154  ) 
155  uf.add_keyarg( 
156      name = "atom_id", 
157      basic_types = ["str"], 
158      desc_short = "atom identification string", 
159      desc = "The atom identification string to allow the distribution to be a subset of all atoms.", 
160      can_be_none = True 
161  ) 
162  uf.add_keyarg( 
163      name = "total", 
164      default = 1000, 
165      min = 1, 
166      max = 1000000, 
167      basic_types = ["int"], 
168      desc_short = "total number of structures", 
169      desc = "The total number of structures to include in the uniform distribution.", 
170      wiz_element_type = "spin" 
171  ) 
172  uf.add_keyarg( 
173      name = "max_rotations", 
174      default = 100000, 
175      min = 1, 
176      max = 100000000, 
177      basic_types = ["int"], 
178      desc_short = "maximum number of rotations", 
179      desc = "The maximum number of rotations to generate the distribution from.  This prevents the user function from executing for an infinite amount of time.  This occurs whenever a frame order amplitude parameter (cone opening angle or torsion angle) is zero so that the subset of all rotations within the motional distribution is also zero.", 
180      wiz_element_type = "spin" 
181  ) 
182  uf.add_keyarg( 
183      name = "model", 
184      default = 1, 
185      min = 1, 
186      basic_types = ["int"], 
187      desc_short = "original structural model", 
188      desc = "Only one model from an analysed ensemble of structures can be used for the distribution, as the distribution PDB file consists of one model per state.", 
189      wiz_element_type = "spin" 
190  ) 
191  uf.add_keyarg( 
192      name = "force", 
193      default = False, 
194      basic_types = ["bool"], 
195      desc_short = "force flag", 
196      desc = "A flag which, if set to True, will overwrite the any pre-existing file." 
197  ) 
198  # Description. 
199  uf.desc.append(Desc_container()) 
200  uf.desc[-1].add_paragraph("To visualise the frame order motions, this user function generates a distribution of structures randomly within the bounds of the uniform distribution of the frame order model.  The original structure is rotated randomly and only accepted for the distribution if it is within the bounds.  This is a more faithful representation of the dynamics than the pseudo-Brownian simulation user function.") 
201  uf.desc[-1].add_paragraph("Note that the RDC and PCS data does not contain information about all parts of the real distribution of structures.  Therefore the structures in this distribution only represent the components of the distribution present in the data, as modelled by the frame order models.") 
202  uf.desc[-1].add_paragraph("As the distribution consists of one model per state, if an ensemble of structures has been analysed, only one model from the ensemble can be used for the representation.") 
203  uf.backend = distribute 
204  uf.menu_text = "&distribute" 
205  uf.gui_icon = "oxygen.actions.document-save" 
206  uf.wizard_height_desc = 420 
207  uf.wizard_size = (900, 600) 
208  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
209   
210   
211  # The frame_order.pdb_model user function. 
212  uf = uf_info.add_uf('frame_order.pdb_model') 
213  uf.title = "Create a PDB file representation of the frame order dynamics." 
214  uf.title_short = "Frame order dynamics PDB representation." 
215  uf.add_keyarg( 
216      name = "ave_pos", 
217      default = "ave_pos", 
218      basic_types = ["str"], 
219      desc_short = "average structure file root", 
220      desc = "The file root of the 3D structure PDB file for the molecular structure with the moving domains shifted to the average position.", 
221      can_be_none = True 
222  ) 
223  uf.add_keyarg( 
224      name = "rep", 
225      default = "frame_order", 
226      basic_types = ["str"], 
227      desc_short = "PDB representation file root", 
228      desc = "The file root of the PDB file for the geometric object representation of the frame order dynamics.", 
229      can_be_none = True 
230  ) 
231  uf.add_keyarg( 
232      name = "dir", 
233      arg_type = "dir", 
234      desc_short = "directory name", 
235      desc = "The directory where the files are to be located.", 
236      can_be_none = True 
237  ) 
238  uf.add_keyarg( 
239      name = "compress_type", 
240      default = 0, 
241      basic_types = ["int"], 
242      desc_short = "file compression", 
243      desc = "The type of compression to use when creating the files.", 
244      wiz_element_type = "combo", 
245      wiz_combo_choices = [ 
246          "No compression", 
247          "bzip2 compression", 
248          "gzip compression" 
249      ], 
250      wiz_combo_data = [ 
251          0, 
252          1, 
253          2 
254      ], 
255      wiz_read_only = True 
256  ) 
257  uf.add_keyarg( 
258      name = "size", 
259      default = 30.0, 
260      basic_types = ["number"], 
261      desc_short = "geometric object size", 
262      desc = "The size of the geometric object in Angstroms." 
263  ) 
264  uf.add_keyarg( 
265      name = "inc", 
266      default = 36, 
267      basic_types = ["int"], 
268      desc_short = "increment number", 
269      desc = "The number of increments used to create the geometric object.", 
270      wiz_element_type = "spin" 
271  ) 
272  uf.add_keyarg( 
273      name = "model", 
274      default = 1, 
275      min = 1, 
276      basic_types = ["int"], 
277      desc_short = "structural model", 
278      desc = "Only one model from an analysed ensemble can be used for the PDB representation of the Monte Carlo simulations of the average domain position, as these consists of one model per simulation.", 
279      wiz_element_type = "spin" 
280  ) 
281  uf.add_keyarg( 
282      name = "force", 
283      default = False, 
284      basic_types = ["bool"], 
285      desc_short = "force flag", 
286      desc = "A flag which, if set to True, will overwrite the any pre-existing files." 
287  ) 
288  # Description. 
289  uf.desc.append(Desc_container()) 
290  uf.desc[-1].add_paragraph("This function creates a set of PDB files for representing the frame order cone models.  This includes a file for the average position of the molecule and a file containing a geometric representation of the frame order motions.") 
291  uf.desc[-1].add_paragraph("The three files are specified via the file root whereby the extensions '.pdb', '.pdb.gz', etc. should not be provided.  This is important for the geometric representation whereby different files are created for the positive and negative representations (due to symmetry in the NMR data, these cannot be differentiated), and for the Monte Carlo simulations.  For example if the file root is 'frame_order', the positive and negative representations will be placed in the 'frame_order_pos.pdb.gz' and 'frame_order_neg.pdb.gz' files and the Monte Carlo simulations in the 'frame_order_sim_pos.pdb.gz' and 'frame_order_sim_neg.pdb.gz' files.  For models where there is no difference in representation between the positive and negative directions, the files 'frame_order.pdb.gz' and 'frame_order_sim.pdb.gz' will be produced.") 
292  uf.desc[-1].add_paragraph("There are four different types of residue within the PDB.  The pivot point is represented as as a single carbon atom of the residue 'PIV'.  The cone consists of numerous H atoms of the residue 'CON'.  The cone axis vector is presented as the residue 'AXE' with one carbon atom positioned at the pivot and the other x Angstroms away on the cone axis (set by the geometric object size).  Finally, if Monte Carlo have been performed, there will be multiple 'MCC' residues representing the cone for each simulation, and multiple 'MCA' residues representing the multiple cone axes.") 
293  uf.desc[-1].add_paragraph("To create the diffusion in a cone PDB representation, a uniform distribution of vectors on a sphere is generated using spherical coordinates with the polar angle defined by the cone axis.  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 are all placed into the PDB file as 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 representing the filled cone.") 
294  uf.desc[-1].add_paragraph("The PDB representation of the Monte Carlo simulations consists of one model per simulation.  Therefore if an ensemble of structures has been analysed, only one model from the ensemble can be used for the representation.  This defaults to model number 1, but this can be changed.") 
295  uf.backend = pdb_model 
296  uf.menu_text = "pdb_&model" 
297  uf.gui_icon = "oxygen.actions.document-save" 
298  uf.wizard_height_desc = 400 
299  uf.wizard_size = (1000, 750) 
300  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
301   
302   
303  # The frame_order.permute_axes user function. 
304  uf = uf_info.add_uf('frame_order.permute_axes') 
305  uf.title = "Permute the axes of the motional eigenframe to switch between local minima." 
306  uf.title_short = "Eigenframe axis permutation." 
307  uf.add_keyarg( 
308      name = "permutation", 
309      default = "A", 
310      basic_types = ["str"], 
311      desc_short = "permutation", 
312      desc = "Which of the two permutations 'A' or 'B' to create.  Three permutations are possible, and 'A' and 'B' select those which are not the starting combination.", 
313      wiz_element_type = "combo", 
314      wiz_combo_choices = [ 
315          "A", 
316          "B" 
317      ], 
318      wiz_read_only = True 
319  ) 
320  # Description. 
321  uf.desc.append(Desc_container()) 
322  uf.desc[-1].add_paragraph("The isotropic and pseudo-elliptic cone frame order models consist of multiple solutions as the optimisation space contains multiple local minima.  Because of the constraint cone_theta_x <= cone_theta_y in the pseudo-ellipse model, there are exactly three local minima (out of 6 possible permutations).  However the cone_theta_x == cone_theta_y condition of the isotropic cone collapses this to two minima.  The multiple minima correspond to permutations of the motional system - the eigenframe x, y and z-axes as well as the cone opening angles cone_theta_x, cone_theta_y, and cone_sigma_max associated with these axes.  But as the mechanics of the cone angles is not identical to that of the torsion angle, only one of the three local minima is the global minimum.") 
323  uf.desc[-1].add_paragraph("When optimising the pseudo-elliptic models, specifically the '%s' and '%s' model, any of the three local minima can be found.  Convergence to the global minimum is not guaranteed.  Therefore this user function can be used to permute the motional system to jump from one local minimum to the other.  Optimisation will be required as the permuted parameters will not be exactly at the minimum." % (MODEL_PSEUDO_ELLIPSE, MODEL_PSEUDO_ELLIPSE_TORSIONLESS)) 
324  table = uf_tables.add_table(label="table: frame_order.permute_axes combinations", caption="The motional eigenframe axis permutations for the frame order models.", caption_short="The frame order axis permutations.") 
325  table.add_headings(["Condition", "Permutation name", "Cone angles", "Axes"]) 
326  table.add_row(["x < y < z", "Self", "[x, y, z]", "[x, y, z]"]) 
327  table.add_row(["         ", " A  ", "[x, z, y]", "[-z, y, x]"]) 
328  table.add_row(["         ", " B  ", "[y, z, x]", "[z, x, y]"]) 
329  table.add_row(["x < z < y", "Self", "[x, y, z]", "[x, y, z]"]) 
330  table.add_row(["         ", " A  ", "[x, z, y]", "[-z, y, x]"]) 
331  table.add_row(["         ", " B  ", "[z, y, x]", "[x, -z, y]"]) 
332  table.add_row(["z < x < y", "Self", "[x, y, z]", "[x, y, z]"]) 
333  table.add_row(["         ", " A  ", "[z, x, y]", "[y, z, x]"]) 
334  table.add_row(["         ", " B  ", "[z, y, x]", "[x, -z, y]"]) 
335  uf.desc[-1].add_table(table.label) 
336  uf.desc[-1].add_paragraph("In this table, the condition and cone angle values [x, y, z] correspond to cone_theta_x, cone_theta_y, and cone_sigma_max.") 
337  # Prompt examples. 
338  uf.desc.append(Desc_container("Prompt examples")) 
339  uf.desc[-1].add_paragraph("For combination 'A', simply type:") 
340  uf.desc[-1].add_prompt("relax> frame_order.permute_axes('A')") 
341  uf.backend = permute_axes 
342  uf.menu_text = "per&mute_axes" 
343  uf.wizard_height_desc = 580 
344  uf.wizard_size = (1000, 750) 
345  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
346   
347   
348  # The frame_order.pivot user function. 
349  uf = uf_info.add_uf('frame_order.pivot') 
350  uf.title = "Set the pivot points for the two body motion in the structural coordinate system." 
351  uf.title_short = "Pivot point setting." 
352  uf.add_keyarg( 
353      name = "pivot", 
354      basic_types = ["number"], 
355      container_types = ["number array"], 
356      dim = (3,), 
357      desc_short = "pivot point", 
358      desc = "The pivot point for the motion (e.g. the position between the 2 domains in PDB coordinates).", 
359      can_be_none = True 
360  ) 
361  uf.add_keyarg( 
362      name = "order", 
363      default = 1, 
364      min = 1, 
365      max = 100, 
366      basic_types = ["int"], 
367      desc_short = "pivot point number", 
368      desc = "The ordinal number of the pivot point.  The value of 1 is for the first pivot point, the value of 2 for the second pivot point, and so on.", 
369      wiz_element_type = "spin" 
370  ) 
371  uf.add_keyarg( 
372      name = "fix", 
373      basic_types = ["bool"], 
374      default = False, 
375      desc_short = "fixed flag", 
376      desc = "A flag specifying if the pivot point should be fixed during optimisation." 
377  ) 
378  # Description. 
379  uf.desc.append(Desc_container()) 
380  uf.desc[-1].add_paragraph("This will set the pivot points for the two domain system within the PDB coordinate system.  This is required for interpreting PCS data as well as for the generation of cone or other PDB representations of the domain motions.") 
381  uf.desc[-1].add_paragraph("This user function can also be used to change the optimisation status of an already set pivot point.  By simply providing the fixed flag and not the pivot point values, the pivot can be changed to be either fixed during optimisation or that it will be optimised.") 
382  # Prompt examples. 
383  uf.desc.append(Desc_container("Prompt examples")) 
384  uf.desc[-1].add_paragraph("To set the pivot point, type one of:") 
385  uf.desc[-1].add_prompt("relax> frame_order.pivot([12.067, 14.313, -3.2675])") 
386  uf.desc[-1].add_prompt("relax> frame_order.pivot(pivot=[12.067, 14.313, -3.2675])") 
387  uf.desc[-1].add_paragraph("To change an already set and fixed pivot point so that it can now be optimised, type:") 
388  uf.desc[-1].add_prompt("relax> frame_order.pivot(fix=False)") 
389  uf.backend = pivot 
390  uf.menu_text = "&pivot" 
391  uf.wizard_size = (900, 600) 
392  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
393   
394   
395  # The frame_order.quad_int user function. 
396  uf = uf_info.add_uf('frame_order.quad_int') 
397  uf.title = "Turn the high precision quadratic integration on or off." 
398  uf.title_short = "Quadratic integration." 
399  uf.add_keyarg( 
400      name = "flag", 
401      default = True, 
402      basic_types = ["bool"], 
403      desc_short = "flag", 
404      desc = "The flag with if True  will perform high precision numerical integration via the scipy.integrate quad(), dblquad() and tplquad() integration methods rather than the rough quasi-random numerical integration." 
405  ) 
406  # Description. 
407  uf.desc.append(Desc_container()) 
408  uf.desc[-1].add_paragraph("This allows the high precision numerical integration of the Scipy quad() and related functions to be used instead of the lower precision quasi-random Sobol' sequence integration.  This is for the optimisation of the Frame Order target functions.  The quadratic integration is orders of magnitude slower than the Sobol' sequence integration, but the precision is much higher.") 
409  uf.backend = quad_int 
410  uf.menu_text = "&quad_int" 
411  uf.gui_icon = "oxygen.actions.edit-rename" 
412  uf.wizard_size = (900, 500) 
413  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
414   
415   
416  # The frame_order.ref_domain user function. 
417  uf = uf_info.add_uf('frame_order.ref_domain') 
418  uf.title = "Set the reference non-moving domain for the 2-domain frame order theories." 
419  uf.title_short = "Reference non-moving domain set up." 
420  uf.add_keyarg( 
421      name = "ref", 
422      basic_types = ["str"], 
423      desc_short = "non-moving reference domain", 
424      desc = "The non-moving domain which will act as the frame of reference." 
425  ) 
426  # Description. 
427  uf.desc.append(Desc_container()) 
428  uf.desc[-1].add_paragraph("Prior to optimisation of the frame order model, the frame of reference non-moving domain must be specified.  This is essential for determining which spins will be used in the analysis, which will be shifted to the average position, etc.") 
429  # Prompt examples. 
430  uf.desc.append(Desc_container("Prompt examples")) 
431  uf.desc[-1].add_paragraph("To set up the isotropic cone frame order model with 'centre' domain being the frame of reference, type:") 
432  uf.desc[-1].add_prompt("relax> frame_order.ref_domain(ref='centre')") 
433  uf.backend = ref_domain 
434  uf.menu_text = "&ref_domain" 
435  uf.gui_icon = "oxygen.actions.edit-rename" 
436  uf.wizard_size = (900, 500) 
437  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
438   
439   
440  # The frame_order.select_model user function. 
441  uf = uf_info.add_uf('frame_order.select_model') 
442  uf.title = "Select and set up the Frame Order model." 
443  uf.title_short = "Model choice." 
444  uf.add_keyarg( 
445      name = "model", 
446      basic_types = ["str"], 
447      desc_short = "Frame Order model", 
448      desc = "The name of the preset Frame Order model.", 
449      wiz_element_type = "combo", 
450      wiz_combo_choices = [ 
451          "Rigid model", 
452          "Rotor model", 
453          "Free rotor model", 
454          "Torsionless isotropic cone", 
455          "Isotropic cone", 
456          "Free rotor isotropic cone", 
457          "Torsionless pseudo-ellipse", 
458          "Pseudo-ellipse", 
459          "Free rotor pseudo-ellipse", 
460          "Double rotor" 
461      ], 
462      wiz_combo_data = [ 
463          MODEL_RIGID, 
464          MODEL_ROTOR, 
465          MODEL_FREE_ROTOR, 
466          MODEL_ISO_CONE_TORSIONLESS, 
467          MODEL_ISO_CONE, 
468          MODEL_ISO_CONE_FREE_ROTOR, 
469          MODEL_PSEUDO_ELLIPSE_TORSIONLESS, 
470          MODEL_PSEUDO_ELLIPSE, 
471          MODEL_PSEUDO_ELLIPSE_FREE_ROTOR, 
472          MODEL_DOUBLE_ROTOR 
473      ], 
474      wiz_read_only = True, 
475  ) 
476  # Description. 
477  uf.desc.append(Desc_container()) 
478  uf.desc[-1].add_paragraph("Prior to optimisation, the Frame Order model should be selected.  These models consist of three parameter categories:") 
479  uf.desc[-1].add_list_element("The average domain position.  This includes the parameters ave_pos_alpha, ave_pos_beta, and ave_pos_gamma.  These Euler angles rotate the tensors from the arbitrary PDB frame of the moving domain to the average domain position.") 
480  uf.desc[-1].add_list_element("The frame order eigenframe.  This includes the parameters eigen_alpha, eigen_beta, and eigen_gamma.  These Euler angles define the major modes of motion.  The cone central axis is defined as the z-axis.  The pseudo-elliptic cone x and y-axes are defined as the x and y-axes of the eigenframe.") 
481  uf.desc[-1].add_list_element("The cone parameters.  These are defined as the tilt-torsion angles cone_theta_x, cone_theta_y, and cone_sigma_max.  The cone_theta_x and cone_theta_y parameters define the two cone opening angles of the pseudo-ellipse.  The amount of domain torsion is defined as the average domain position, plus and minus cone_sigma_max.  The isotropic cones are defined by setting cone_theta_x = cone_theta_y and converting the single parameter into a 2nd rank order parameter.") 
482  uf.desc[-1].add_paragraph("The list of available models are:") 
483  uf.desc[-1].add_item_list_element(repr(MODEL_PSEUDO_ELLIPSE), "The pseudo-elliptic cone model.  This is the full model consisting of the parameters ave_pos_alpha, ave_pos_beta, ave_pos_gamma, eigen_alpha, eigen_beta, eigen_gamma, cone_theta_x, cone_theta_y, and cone_sigma_max.") 
484  uf.desc[-1].add_item_list_element(repr(MODEL_PSEUDO_ELLIPSE_TORSIONLESS), "The pseudo-elliptic cone with the torsion angle cone_sigma_max set to zero.") 
485  uf.desc[-1].add_item_list_element(repr(MODEL_PSEUDO_ELLIPSE_FREE_ROTOR), "The pseudo-elliptic cone with no torsion angle restriction.") 
486  uf.desc[-1].add_item_list_element(repr(MODEL_ISO_CONE), "The isotropic cone model.  The cone is defined by a single order parameter s1 which is related to the single cone opening angle cone_theta_x = cone_theta_y.  Due to rotational symmetry about the cone axis, the average position alpha Euler angle ave_pos_alpha is dropped from the model.  The symmetry also collapses the eigenframe to a single z-axis defined by the parameters axis_theta and axis_phi.") 
487  uf.desc[-1].add_item_list_element(repr(MODEL_ISO_CONE_TORSIONLESS), "The isotropic cone model with the torsion angle cone_sigma_max set to zero.") 
488  uf.desc[-1].add_item_list_element(repr(MODEL_ISO_CONE_FREE_ROTOR), "The isotropic cone model with no torsion angle restriction.") 
489  uf.desc[-1].add_item_list_element(repr(MODEL_ROTOR), "The only motion is a rotation about the cone axis restricted by the torsion angle cone_sigma_max.") 
490  uf.desc[-1].add_item_list_element(repr(MODEL_RIGID), "No domain motions.") 
491  uf.desc[-1].add_item_list_element(repr(MODEL_FREE_ROTOR), "The only motion is free rotation about the cone axis.") 
492  uf.desc[-1].add_item_list_element(repr(MODEL_DOUBLE_ROTOR), "Restricted motions about two independent but orthogonal rotor axes.  The first rotation is about the y-axis and the second is about the x-axis.") 
493  # Prompt examples. 
494  uf.desc.append(Desc_container("Prompt examples")) 
495  uf.desc[-1].add_paragraph("To select the isotropic cone model, type:") 
496  uf.desc[-1].add_prompt("relax> frame_order.select_model(model='%s')" % MODEL_ISO_CONE) 
497  uf.backend = select_model 
498  uf.menu_text = "&select_model" 
499  uf.gui_icon = "oxygen.actions.list-add" 
500  uf.wizard_height_desc = 560 
501  uf.wizard_size = (1000, 750) 
502  uf.wizard_apply_button = False 
503  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
504   
505   
506  # The frame_order.simulate user function. 
507  uf = uf_info.add_uf('frame_order.simulate') 
508  uf.title = "Pseudo-Brownian dynamics simulation of the frame order motions." 
509  uf.title_short = "Frame order pseudo-Brownian dynamics simulation." 
510  uf.add_keyarg( 
511      name = "file", 
512      default = "simulation.pdb.gz", 
513      arg_type = "file sel read", 
514      desc_short = "simulation file", 
515      desc = "The PDB file for storing the frame order pseudo-Brownian dynamics simulation.  The compression is determined automatically by the file extensions '*.pdb', '*.pdb.gz', and '*.pdb.bz2'.", 
516      wiz_filesel_wildcard = WILDCARD_STRUCT_PDB_ALL, 
517      wiz_filesel_preview = False 
518  ) 
519  uf.add_keyarg( 
520      name = "dir", 
521      arg_type = "dir", 
522      desc_short = "directory name", 
523      desc = "The directory where the files are to be located.", 
524      can_be_none = True 
525  ) 
526  uf.add_keyarg( 
527      name = "step_size", 
528      default = 2.0, 
529      basic_types = ["float"], 
530      desc_short = "angle of rotation", 
531      desc = "The rotation will be of a random direction but with this fixed angle.  The value is in degrees." 
532  ) 
533  uf.add_keyarg( 
534      name = "snapshot", 
535      default = 10, 
536      min = 1, 
537      max = 1000000, 
538      basic_types = ["int"], 
539      desc_short = "number of steps per snapshot", 
540      desc = "The number of steps in the simulation when snapshots will be taken." 
541  ) 
542  uf.add_keyarg( 
543      name = "total", 
544      default = 1000, 
545      min = 1, 
546      max = 1000000, 
547      basic_types = ["int"], 
548      desc_short = "total number of snapshots", 
549      desc = "The total number of snapshots to take before stopping the simulation.", 
550      wiz_element_type = "spin" 
551  ) 
552  uf.add_keyarg( 
553      name = "model", 
554      default = 1, 
555      min = 1, 
556      basic_types = ["int"], 
557      desc_short = "original structural model", 
558      desc = "Only one model from an analysed ensemble of structures can be used for the pseudo-Brownian simulation, as the simulation and corresponding PDB file consists of one model per simulation.", 
559      wiz_element_type = "spin" 
560  ) 
561  uf.add_keyarg( 
562      name = "force", 
563      default = False, 
564      basic_types = ["bool"], 
565      desc_short = "force flag", 
566      desc = "A flag which, if set to True, will overwrite the any pre-existing file." 
567  ) 
568  # Description. 
569  uf.desc.append(Desc_container()) 
570  uf.desc[-1].add_paragraph("To visualise the frame order motions, this user function performs a type of simulation whereby structures are randomly rotated by a fixed angle within the bounds of the uniform distribution of the frame order model.  This can be thought of as a pseudo-Brownian dynamics simulation.  It is in no way a real molecular or Brownian dynamics simulation.") 
571  uf.desc[-1].add_paragraph("Note that the RDC and PCS data does not contain information about all parts of the real distribution of structures.  Therefore the snapshots in this simulation only represent the components of the distribution present in the data, as modelled by the frame order models.") 
572  uf.desc[-1].add_paragraph("The simulation algorithm is as follows.  The current state is initially defined as the identity matrix I.  The maximum opening angle theta or the torsion angle sigma are defined by the parameter values of the frame order model.  The algorithm for one step of the simulation is:") 
573  uf.desc[-1].add_item_list_element("1", "Generate a random vector in 3D.") 
574  uf.desc[-1].add_item_list_element("2", "Construct a rotation matrix from the random vector and the fixed rotation angle.") 
575  uf.desc[-1].add_item_list_element("3", "Pre-multiply the current state by the rotation matrix.") 
576  uf.desc[-1].add_item_list_element("4", "Decompose the new state into the torsion-tilt angles.") 
577  uf.desc[-1].add_item_list_element("5", "If theta or sigma are greater than model parameter values, set them to these maximum values.") 
578  uf.desc[-1].add_item_list_element("6", "Back convert the modified torsion-tilt angles to a rotation matrix - this is the current state.") 
579  uf.desc[-1].add_item_list_element("7", "Store a snapshot if the correct number of iterations has been reached.  This consists of rotating a new model about the pivot(s), as defined by the frame order model.") 
580  uf.desc[-1].add_item_list_element("8", "Terminate the loop if the maximum number of snapshots has been reached.") 
581  uf.desc[-1].add_paragraph("The setting of the steps outside of the distribution to the maximum parameter values is specifically to allow for models with parameter values close to zero.  Without this, the simulation would take a huge amount of time to complete.") 
582  uf.desc[-1].add_paragraph("As the simulation consists of one model per snapshot, if an ensemble of structures has been analysed, only one model from the ensemble can be used for the representation.  This defaults to model number 1, but this can be changed.") 
583  uf.backend = simulate 
584  uf.menu_text = "simula&te" 
585  uf.gui_icon = "oxygen.actions.document-save" 
586  uf.wizard_height_desc = 420 
587  uf.wizard_size = (1000, 750) 
588  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
589   
590   
591  # The frame_order.sobol_setup user function. 
592  uf = uf_info.add_uf('frame_order.sobol_setup') 
593  uf.title = "Set up the quasi-random Sobol' sequence points for numerical PCS integration." 
594  uf.title_short = "Set up the quasi-random Sobol' sequence." 
595  uf.add_keyarg( 
596      name = "max_num", 
597      default = 200, 
598      min = 3, 
599      max = 10000000, 
600      basic_types = ["int"], 
601      desc_short = "maximum number of Sobol' points", 
602      desc = "The maximum number of integration points to use in the Sobol' sequence during optimisation.  This can be considered as the number of molecular structures in an ensemble used form a uniform distribution of the dynamics.", 
603      wiz_element_type = "spin" 
604  ) 
605  uf.add_keyarg( 
606      name = "oversample", 
607      default = 1, 
608      min = 1, 
609      max = 100000, 
610      basic_types = ["int"], 
611      desc_short = "oversampling factor", 
612      desc = "The generation of the Sobol' sequence oversamples as N * Ov * 10**M, where N is the maximum number of points, Ov is the oversamling value, and M is the number of dimensions or torsion-tilt angles used in the system.", 
613      wiz_element_type = "spin" 
614  ) 
615  # Description. 
616  uf.desc.append(Desc_container()) 
617  uf.desc[-1].add_paragraph("This allows the maximum number of integration points N used during the frame order target function optimisation to be specified.  This is used in the quasi-random Sobol' sequence for the numerical integration of the PCS.  The formula used to find the total number of Sobol' points is:") 
618  uf.desc[-1].add_verbatim(""" 
619      total_num = N * Ov * 10**M, 
620  """) 
621  uf.desc[-1].add_paragraph("where:") 
622  uf.desc[-1].add_list_element("N is the maximum number of Sobol' integration points,") 
623  uf.desc[-1].add_list_element("Ov is the oversampling factor.") 
624  uf.desc[-1].add_list_element("M is the number of dimensions or torsion-tilt angles used in the system.") 
625  uf.desc[-1].add_paragraph("The aim of the oversampling is to try to reach the maximum number of points.  However if the system is not very dynamic, the maximum number of points may not be reached.  In this case, simply increase the oversampling factor.  The algorithm used for uniformly sampling the motional space is:") 
626  uf.desc[-1].add_list_element("Generate the Sobol' sequence for the total number of points.") 
627  uf.desc[-1].add_list_element("Convert all points to the torsion-tilt angle system.") 
628  uf.desc[-1].add_list_element("Skip all Sobol' points with angles greater than the current parameter values.") 
629  uf.desc[-1].add_list_element("Terminate the loop over the Sobol' points once the maximum number of points has been reached.") 
630  uf.backend = sobol_setup 
631  uf.menu_text = "&sobol_setup" 
632  uf.gui_icon = "oxygen.actions.edit-rename" 
633  uf.wizard_height_desc = 500 
634  uf.wizard_size = (1000, 700) 
635  uf.wizard_image = WIZARD_IMAGE_PATH + 'frame_order.png' 
636