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

Source Code for Module user_functions.align_tensor

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2007-2015 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 align_tensor user function definitions.""" 
 24   
 25  # relax module imports. 
 26  from graphics import WIZARD_IMAGE_PATH 
 27  from pipe_control import align_tensor, pipes 
 28  from user_functions.data import Uf_info; uf_info = Uf_info() 
 29  from user_functions.objects import Desc_container 
 30   
 31   
 32  # The user function class. 
 33  uf_class = uf_info.add_class('align_tensor') 
 34  uf_class.title = "Class for manipulating the alignment tensor." 
 35  uf_class.menu_text = "&align_tensor" 
 36  uf_class.gui_icon = "relax.align_tensor" 
 37   
 38   
 39  # The align_tensor.copy user function. 
 40  uf = uf_info.add_uf('align_tensor.copy') 
 41  uf.title = "Copy alignment tensor data." 
 42  uf.title_short = "Alignment tensor copying." 
 43  uf.add_keyarg( 
 44      name = "tensor_from", 
 45      default = None, 
 46      py_type = "str", 
 47      desc_short = "source tensor ID", 
 48      desc = "The identification string of the alignment tensor to copy the data from.", 
 49      can_be_none = True 
 50  ) 
 51  uf.add_keyarg( 
 52      name = "pipe_from", 
 53      default = None, 
 54      py_type = "str", 
 55      desc_short = "source data pipe", 
 56      desc = "The name of the data pipe to copy the alignment tensor data from.", 
 57      wiz_element_type = 'combo', 
 58      wiz_combo_iter = pipes.pipe_names, 
 59      can_be_none = True 
 60  ) 
 61  uf.add_keyarg( 
 62      name = "tensor_to", 
 63      default = None, 
 64      py_type = "str", 
 65      desc_short = "destination tensor ID", 
 66      desc = "The identification string of the alignment tensor to copy the data to.", 
 67      can_be_none = True 
 68  ) 
 69  uf.add_keyarg( 
 70      name = "pipe_to", 
 71      default = None, 
 72      py_type = "str", 
 73      desc_short = "destination data pipe", 
 74      desc = "The name of the data pipe to copy the alignment tensor data to.", 
 75      wiz_element_type = 'combo', 
 76      wiz_combo_iter = pipes.pipe_names, 
 77      can_be_none = True 
 78  ) 
 79  # Description. 
 80  uf.desc.append(Desc_container()) 
 81  uf.desc[-1].add_paragraph("This will copy the alignment tensor data to a new tensor or a new data pipe.  The destination data pipe must not contain any alignment tensor data corresponding to the tensor_to label.  If the source or destination data pipes are not supplied, then both will default to the current data pipe.  Both the source and destination tensor IDs must be supplied.") 
 82  # Prompt examples. 
 83  uf.desc.append(Desc_container("Prompt examples")) 
 84  uf.desc[-1].add_paragraph("To copy the alignment tensor data corresponding to 'Pf1' from the data pipe 'old' to the current data pipe, type one of:") 
 85  uf.desc[-1].add_prompt("relax> align_tensor.copy('Pf1', 'old')") 
 86  uf.desc[-1].add_prompt("relax> align_tensor.copy(tensor_from='Pf1', pipe_from='old')") 
 87  uf.desc[-1].add_paragraph("To copy the alignment tensor data corresponding to 'Otting' from the current data pipe to the data pipe new, type one of:") 
 88  uf.desc[-1].add_prompt("relax> align_tensor.copy('Otting', pipe_to='new')") 
 89  uf.desc[-1].add_prompt("relax> align_tensor.copy(tensor_from='Otting', pipe_to='new')") 
 90  uf.desc[-1].add_paragraph("To copy the alignment tensor data of 'Otting' to that of 'Otting new', type one of:") 
 91  uf.desc[-1].add_prompt("relax> align_tensor.copy('Otting', tensor_to='Otting new')") 
 92  uf.desc[-1].add_prompt("relax> align_tensor.copy(tensor_from='Pf1', tensor_to='Otting new')") 
 93  uf.backend = align_tensor.copy 
 94  uf.menu_text = "&copy" 
 95  uf.gui_icon = "oxygen.actions.list-add" 
 96  uf.wizard_size = (800, 600) 
 97  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
 98   
 99   
100  # The align_tensor.delete user function. 
101  uf = uf_info.add_uf('align_tensor.delete') 
102  uf.title = "Delete alignment tensor data from the relax data store." 
103  uf.title_short = "Alignment tensor pipe deletion." 
104  uf.add_keyarg( 
105      name = "tensor", 
106      py_type = "str", 
107      desc_short = "tensor", 
108      desc = "The alignment tensor identification string.", 
109      wiz_element_type = 'combo', 
110      wiz_combo_iter = align_tensor.get_tensor_ids, 
111      wiz_read_only = True, 
112      can_be_none = True 
113  ) 
114  # Description. 
115  uf.desc.append(Desc_container()) 
116  uf.desc[-1].add_paragraph("This will delete the specified alignment tensor data from the current data pipe.  If no tensor is specified, all tensors will be deleted.") 
117  uf.backend = align_tensor.delete 
118  uf.menu_text = "&delete" 
119  uf.gui_icon = "oxygen.actions.list-remove" 
120  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
121   
122   
123  # The align_tensor.display user function. 
124  uf = uf_info.add_uf('align_tensor.display') 
125  uf.title = "Display the alignment tensor information in full detail." 
126  uf.title_short = "Align tensor display." 
127  uf.display = True 
128  uf.add_keyarg( 
129      name = "tensor", 
130      py_type = "str", 
131      desc_short = "tensor", 
132      desc = "The alignment tensor identification string.", 
133      wiz_element_type = 'combo', 
134      wiz_combo_iter = align_tensor.get_tensor_ids, 
135      wiz_read_only = True, 
136      can_be_none = True 
137  ) 
138  uf.desc.append(Desc_container()) 
139  uf.desc[-1].add_paragraph("This will show all information relating to the alignment tensor, including the different tensor forms:") 
140  uf.desc[-1].add_list_element("Probability tensor.") 
141  uf.desc[-1].add_list_element("Saupe order matrix.") 
142  uf.desc[-1].add_list_element("Alignment tensor.") 
143  uf.desc[-1].add_list_element("Magnetic susceptibility tensor.") 
144  uf.desc[-1].add_paragraph("All possible tensor parameters and information will also be shown (Eigensystem, GDO, Aa, Ar, R, eta, chi_ax, chi_rh, etc).  The printout will be extensive.") 
145  uf.desc[-1].add_paragraph("If no tensor is specified, all tensors will be displayed.") 
146  uf.backend = align_tensor.display 
147  uf.menu_text = "dis&play" 
148  uf.gui_icon = "oxygen.actions.document-preview" 
149  uf.wizard_height_desc = 400 
150  uf.wizard_size = (800, 600) 
151  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
152   
153   
154  # The align_tensor.fix user function. 
155  uf = uf_info.add_uf('align_tensor.fix') 
156  uf.title = "Fix all alignment tensors so that they do not change during optimisation." 
157  uf.title_short = "Fix alignment tensors." 
158  uf.add_keyarg( 
159      name = "id", 
160      py_type = "str", 
161      desc_short = "tensor ID", 
162      desc = "The alignment tensor identification string.", 
163      wiz_element_type = 'combo', 
164      wiz_combo_iter = align_tensor.get_tensor_ids, 
165      wiz_read_only = True, 
166      can_be_none = True 
167  ) 
168  uf.add_keyarg( 
169      name = "fixed", 
170      default = True, 
171      py_type = "bool", 
172      desc_short = "fixed flag", 
173      desc = "The flag specifying if the tensors should be fixed or variable." 
174  ) 
175  uf.desc.append(Desc_container()) 
176  uf.desc[-1].add_paragraph("If the ID string is left unset, then all alignment tensors will be fixed.") 
177  uf.backend = align_tensor.fix 
178  uf.menu_text = "&fix" 
179  uf.gui_icon = "oxygen.status.object-locked" 
180  uf.wizard_size = (800, 500) 
181  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
182   
183   
184  # The align_tensor.init user function. 
185  uf = uf_info.add_uf('align_tensor.init') 
186  uf.title = "Initialise an alignment tensor." 
187  uf.title_short = "Alignment tensor initialisation." 
188  uf.add_keyarg( 
189      name = "tensor", 
190      py_type = "str", 
191      desc_short = "tensor ID", 
192      desc = "The optional alignment tensor ID string, required if multiple tensors exist per alignment.", 
193      can_be_none = True 
194  ) 
195  uf.add_keyarg( 
196      name = "align_id", 
197      py_type = "str", 
198      desc_short = "alignment ID", 
199      desc = "The alignment ID string that the tensor corresponds to.", 
200      wiz_element_type = "combo", 
201      wiz_combo_iter = align_tensor.get_tensor_ids, 
202      wiz_read_only = False 
203  ) 
204  uf.add_keyarg( 
205      name = "domain", 
206      py_type = "str", 
207      desc_short = "domain ID", 
208      desc = "The optional domain ID string that the tensor corresponds to.", 
209      can_be_none = True 
210  ) 
211  uf.add_keyarg( 
212      name = "params", 
213      py_type = "num_tuple", 
214      desc_short = "alignment tensor parameters", 
215      dim = 5, 
216      desc = "The alignment tensor data.", 
217      wiz_read_only = False, 
218      can_be_none = True 
219  ) 
220  uf.add_keyarg( 
221      name = "scale", 
222      default = 1.0, 
223      py_type = "float", 
224      desc_short = "scale", 
225      desc = "The alignment tensor eigenvalue scaling value." 
226  ) 
227  uf.add_keyarg( 
228      name = "angle_units", 
229      default = "deg", 
230      py_type = "str", 
231      desc_short = "angle units", 
232      desc = "The units for the angle parameters." 
233  ) 
234  uf.add_keyarg( 
235      name = "param_types", 
236      default = 2, 
237      py_type = "int", 
238      desc_short = "parameter types", 
239      desc = "A flag to select different parameter combinations.", 
240      wiz_element_type = "combo", 
241      wiz_combo_choices = [ 
242          "{Sxx, Syy, Sxy, Sxz, Syz}", 
243          "{Szz, Sxx-yy, Sxy, Sxz, Syz}", 
244          "{Axx, Ayy, Axy, Axz, Ayz}", 
245          "{Azz, Axx-yy, Axy, Axz, Ayz}", 
246          "{Axx, Ayy, Axy, Axz, Ayz}", 
247          "{Azz, Axx-yy, Axy, Axz, Ayz}", 
248          "{Pxx, Pyy, Pxy, Pxz, Pyz}", 
249          "{Pzz, Pxx-yy, Pxy, Pxz, Pyz}" 
250      ], 
251      wiz_combo_data = [ 
252          0, 
253          1, 
254          2, 
255          3, 
256          4, 
257          5, 
258          6, 
259          7 
260      ], 
261      wiz_read_only = True 
262  ) 
263  uf.add_keyarg( 
264      name = "errors", 
265      default = False, 
266      py_type = "bool", 
267      desc_short = "errors flag", 
268      desc = "A flag which determines if the alignment tensor data or its errors are being input." 
269  ) 
270  uf.desc.append(Desc_container()) 
271  uf.desc[-1].add_paragraph("The tensor ID is only required if there are multiple unique tensors per alignment.  An example is if internal domain motions cause multiple parts of the molecule to align differently.  The tensor ID is optional and in the case of only a single tensor per alignment, the tensor can be identified using the alignment ID instead.") 
272  uf.desc[-1].add_paragraph("The alignment tensor parameters should be a tuple of floating point numbers (a list surrounded by round brakets).  These correspond to the parameters of the tensor which can be specified by the parameter types whereby the values correspond to:") 
273  uf.desc[-1].add_item_list_element("0", "{Sxx, Syy, Sxy, Sxz, Syz}  (unitless),") 
274  uf.desc[-1].add_item_list_element("1", "{Szz, Sxx-yy, Sxy, Sxz, Syz}  (Pales default format),") 
275  uf.desc[-1].add_item_list_element("2", "{Axx, Ayy, Axy, Axz, Ayz}  (unitless),") 
276  uf.desc[-1].add_item_list_element("3", "{Azz, Axx-yy, Axy, Axz, Ayz}  (unitless),") 
277  uf.desc[-1].add_item_list_element("4", "{Axx, Ayy, Axy, Axz, Ayz}  (units of Hertz),") 
278  uf.desc[-1].add_item_list_element("5", "{Azz, Axx-yy, Axy, Axz, Ayz}  (units of Hertz),") 
279  uf.desc[-1].add_item_list_element("6", "{Pxx, Pyy, Pxy, Pxz, Pyz}  (unitless),") 
280  uf.desc[-1].add_item_list_element("7", "{Pzz, Pxx-yy, Pxy, Pxz, Pyz}  (unitless).") 
281  uf.desc[-1].add_paragraph("Other formats may be added later.  The relationship between the Saupe order matrix S and the alignment tensor A is") 
282  uf.desc[-1].add_item_list_element(None, "S = 3/2 A.") 
283  uf.desc[-1].add_paragraph("The probability matrix P is related to the alignment tensor A by") 
284  uf.desc[-1].add_item_list_element(None, "A = P - 1/3 I,") 
285  uf.desc[-1].add_paragraph("where I is the identity matrix.  For the alignment tensor to be supplied in Hertz, the bond vectors must all be of equal length.") 
286  # Prompt examples. 
287  uf.desc.append(Desc_container("Prompt examples")) 
288  uf.desc[-1].add_paragraph("To set a rhombic tensor for the domain labelled 'domain 1' with the alignment named 'super media', type one of:") 
289  uf.desc[-1].add_prompt("relax> align_tensor.init('domain 1', 'super media', (-8.6322e-05, -5.5786e-04, -3.1732e-05, 2.2927e-05, 2.8599e-04), param_types=1)") 
290  uf.desc[-1].add_prompt("relax> align_tensor.init(tensor='domain 1', align_id='super media', params=(-8.6322e-05, -5.5786e-04, -3.1732e-05, 2.2927e-05, 2.8599e-04), param_types=1)") 
291  uf.backend = align_tensor.init 
292  uf.menu_text = "&init" 
293  uf.wizard_height_desc = 370 
294  uf.wizard_size = (1000, 750) 
295  uf.gui_icon = "relax.align_tensor" 
296  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
297   
298   
299  # The align_tensor.matrix_angles user function. 
300  uf = uf_info.add_uf('align_tensor.matrix_angles') 
301  uf.title = "Calculate the angles between all alignment tensors." 
302  uf.title_short = "Alignment tensor angle calculation." 
303  uf.display = True 
304  uf.add_keyarg( 
305      name = "basis_set", 
306      default = "matrix", 
307      py_type = "str", 
308      desc_short = "basis set", 
309      desc = "The basis set to operate with.", 
310      wiz_element_type = "combo", 
311      wiz_combo_choices = ["Standard inter-matrix angles", "Irreducible 5D {A-2, A-1, A0, A1, A2}", "Unitary 9D {Sxx, Sxy, Sxz, ..., Szz}", "Unitary 5D {Sxx, Syy, Sxy, Sxz, Syz}", "Geometric 5D {Szz, Sxxyy, Sxy, Sxz, Syz}"], 
312      wiz_combo_data = ["matrix", "irreducible 5D", "unitary 9D", "unitary 5D", "geometric 5D"] 
313  ) 
314  uf.add_keyarg( 
315      name = "tensors", 
316      py_type = "str_list", 
317      desc_short = "alignment tensor IDs", 
318      desc = "A list of the tensors to apply the calculation to.  If None, all tensors are used.", 
319      wiz_element_type = "combo_list", 
320      wiz_combo_iter = align_tensor.get_tensor_ids, 
321      wiz_read_only = True, 
322      can_be_none = True 
323  ) 
324  uf.add_keyarg( 
325      name = "angle_units", 
326      default = "deg", 
327      py_type = "str", 
328      desc_short = "angle units", 
329      desc = "The units for the angle parameters, either 'deg' or 'rad'.", 
330      wiz_element_type = "combo", 
331      wiz_combo_choices = ["Degrees", "Radian"], 
332      wiz_combo_data = ["deg", "rad"] 
333  ) 
334  uf.add_keyarg( 
335      name = "precision", 
336      default = 1, 
337      py_type = "int", 
338      min = 1, 
339      max = 100, 
340      desc_short = "printout precision", 
341      desc = "The precision of the printed out angles.  The number corresponds to the number of figures to print after the decimal point." 
342  ) 
343  # Description. 
344  uf.desc.append(Desc_container()) 
345  uf.desc[-1].add_paragraph("This will calculate the inter-matrix angles between all loaded alignment tensors for the current data pipe.  For the vector basis sets, the matrices are first mapped to vector form and then then the inter-vector angles rather than inter-matrix angles are calculated.  The angles are dependent upon the basis set - linear maps produce identical results whereas non-linear maps result in different angles.  The basis set can be one of:") 
346  uf.desc[-1].add_item_list_element("'matrix'", "The standard inter-matrix angles.  This default option is a linear map, hence angles are preserved.  The angle is calculated via the arccos of the Euclidean inner product of the alignment matrices in rank-2, 3D form divided by the Frobenius norm ||A||_F of the matrices.") 
347  uf.desc[-1].add_item_list_element("'irreducible 5D'", "The inter-tensor vector angles for the irreducible spherical tensor 5D basis set {A-2, A-1, A0, A1, A2}.  This is a linear map, hence angles are preserved.  These are the spherical harmonic decomposition coefficients.") 
348  uf.desc[-1].add_item_list_element("'unitary 9D'", "The inter-tensor vector angles for the unitary 9D basis set {Sxx, Sxy, Sxz, Syx, Syy, Syz, Szx, Szy, Szz}.  This is a linear map, hence angles are preserved.") 
349  uf.desc[-1].add_item_list_element("'unitary 5D'", "The inter-tensor vector angles for the unitary 5D basis set {Sxx, Syy, Sxy, Sxz, Syz}.  This is a non-linear map, hence angles are not preserved.") 
350  uf.desc[-1].add_item_list_element("'geometric 5D'", "The inter-tensor vector angles for the geometric 5D basis set {Szz, Sxxyy, Sxy, Sxz, Syz}.  This is a non-linear map, hence angles are not preserved.  This is also the Pales standard notation.") 
351  uf.desc[-1].add_paragraph("The full matrix angle via the Euclidean inner product is defined as") 
352  uf.desc[-1].add_verbatim("""\ 
353                     /   <A1 , A2>   \  
354      theta = arccos | ------------- | , 
355                     \ ||A1||.||A2|| / \ 
356  """) 
357  uf.desc[-1].add_paragraph("where <a,b> is the Euclidean inner product and ||a|| is the Frobenius norm of the matrix.  For the irreducible spherical tensor 5D basis set, the Am components are defined as") 
358  uf.desc[-1].add_verbatim("""\ 
359              / 4pi \ 1/2 
360         A0 = | --- |     Szz , 
361              \  5  / 
362   
363                  / 8pi \ 1/2 
364      A+/-1 = +/- | --- |     (Sxz +/- iSyz) , 
365                  \ 15  / 
366   
367              / 2pi \ 1/2 
368      A+/-2 = | --- |     (Sxx - Syy +/- 2iSxy) , 
369              \ 15  / \ 
370  """) 
371  uf.desc[-1].add_paragraph("and, for this complex notation, the angle is") 
372  uf.desc[-1].add_verbatim("""\ 
373                     / Re(<A1|A2>) \  
374      theta = arccos | ----------- | , 
375                     \  |A1|.|A2|  / \ 
376  """) 
377  uf.desc[-1].add_paragraph("where the inner product is defined as") 
378  uf.desc[-1].add_verbatim("""\ 
379                 ___ 
380                 \      1    2* 
381      <A1|A2> =   >   Am . Am   , 
382                 /__ 
383                m=-2,2 \ 
384  """) 
385  uf.desc[-1].add_paragraph("and where Am* = (-1)^m A-m, and the norm is defined as |A1| = Re(sqrt(<A1|A1>)).  For all other basis sets whereby the map is real matrix -> real vector, the inter-tensor angle is defined as") 
386  uf.desc[-1].add_verbatim("""\ 
387                     /  <A1|A2>  \  
388      theta = arccos | --------- | , 
389                     \ |A1|.|A2| / \ 
390  """) 
391  uf.desc[-1].add_paragraph("where the inner product <A1|A2> is simply the vector dot product and |A1| is the vector length.") 
392  uf.backend = align_tensor.matrix_angles 
393  uf.menu_text = "&matrix_angles" 
394  uf.gui_icon = "oxygen.categories.applications-education" 
395  uf.wizard_height_desc = 450 
396  uf.wizard_size = (1000, 750) 
397  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
398   
399   
400  # The align_tensor.reduction user function. 
401  uf = uf_info.add_uf('align_tensor.reduction') 
402  uf.title = "Specify that one tensor is a reduction of another." 
403  uf.title_short = "Specify tensor reductions." 
404  uf.add_keyarg( 
405      name = "full_tensor", 
406      py_type = "str", 
407      desc_short = "full tensor", 
408      desc = "The full alignment tensor.", 
409      wiz_element_type = 'combo', 
410      wiz_combo_iter = align_tensor.get_tensor_ids, 
411      wiz_read_only = True 
412  ) 
413  uf.add_keyarg( 
414      name = "red_tensor", 
415      py_type = "str", 
416      desc_short = "reduced tensor", 
417      desc = "The reduced alignment tensor.", 
418      wiz_element_type = 'combo', 
419      wiz_combo_iter = align_tensor.get_tensor_ids, 
420      wiz_read_only = True 
421  ) 
422  # Description. 
423  uf.desc.append(Desc_container()) 
424  uf.desc[-1].add_paragraph("Prior to optimisation of the N-state model and Frame Order theories using alignment tensors, which tensor is a reduction of which other tensor must be specified through this user function.") 
425  # Prompt examples. 
426  uf.desc.append(Desc_container("Prompt examples")) 
427  uf.desc[-1].add_paragraph("To state that the alignment tensor loaded as 'chi3 C-dom' is a reduction of 'chi3 N-dom', type:") 
428  uf.desc[-1].add_prompt("relax> align_tensor.reduction(full_tensor='chi3 N-dom', red_tensor='chi3 C-dom')") 
429  uf.backend = align_tensor.reduction 
430  uf.menu_text = "&reduction" 
431  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
432   
433   
434  # The align_tensor.set_domain user function. 
435  uf = uf_info.add_uf('align_tensor.set_domain') 
436  uf.title = "Set the domain label for the alignment tensor." 
437  uf.title_short = "Tensor domain labelling." 
438  uf.add_keyarg( 
439      name = "tensor", 
440      py_type = "str", 
441      desc_short = "tensor ID", 
442      desc = "The alignment tensor to assign the domain label to.", 
443      wiz_element_type = 'combo', 
444      wiz_combo_iter = align_tensor.get_tensor_ids, 
445      wiz_read_only = True, 
446  ) 
447  uf.add_keyarg( 
448      name = "domain", 
449      py_type = "str", 
450      desc_short = "domain", 
451      desc = "The domain label." 
452  ) 
453  # Description. 
454  uf.desc.append(Desc_container()) 
455  uf.desc[-1].add_paragraph("Prior to optimisation of the N-state model or Frame Order theories, the domain to which each alignment tensor belongs must be specified.") 
456  # Prompt examples. 
457  uf.desc.append(Desc_container("Prompt examples")) 
458  uf.desc[-1].add_paragraph("To link the alignment tensor loaded as 'chi3 C-dom' to the C-terminal domain 'C', type:") 
459  uf.desc[-1].add_prompt("relax> align_tensor.set_domain(tensor='chi3 C-dom', domain='C')") 
460  uf.backend = align_tensor.set_domain 
461  uf.menu_text = "&set_domain" 
462  uf.gui_icon = "oxygen.actions.edit-select" 
463  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
464   
465   
466  # The align_tensor.svd user function. 
467  uf = uf_info.add_uf('align_tensor.svd') 
468  uf.title = "Calculate the singular values and condition number for all alignment tensors." 
469  uf.title_short = "Alignment tensor SVD calculation." 
470  uf.display = True 
471  uf.add_keyarg( 
472      name = "basis_set", 
473      default = "irreducible 5D", 
474      py_type = "str", 
475      desc_short = "basis set", 
476      desc = "The basis set to operate with.", 
477      wiz_element_type = "combo", 
478      wiz_combo_choices = ["Irreducible 5D {A-2, A-1, A0, A1, A2}", "Unitary 9D {Sxx, Sxy, Sxz, ..., Szz}", "Unitary 5D {Sxx, Syy, Sxy, Sxz, Syz}", "Geometric 5D {Szz, Sxxyy, Sxy, Sxz, Syz}"], 
479      wiz_combo_data = ["irreducible 5D", "unitary 9D", "unitary 5D", "geometric 5D"] 
480  ) 
481  uf.add_keyarg( 
482      name = "tensors", 
483      py_type = "str_list", 
484      desc_short = "alignment tensor IDs", 
485      desc = "A list of the tensors to apply the calculation to.  If None, all tensors are used.", 
486      wiz_element_type = "combo_list", 
487      wiz_combo_iter = align_tensor.get_tensor_ids, 
488      wiz_read_only = True, 
489      can_be_none = True 
490  ) 
491  uf.add_keyarg( 
492      name = "precision", 
493      default = 4, 
494      py_type = "int", 
495      min = 1, 
496      max = 100, 
497      desc_short = "printout precision", 
498      desc = "The precision of the printed out singular values and condition numbers.  The number corresponds to the number of figures to print after the decimal point." 
499  ) 
500  # Description. 
501  uf.desc.append(Desc_container()) 
502  uf.desc[-1].add_paragraph("This will perform a singular value decomposition for all alignment tensors and calculate the condition number.  The singular values and condition number are dependent on the basis set - linear maps produce identical results whereas non-linear maps result in different values.  The basis set can be one of:") 
503  uf.desc[-1].add_item_list_element("'irreducible 5D'", "The irreducible spherical tensor 5D basis set {A-2, A-1, A0, A1, A2}.  This is a linear map, hence angles, singular values, and condition number are preserved.  These are the spherical harmonic decomposition coefficients.") 
504  uf.desc[-1].add_item_list_element("'unitary 9D'", "The unitary 9D basis set {Sxx, Sxy, Sxz, Syx, Syy, Syz, Szx, Szy, Szz}.  This is a linear map, hence angles, singular values, and condition number are preserved.") 
505  uf.desc[-1].add_item_list_element("'unitary 5D'", "The unitary 5D basis set {Sxx, Syy, Sxy, Sxz, Syz}.  This is a non-linear map, hence angles, singular values, and condition number are not preserved.") 
506  uf.desc[-1].add_item_list_element("'geometric 5D'", "The geometric 5D basis set {Szz, Sxxyy, Sxy, Sxz, Syz}.  This is a non-linear map, hence angles, singular values, and condition number are not preserved.  This is also the Pales standard notation.") 
507  uf.desc[-1].add_paragraph("If the selected basis set is the default of 'irreducible 5D', the matrix on which SVD will be performed will be:") 
508  uf.desc[-1].add_verbatim("""\ 
509      | A-2(1) A-1(1) A0(1)  A1(1)  A2(1) | 
510      | A-2(2) A-1(2) A0(2)  A1(2)  A2(2) | 
511      | A-2(3) A-1(3) A0(3)  A1(3)  A2(3) | 
512      |   .      .     .      .      .    | 
513      |   .      .     .      .      .    | 
514      |   .      .     .      .      .    | 
515      | A-2(N) A-1(N) A0(N)  A1(N)  A2(N) |\ 
516  """) 
517  uf.desc[-1].add_paragraph("If the selected basis set is 'unitary 9D', the matrix on which SVD will be performed will be:") 
518  uf.desc[-1].add_verbatim("""\ 
519      | Sxx1 Sxy1 Sxz1 Syx1 Syy1 Syz1 Szx1 Szy1 Szz1 | 
520      | Sxx2 Sxy2 Sxz2 Syx2 Syy2 Syz2 Szx2 Szy2 Szz2 | 
521      | Sxx3 Sxy3 Sxz3 Syx3 Syy3 Syz3 Szx3 Szy3 Szz3 | 
522      |  .    .    .    .    .    .    .    .    .   | 
523      |  .    .    .    .    .    .    .    .    .   | 
524      |  .    .    .    .    .    .    .    .    .   | 
525      | SxxN SxyN SxzN SyxN SyyN SyzN SzxN SzyN SzzN |\ 
526  """) 
527  uf.desc[-1].add_paragraph("Otherwise if the selected basis set is 'unitary 5D', the matrix for SVD is:") 
528  uf.desc[-1].add_verbatim("""\ 
529      | Sxx1 Syy1 Sxy1 Sxz1 Syz1 | 
530      | Sxx2 Syy2 Sxy2 Sxz2 Syz2 | 
531      | Sxx3 Syy3 Sxy3 Sxz3 Syz3 | 
532      |  .    .    .    .    .   | 
533      |  .    .    .    .    .   | 
534      |  .    .    .    .    .   | 
535      | SxxN SyyN SxyN SxzN SyzN |\ 
536  """) 
537  uf.desc[-1].add_paragraph("Or if the selected basis set is 'geometric 5D', the stretching and skewing parameters Szz and Sxx-yy will be used instead and the matrix is:") 
538  uf.desc[-1].add_verbatim("""\ 
539      | Szz1 Sxxyy1 Sxy1 Sxz1 Syz1 | 
540      | Szz2 Sxxyy2 Sxy2 Sxz2 Syz2 | 
541      | Szz3 Sxxyy3 Sxy3 Sxz3 Syz3 | 
542      |  .     .     .    .    .   | 
543      |  .     .     .    .    .   | 
544      |  .     .     .    .    .   | 
545      | SzzN SxxyyN SxyN SxzN SyzN |\ 
546  """) 
547  uf.desc[-1].add_paragraph("For the irreducible spherical tensor basis set, the Am components are defined as") 
548  uf.desc[-1].add_verbatim("""\ 
549              / 4pi \ 1/2 
550         A0 = | --- |     Szz , 
551              \  5  / 
552   
553                  / 8pi \ 1/2 
554      A+/-1 = +/- | --- |     (Sxz +/- iSyz) , 
555                  \ 15  / 
556   
557              / 2pi \ 1/2 
558      A+/-2 = | --- |     (Sxx - Syy +/- 2iSxy) . 
559              \ 15  / \ 
560  """) 
561  uf.desc[-1].add_paragraph("The relationships between the geometric and unitary basis sets are") 
562  uf.desc[-1].add_verbatim("""\ 
563      Szz = - Sxx - Syy, 
564      Sxxyy = Sxx - Syy.\ 
565  """) 
566  uf.backend = align_tensor.svd 
567  uf.menu_text = "s&vd" 
568  uf.gui_icon = "oxygen.categories.applications-education" 
569  uf.wizard_height_desc = 500 
570  uf.wizard_size = (1000, 750) 
571  uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png' 
572