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

Source Code for Module user_functions.relax_disp

   1  ############################################################################### 
   2  #                                                                             # 
   3  # Copyright (C) 2004-2015 Edward d'Auvergne                                   # 
   4  # Copyright (C) 2009 Sebastien Morin                                          # 
   5  # Copyright (C) 2014 Troels E. Linnet                                         # 
   6  #                                                                             # 
   7  # This file is part of the program relax (http://www.nmr-relax.com).          # 
   8  #                                                                             # 
   9  # This program is free software: you can redistribute it and/or modify        # 
  10  # it under the terms of the GNU General Public License as published by        # 
  11  # the Free Software Foundation, either version 3 of the License, or           # 
  12  # (at your option) any later version.                                         # 
  13  #                                                                             # 
  14  # This program is distributed in the hope that it will be useful,             # 
  15  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
  16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
  17  # GNU General Public License for more details.                                # 
  18  #                                                                             # 
  19  # You should have received a copy of the GNU General Public License           # 
  20  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
  21  #                                                                             # 
  22  ############################################################################### 
  23   
  24  # Module docstring. 
  25  """The relax_disp user function definitions.""" 
  26   
  27  # Python module imports. 
  28  import dep_check 
  29  from os import sep 
  30  if dep_check.wx_module: 
  31      from wx import FD_OPEN, FD_SAVE 
  32  else: 
  33      FD_OPEN = -1 
  34      FD_SAVE = -1 
  35   
  36  # relax module imports. 
  37  from lib.dispersion.variables import EXP_TYPE_CPMG_DQ, EXP_TYPE_CPMG_MQ, EXP_TYPE_CPMG_SQ, EXP_TYPE_CPMG_ZQ, EXP_TYPE_CPMG_PROTON_MQ, EXP_TYPE_CPMG_PROTON_SQ, EXP_TYPE_R1RHO, MODEL_B14, MODEL_B14_FULL, MODEL_CR72, MODEL_CR72_FULL, MODEL_DPL94, MODEL_IT99, MODEL_LIST_FIT_R1, MODEL_LM63, MODEL_LM63_3SITE, MODEL_M61, MODEL_M61B, MODEL_MMQ_CR72, MODEL_MP05, MODEL_NOREX, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_MMQ_2SITE, MODEL_NS_MMQ_3SITE, MODEL_NS_MMQ_3SITE_LINEAR, MODEL_NS_R1RHO_2SITE, MODEL_NS_R1RHO_3SITE, MODEL_NS_R1RHO_3SITE_LINEAR, MODEL_R2EFF, MODEL_TAP03, MODEL_TP02, MODEL_TSMFK01 
  38  from lib.text.gui import dw, dw_AB, dw_BC, dwH, dwH_AB, dwH_BC, i0, kex, kAB, kBC, kAC, phi_ex, phi_exB, phi_exC, nu_1, nu_cpmg, r1rho, r1rho_prime, r2, r2a, r2b, r2eff, tex, theta, w_eff, w_rf 
  39  from graphics import ANALYSIS_IMAGE_PATH, WIZARD_IMAGE_PATH 
  40  from pipe_control import pipes, spectrum 
  41  from pipe_control.mol_res_spin import get_spin_ids 
  42  from specific_analyses.relax_disp.catia import catia_execute, catia_input 
  43  from specific_analyses.relax_disp.cpmgfit import cpmgfit_execute, cpmgfit_input 
  44  from specific_analyses.relax_disp.estimate_r2eff import estimate_r2eff_err 
  45  from specific_analyses.relax_disp.data import cpmg_setup, insignificance, plot_disp_curves, plot_exp_curves, r2eff_read, r2eff_read_spin, relax_time, set_exp_type, r20_from_min_r2eff, spin_lock_field, spin_lock_offset, write_disp_curves 
  46  from specific_analyses.relax_disp.data import INTERPOLATE_DISP, INTERPOLATE_OFFSET, X_AXIS_DISP, X_AXIS_W_EFF, X_AXIS_THETA, Y_AXIS_R2_R1RHO, Y_AXIS_R2_EFF 
  47  from specific_analyses.relax_disp.nessy import nessy_input 
  48  from specific_analyses.relax_disp.parameters import copy 
  49  from specific_analyses.relax_disp.sherekhan import sherekhan_input 
  50  from specific_analyses.relax_disp import uf as relax_disp_uf 
  51  from user_functions.data import Uf_info; uf_info = Uf_info() 
  52  from user_functions.objects import Desc_container 
  53  from user_functions.wildcards import WILDCARD_GRACE_ALL 
  54   
  55   
  56  # The user function class. 
  57  uf_class = uf_info.add_class('relax_disp') 
  58  uf_class.title = "Class for relaxation curve fitting." 
  59  uf_class.menu_text = "&relax_disp" 
  60  uf_class.gui_icon = "relax.relax_disp" 
  61   
  62   
  63  # The relax_disp.catia_execute user function. 
  64  uf = uf_info.add_uf('relax_disp.catia_execute') 
  65  uf.title = "Perform a relaxation dispersion optimisation using Flemming Hansen's CATIA." 
  66  uf.title_short = "CATIA execution." 
  67  uf.add_keyarg( 
  68      name = "dir", 
  69      py_type = "str", 
  70      arg_type = "dir sel", 
  71      desc_short = "directory name", 
  72      desc = "The directory containing all of the CATIA input files.", 
  73      can_be_none = True 
  74  ) 
  75  uf.add_keyarg( 
  76      name = "binary", 
  77      default = "catia", 
  78      py_type = "str", 
  79      arg_type = "file sel", 
  80      desc_short = "CATIA executable file", 
  81      desc = "The name of the executable CATIA program file.", 
  82      wiz_filesel_style = FD_OPEN, 
  83      wiz_filesel_preview = False 
  84  ) 
  85  # Description. 
  86  uf.desc.append(Desc_container()) 
  87  uf.desc[-1].add_paragraph("CATIA will be executed as") 
  88  uf.desc[-1].add_prompt("$ catia < Fit.catia") 
  89  uf.desc[-1].add_paragraph("If you would like to use a different CATIA executable file, change the binary name to the appropriate file name.  If the file is not located within the environment's path, include the full path in front of the binary file name.") 
  90  uf.backend = catia_execute 
  91  uf.gui_icon = "oxygen.categories.applications-education" 
  92  uf.menu_text = "catia_e&xecute" 
  93  uf.wizard_size = (800, 600) 
  94  uf.wizard_apply_button = False 
  95  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
  96   
  97   
  98  # The relax_disp.catia_input user function. 
  99  uf = uf_info.add_uf('relax_disp.catia_input') 
 100  uf.title = "Create the input files for Flemming Hansen's CATIA program." 
 101  uf.title_short = "CATIA input file creation." 
 102  uf.add_keyarg( 
 103      name = "dir", 
 104      default = "catia", 
 105      py_type = "str", 
 106      arg_type = "dir sel", 
 107      desc_short = "directory name", 
 108      desc = "The directory to place the CATIA input files, output directory, etc.", 
 109      can_be_none = True 
 110  ) 
 111  uf.add_keyarg( 
 112      name = "force", 
 113      default = False, 
 114      py_type = "bool", 
 115      desc_short = "force flag", 
 116      desc = "A flag which if set to True will cause the files to be overwritten if they already exist." 
 117  ) 
 118  # Description. 
 119  uf.desc.append(Desc_container()) 
 120  uf.desc[-1].add_paragraph("This will create all of the input file required for CATIA as well as the CATIA results output directory.") 
 121  uf.backend = catia_input 
 122  uf.gui_icon = "oxygen.actions.list-add-relax-blue" 
 123  uf.menu_text = "&catia_input" 
 124  uf.wizard_size = (800, 600) 
 125  uf.wizard_apply_button = False 
 126  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 127   
 128   
 129  # The relax_disp.cluster user function. 
 130  uf = uf_info.add_uf('relax_disp.cluster') 
 131  uf.title = "Define clusters of spins for joint optimisation." 
 132  uf.title_short = "Spin clustering." 
 133  uf.add_keyarg( 
 134      name = "cluster_id", 
 135      py_type = "str", 
 136      desc_short = "cluster ID", 
 137      desc = "The cluster identification string.", 
 138      wiz_element_type = 'combo', 
 139      wiz_combo_iter = relax_disp_uf.cluster_ids 
 140  ) 
 141  uf.add_keyarg( 
 142      name = "spin_id", 
 143      py_type = "str", 
 144      desc_short = "spin ID string", 
 145      desc = "The spin identifier string for the spin or group of spins to add to the cluster.", 
 146      wiz_element_type = 'combo', 
 147      wiz_combo_iter = get_spin_ids, 
 148      can_be_none = True 
 149  ) 
 150  # Description. 
 151  uf.desc.append(Desc_container()) 
 152  uf.desc[-1].add_paragraph("In a relaxation dispersion analysis, the parameters of the model of dispersion can either be optimised for each spin system separately or a number of spins can be grouped or clustered and the dispersion model parameters optimised for all spins in the cluster together.  Clusters are identified by unique ID strings.  Any spins not within a cluster will be optimised separately and individually.") 
 153  uf.desc[-1].add_paragraph("If the cluster ID string already exists, the spins will be added to that pre-existing cluster.  If no spin ID is given, then all spins will be added to the cluster.") 
 154  uf.desc[-1].add_paragraph("The special cluster ID string 'free spins' is reserved for the pool of non-clustered spins.  This can be used to remove a spin system from an already existing cluster by specifying this cluster ID and the desired spin ID.") 
 155  # Prompt examples. 
 156  uf.desc.append(Desc_container("Prompt examples")) 
 157  uf.desc[-1].add_paragraph("To add the spins ':1@N' and ':3@N' to a new cluster called 'cluster', type one of:") 
 158  uf.desc[-1].add_prompt("relax> relax_disp.cluster('cluster', ':1,3@N')") 
 159  uf.desc[-1].add_prompt("relax> relax_disp.cluster(cluster_id='cluster', spin_id=':1,3@N')") 
 160  uf.backend = relax_disp_uf.cluster 
 161  uf.menu_text = "c&luster" 
 162  uf.gui_icon = "relax.cluster" 
 163  uf.wizard_height_desc = 500 
 164  uf.wizard_size = (800, 600) 
 165  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 166   
 167   
 168  # The relax_disp.cpmg_setup user function. 
 169  uf = uf_info.add_uf('relax_disp.cpmg_setup') 
 170  uf.title = "Set the CPMG pulse sequence information associated with a given spectrum." 
 171  uf.title_short = "CPMG experiment setup." 
 172  uf.add_keyarg( 
 173      name = "spectrum_id", 
 174      py_type = "str", 
 175      desc_short = "spectrum ID string", 
 176      desc = "The spectrum ID string to associate the CPMG pulse sequence information to.", 
 177      wiz_element_type = 'combo', 
 178      wiz_combo_iter = spectrum.get_ids, 
 179      wiz_read_only = True 
 180  ) 
 181  uf.add_keyarg( 
 182      name = "cpmg_frq", 
 183      py_type = "num", 
 184      desc_short = "CPMG frequency (Hz)", 
 185      desc = "The frequency, in Hz, of the CPMG pulse train.", 
 186      can_be_none = True 
 187  ) 
 188  uf.add_keyarg( 
 189      name = "ncyc_even", 
 190      default = True, 
 191      py_type = "bool", 
 192      desc_short = "even ncyc flag", 
 193      desc = "A flag which if True means that the number of CPMG blocks must be even.  This is pulse sequence dependant." 
 194  ) 
 195  # Description. 
 196  uf.desc.append(Desc_container()) 
 197  uf.desc[-1].add_paragraph("This allows all information about CPMG pulse sequence required for a relaxation dispersion analysis to be specified.  This includes:") 
 198  uf.desc[-1].add_list_element("'cpmg_frq' allows the CPMG pulse train frequency of a given spectrum to be set.  If None is given for frequency, then the spectrum will be treated as a reference spectrum.") 
 199  uf.desc[-1].add_list_element("'ncyc_even' specifies if an even number of CPMG blocks are required for the pulse sequence.") 
 200  # Prompt examples. 
 201  uf.desc.append(Desc_container("Prompt examples")) 
 202  uf.desc[-1].add_paragraph("To identify the reference spectrum called 'reference_spectrum', type:") 
 203  uf.desc[-1].add_prompt("relax> relax_disp.cpmg_setup(spectrum_id='reference_spectrum', cpmg_frq=None)") 
 204  uf.desc[-1].add_paragraph("To set a frequency of 200 Hz for the spectrum '200_Hz_spectrum', type:") 
 205  uf.desc[-1].add_prompt("relax> relax_disp.cpmg_setup(spectrum_id='200_Hz_spectrum', cpmg_frq=200)") 
 206  uf.backend = cpmg_setup 
 207  uf.menu_text = "&cpmg_setup" 
 208  uf.wizard_size = (900, 600) 
 209  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 210   
 211   
 212  # The relax_disp.cpmgfit_execute user function. 
 213  uf = uf_info.add_uf('relax_disp.cpmgfit_execute') 
 214  uf.title = "Optimisation of the CPMG data using Art Palmer's CPMGFit program." 
 215  uf.title_short = "CPMGFit execution." 
 216  uf.add_keyarg( 
 217      name = "dir", 
 218      py_type = "str", 
 219      arg_type = "dir sel", 
 220      desc_short = "directory name", 
 221      desc = "The directory containing all of the CPMGFit input files.  If not given, this defaults to the model name in lower case.", 
 222      can_be_none = True 
 223  ) 
 224  uf.add_keyarg( 
 225      name = "force", 
 226      default = False, 
 227      py_type = "bool", 
 228      desc_short = "force flag", 
 229      desc = "A flag which if set to True will cause the results files to be overwritten if they already exist." 
 230  ) 
 231  uf.add_keyarg( 
 232      name = "binary", 
 233      default = "cpmgfit", 
 234      py_type = "str", 
 235      arg_type = "file sel", 
 236      desc_short = "CPMGFit executable file", 
 237      desc = "The name of the executable CPMGFit program file.", 
 238      wiz_filesel_style = FD_OPEN, 
 239      wiz_filesel_preview = False 
 240  ) 
 241  # Description. 
 242  uf.desc.append(Desc_container()) 
 243  uf.desc[-1].add_paragraph("CPMGFit will be executed once per spin as:") 
 244  uf.desc[-1].add_prompt("$ cpmgfit -grid -xmgr -f dir/spin_x.in | tee dir/spin_x.out") 
 245  uf.desc[-1].add_paragraph("where x is replaced by each spin ID string.  If you would like to use a different CPMGFit executable file, change the binary name to the appropriate file name.  If the file is not located within the environment's path, be sure to include the full path in front of the binary file name so it can be found.") 
 246  uf.backend = cpmgfit_execute 
 247  uf.menu_text = "&cpmgfit_execute" 
 248  uf.gui_icon = "oxygen.categories.applications-education" 
 249  uf.wizard_size = (800, 600) 
 250  uf.wizard_apply_button = False 
 251  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 252   
 253   
 254  # The relax_disp.cpmgfit_input user function. 
 255  uf = uf_info.add_uf('relax_disp.cpmgfit_input') 
 256  uf.title = "Create the input files for Art Palmer's CPMGFit program." 
 257  uf.title_short = "CPMGFit input file creation." 
 258  uf.add_keyarg( 
 259      name = "dir", 
 260      py_type = "str", 
 261      arg_type = "dir sel", 
 262      desc_short = "directory name", 
 263      desc = "The directory to place the files.  If not given, this defaults to the model name in lower case.", 
 264      can_be_none = True 
 265  ) 
 266  uf.add_keyarg( 
 267      name = "force", 
 268      default = False, 
 269      py_type = "bool", 
 270      desc_short = "force flag", 
 271      desc = "A flag which if set to True will cause the files to be overwritten if they already exist." 
 272  ) 
 273  uf.add_keyarg( 
 274      name = "binary", 
 275      default = "cpmgfit", 
 276      py_type = "str", 
 277      arg_type = "file sel", 
 278      desc_short = "CPMGFit executable file", 
 279      desc = "The name of the executable CPMGFit program file.", 
 280      wiz_filesel_style = FD_OPEN, 
 281      wiz_filesel_preview = False 
 282  ) 
 283  uf.add_keyarg( 
 284      name = "spin_id", 
 285      py_type = "str", 
 286      desc_short = "spin ID string", 
 287      desc = "The spin identification string.", 
 288      can_be_none = True 
 289  ) 
 290  # Description. 
 291  uf.desc.append(Desc_container()) 
 292  uf.desc[-1].add_paragraph("The following files are created:") 
 293  uf.desc[-1].add_list_element("'dir/spin_x.in',") 
 294  uf.desc[-1].add_list_element("'dir/run.sh'.") 
 295  uf.desc[-1].add_paragraph("One CPMGFit input file is created per spin and named 'dir/spin_x.in', where x is the spin ID string.  The file 'dir/run.sh' is a batch file for executing CPMGFit for all of the spin input files.  If you would like to use a different CPMGFit executable file, change the binary name to the appropriate file name.  If the file is not located within the environment's path, be sure to include the full path in front of the binary name so it can be found.") 
 296  uf.backend = cpmgfit_input 
 297  uf.menu_text = "&cpmgfit_input" 
 298  uf.gui_icon = "oxygen.actions.list-add-relax-blue" 
 299  uf.wizard_size = (800, 600) 
 300  uf.wizard_apply_button = False 
 301  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 302   
 303   
 304  # The relax_disp.exp_type user function. 
 305  uf = uf_info.add_uf('relax_disp.exp_type') 
 306  uf.title = "Select the relaxation dispersion experiment type." 
 307  uf.title_short = "Relaxation dispersion experiment type selection." 
 308  uf.add_keyarg( 
 309      name = "spectrum_id", 
 310      py_type = "str", 
 311      desc_short = "spectrum ID string", 
 312      desc = "The spectrum ID string to associate the spin-lock field strength to.", 
 313      wiz_element_type = 'combo', 
 314      wiz_combo_iter = spectrum.get_ids, 
 315      wiz_read_only = True 
 316  ) 
 317  uf.add_keyarg( 
 318      name = "exp_type", 
 319      default = EXP_TYPE_CPMG_SQ, 
 320      py_type = "str", 
 321      desc_short = "experiment type", 
 322      desc = "The type of relaxation dispersion experiment performed.", 
 323      wiz_element_type = "combo", 
 324      wiz_combo_choices = [ 
 325          "Single quantum (SQ) CPMG-type data", 
 326          "Zero quantum (ZQ) CPMG-type data", 
 327          "Double quantum (DQ) CPMG-type data", 
 328          "Multiple quantum (MQ) CPMG-type data", 
 329          "1H single quantum (SQ) CPMG-type data", 
 330          "1H multiple quantum (SQ) CPMG-type data", 
 331          "%s-type data" % r1rho 
 332      ], 
 333      wiz_combo_data = [ 
 334          EXP_TYPE_CPMG_SQ, 
 335          EXP_TYPE_CPMG_ZQ, 
 336          EXP_TYPE_CPMG_DQ, 
 337          EXP_TYPE_CPMG_MQ, 
 338          EXP_TYPE_CPMG_PROTON_SQ, 
 339          EXP_TYPE_CPMG_PROTON_MQ, 
 340          EXP_TYPE_R1RHO 
 341      ], 
 342      wiz_read_only = True 
 343  ) 
 344  # Description. 
 345  uf.desc.append(Desc_container()) 
 346  uf.desc[-1].add_paragraph("For each peak intensity set loaded into relax, the type of experiment it comes from needs to be specified.  By specifying this for each spectrum ID, multiple experiment types can be analysed simultaneously.  This is assuming that an appropriate dispersion model exists for the experiment combination.") 
 347  uf.desc[-1].add_paragraph("The currently supported experiments include:") 
 348  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_SQ), "The single quantum (SQ) CPMG-type experiments,") 
 349  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_ZQ), "The zero quantum (ZQ) CPMG-type experiments,") 
 350  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_DQ), "The double quantum (DQ) CPMG-type experiments,") 
 351  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_MQ), "The multiple quantum (MQ) CPMG-type experiments,") 
 352  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_PROTON_SQ), "The 1H single quantum (SQ) CPMG-type experiments,") 
 353  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_PROTON_MQ), "The 1H multiple quantum (MQ) CPMG-type experiments,") 
 354  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_R1RHO), "The R1rho-type experiments.") 
 355  # Prompt examples. 
 356  uf.desc.append(Desc_container("Prompt examples")) 
 357  uf.desc[-1].add_paragraph("To set the experiment type to 'SQ CPMG' for the spectrum ID 'nu_4500.0_800MHz', type one of:") 
 358  uf.desc[-1].add_prompt("relax> relax_disp.exp_type('nu_4500.0_800MHz', 'SQ CPMG')") 
 359  uf.desc[-1].add_prompt("relax> relax_disp.exp_type(spectrum_id='nu_4500.0_800MHz', exp_type='SQ CPMG')") 
 360  uf.backend = set_exp_type 
 361  uf.menu_text = "&exp_type" 
 362  uf.wizard_height_desc = 400 
 363  uf.wizard_size = (900, 600) 
 364  uf.wizard_apply_button = False 
 365  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 366   
 367   
 368  # The relax_disp.insignificance user function. 
 369  uf = uf_info.add_uf('relax_disp.insignificance') 
 370  uf.title = "Deselect all spins with insignificant dispersion." 
 371  uf.title_short = "Insignificant spin deselection." 
 372  uf.add_keyarg( 
 373      name = "level", 
 374      py_type = "float", 
 375      default = 2.0, 
 376      desc_short = "insignificance level", 
 377      desc = "The R2eff/R1rho value in rad/s by which to judge insignificance.  If the maximum difference between two points on all dispersion curves for a spin is less than this value, that spin will be deselected.", 
 378      can_be_none = False 
 379  ) 
 380  # Description. 
 381  uf.desc.append(Desc_container()) 
 382  uf.desc[-1].add_paragraph("This can be used to deselect all spins which have insignificant dispersion profiles.  The insignificance value is the R2eff/R1rho value in rad/s by which to judge the dispersion curves by.  If the maximum difference between two points on all dispersion curves for a spin is less than this value, that spin will be deselected.") 
 383  uf.backend = insignificance 
 384  uf.gui_icon = "relax.spin_grey" 
 385  uf.menu_text = "&insignificance" 
 386  uf.wizard_size = (800, 550) 
 387  uf.wizard_apply_button = False 
 388  uf.wizard_image = WIZARD_IMAGE_PATH + 'deselect.png' 
 389   
 390   
 391  # The relax_disp.nessy_input user function. 
 392  uf = uf_info.add_uf('relax_disp.nessy_input') 
 393  uf.title = "Create the input files for Michael Bieri's NESSY program." 
 394  uf.title_short = "NESSY input file creation." 
 395  uf.add_keyarg( 
 396      name = "dir", 
 397      py_type = "str", 
 398      arg_type = "dir sel", 
 399      desc_short = "directory name", 
 400      desc = "The directory to place the file and to use as the NESSY project directory.  If not given, this defaults to the current directory.", 
 401      can_be_none = True 
 402  ) 
 403  uf.add_keyarg( 
 404      name = "force", 
 405      default = False, 
 406      py_type = "bool", 
 407      desc_short = "force flag", 
 408      desc = "A flag which if set to True will cause the files to be overwritten if they already exist." 
 409  ) 
 410  uf.add_keyarg( 
 411      name = "spin_id", 
 412      py_type = "str", 
 413      desc_short = "spin ID string", 
 414      desc = "The spin identification string.", 
 415      can_be_none = True 
 416  ) 
 417  # Description. 
 418  uf.desc.append(Desc_container()) 
 419  uf.desc[-1].add_paragraph("This will create a single NESSY save file called 'save.NESSY'.  This will contain all of the dispersion data currently loaded in the relax data store.  If the directory name is not supplied, this will default to the current directory.") 
 420  uf.backend = nessy_input 
 421  uf.menu_text = "&nessy_input" 
 422  uf.gui_icon = "relax.nessy" 
 423  uf.wizard_size = (800, 600) 
 424  uf.wizard_apply_button = False 
 425  uf.wizard_image = WIZARD_IMAGE_PATH + 'nessy.png' 
 426   
 427   
 428  # The relax_disp.parameter_copy user function. 
 429  uf = uf_info.add_uf('relax_disp.parameter_copy') 
 430  uf.title = "Copy dispersion specific parameters values from one data pipe to another." 
 431  uf.title_short = "Dispersion parameter copying." 
 432  uf.add_keyarg( 
 433      name = "pipe_from", 
 434      py_type = "str", 
 435      desc_short = "source data pipe", 
 436      desc = "The name of the pipe to copy from.", 
 437      wiz_element_type = 'combo', 
 438      wiz_combo_iter = pipes.pipe_names, 
 439      wiz_read_only = True 
 440  ) 
 441  uf.add_keyarg( 
 442      name = "pipe_to", 
 443      py_type = "str", 
 444      desc_short = "destination data pipe", 
 445      desc = "The name of the pipe to copy to.", 
 446      wiz_element_type = 'combo', 
 447      wiz_combo_iter = pipes.pipe_names, 
 448      wiz_read_only = True 
 449  ) 
 450  # Description. 
 451  uf.desc.append(Desc_container()) 
 452  uf.desc[-1].add_paragraph("This is a special function for copying relaxation dispersion parameters from one data pipe to another.  It is much more advanced than the value.copy user function, in that clustering is taken into account.  When the destination data pipe has spin clusters defined, then the new parameter values, when required, will be taken as the median value.") 
 453  uf.desc[-1].add_paragraph("For the cluster specific parameters, i.e. the populations of the states and the exchange parameters, a median value will be used as the starting point.  For all other parameters, the R20 values for each spin and magnetic field, as well as the parameters related to the chemical shift difference dw, the optimised values of the previous run will be directly copied.") 
 454  uf.desc.append(Desc_container("Prompt examples")) 
 455  uf.desc[-1].add_paragraph("To copy the CSA values from the data pipe 'm1' to 'm2', type:") 
 456  uf.desc[-1].add_prompt("relax> value.parameter_copy('m1', 'm2', 'csa')") 
 457  uf.backend = copy 
 458  uf.menu_text = "&parameter_copy" 
 459  uf.gui_icon = "oxygen.actions.list-add" 
 460  uf.wizard_size = (800, 500) 
 461  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 462   
 463   
 464  # The relax_disp.plot_disp_curves user function. 
 465  uf = uf_info.add_uf('relax_disp.plot_disp_curves') 
 466  uf.title = "Create 2D Grace plots of the dispersion curves for each spin system." 
 467  uf.title_short = "Dispersion curve plotting." 
 468  uf.add_keyarg( 
 469      name = "dir", 
 470      default = "grace", 
 471      py_type = "str", 
 472      arg_type = "dir sel", 
 473      desc_short = "directory name", 
 474      desc = "The directory name to place all of the spin system files into.", 
 475      can_be_none = True 
 476  ) 
 477  uf.add_keyarg( 
 478      name = "y_axis", 
 479      default = Y_AXIS_R2_EFF, 
 480      py_type = "str", 
 481      desc_short = "Y axis data type", 
 482      desc = "Option can be either '%s' which plot 'r2eff' for CPMG experiments or 'r1rho' for R1rho experiments or option can be '%s', which for R1rho experiments plot R2."%(Y_AXIS_R2_EFF, Y_AXIS_R2_R1RHO), 
 483      wiz_element_type = 'combo', 
 484      wiz_combo_choices = [ 
 485          "%s/%s for CPMG/%s experiments"%(r2eff, r1rho, r1rho), 
 486          "%s for %s experiments"%(r2, r1rho) 
 487      ], 
 488      wiz_combo_data = [Y_AXIS_R2_EFF, Y_AXIS_R2_R1RHO], 
 489      wiz_read_only = True 
 490  ) 
 491  uf.add_keyarg( 
 492      name = "x_axis", 
 493      default = X_AXIS_DISP, 
 494      py_type = "str", 
 495      desc_short = "X axis data type", 
 496      desc = "Option can be either '%s' which plot 'CPMG frequency (Hz)' for CPMG experiments or 'Spin-lock field strength (Hz)' for R1rho experiments or option can be either '%s' or '%s' for R1rho experiments, which plot 'Effective field in rotating frame (rad/s)' or 'Rotating frame tilt angle theta (rad)'"%(X_AXIS_DISP, X_AXIS_W_EFF, X_AXIS_THETA), 
 497      wiz_element_type = 'combo', 
 498      wiz_combo_choices = [ 
 499          "CPMG %s (Hz)/Spin-lock %s (Hz)"%(nu_cpmg, nu_1), 
 500          "Eff. field in rot. frame %s (rad/s)"%(w_eff), 
 501          "Rot. frame tilt ang. %s (rad)"%(theta) 
 502      ], 
 503      wiz_combo_data = [X_AXIS_DISP, X_AXIS_W_EFF, X_AXIS_THETA], 
 504      wiz_read_only = True 
 505  ) 
 506  uf.add_keyarg( 
 507      name = "num_points", 
 508      default = 1000, 
 509      min = 1, 
 510      max = 10000000, 
 511      py_type = "int", 
 512      desc_short = "total number of interpolation points", 
 513      desc = "The total number of points to generate the interpolated dispersion curves with.  This value has no effect for the numeric CPMG-based models.", 
 514      can_be_none = False 
 515  ) 
 516  uf.add_keyarg( 
 517      name = "extend_hz", 
 518      py_type = "num", 
 519      default = 500.0, 
 520      desc_short = "interpolated dispersion curve extension (in Hz)", 
 521      desc = "How far to extend the interpolated dispersion curves beyond the last dispersion point, i.e. the nu_CPMG frequency or spin-lock field strength value, in Hertz.", 
 522      can_be_none = False 
 523  ) 
 524  uf.add_keyarg( 
 525      name = "extend_ppm", 
 526      py_type = "num", 
 527      default = 500.0, 
 528      desc_short = "interpolated offset curve extension (in ppm)", 
 529      desc = "How far to extend the interpolated dispersion curves beyond the last dispersion point, i.e. the spin-lock offset value, in ppm.", 
 530      can_be_none = False 
 531  ) 
 532  uf.add_keyarg( 
 533      name = "interpolate", 
 534      default = INTERPOLATE_DISP, 
 535      py_type = "str", 
 536      desc_short = "option to interpolate the fitted curves", 
 537      desc = "Either by option '%s' which interpolate CPMG frequency or spin-lock field strength, or by option '%s' which interpole over spin-lock offset."%(INTERPOLATE_DISP, INTERPOLATE_OFFSET), 
 538      wiz_element_type = 'combo', 
 539      wiz_combo_choices = [ 
 540          "Interpolate CPMG %s (Hz)/Spin-lock %s (Hz)"%(nu_cpmg, nu_1), 
 541          "Interpolate Spin-lock %s (ppm)"%(w_rf) 
 542      ], 
 543      wiz_combo_data = [INTERPOLATE_DISP, INTERPOLATE_OFFSET], 
 544      wiz_read_only = True 
 545  ) 
 546  uf.add_keyarg( 
 547      name = "force", 
 548      default = False, 
 549      py_type = "bool", 
 550      desc_short = "force flag", 
 551      desc = "A flag which, if set to True, will cause the files to be overwritten." 
 552  ) 
 553  # Description. 
 554  uf.desc.append(Desc_container()) 
 555  uf.desc[-1].add_paragraph("This is used to create 2D Grace plots of the dispersion curves of the nu_CPMG frequencies or spin-lock field strength verses the R2eff/R1rho values.  One file will be created per spin system with the name 'disp_x.agr', where x is related to the spin ID string.  For each file, one Grace graph will be produced for each experiment.") 
 556  uf.desc[-1].add_paragraph("Four sets of curves of R2eff/R1rho values will be produced per experiment and per magnetic field strength.  These are the experimental values, the fitted values, the interpolated dispersion curves for the fitted solution, and the residuals.  Different dispersion models result in different interpolated dispersion curves.  For the numeric models which use CPMG-type data, the maximum interpolation resolution is constrained by the frequency of a single CPMG block for the entire relaxation period.  For all other models, the interpolation resolution is not constrained and can be as fine as desired by setting the total number of interpolation points.  Interpolated curves are not produced for the 'R2eff' model as they are not necessary.") 
 557  uf.desc[-1].add_paragraph("For R1rho models, graphs can be interpolated against Spin-lock offset, but this feature is not available for CPMG experiment types.  It is also possible to select values on X-axis of 'Effective field in rotating frame %s (rad/s)' or 'Rotating frame tilt angle %s (rad)'."%("w_eff", "theta")) 
 558  uf.desc[-1].add_paragraph("For R1rho models, special Y-value %s %s can for example be plotted as function of %s.  %s is calculated as: %s=(%s - %s cos^2(%s)) / sin^2(%s)."%("R2", "R1rho", "w_eff", "R2", "R2", "R1rho", "R1", "theta", "theta")) 
 559  uf.backend = plot_disp_curves 
 560  uf.menu_text = "&plot_disp_curves" 
 561  uf.gui_icon = "oxygen.actions.document-save" 
 562  uf.wizard_size = (950, 700) 
 563  uf.wizard_image = WIZARD_IMAGE_PATH + 'grace.png' 
 564   
 565   
 566  # The relax_disp.plot_exp_curves user function. 
 567  uf = uf_info.add_uf('relax_disp.plot_exp_curves') 
 568  uf.title = "Create 2D Grace plots of the exponential curves." 
 569  uf.title_short = "Exponential curve plotting." 
 570  uf.add_keyarg( 
 571      name = "file", 
 572      py_type = "str", 
 573      arg_type = "file sel", 
 574      desc_short = "file name", 
 575      desc = "The name of the file.", 
 576      wiz_filesel_wildcard = WILDCARD_GRACE_ALL, 
 577      wiz_filesel_style = FD_SAVE 
 578  ) 
 579  uf.add_keyarg( 
 580      name = "dir", 
 581      default = "grace", 
 582      py_type = "str", 
 583      arg_type = "dir", 
 584      desc_short = "directory name", 
 585      desc = "The directory name.", 
 586      can_be_none = True 
 587  ) 
 588  uf.add_keyarg( 
 589      name = "force", 
 590      default = False, 
 591      py_type = "bool", 
 592      desc_short = "force flag", 
 593      desc = "A flag which, if set to True, will cause the file to be overwritten." 
 594  ) 
 595  uf.add_keyarg( 
 596      name = "norm", 
 597      default = False, 
 598      py_type = "bool", 
 599      desc_short = "normalisation flag", 
 600      desc = "A flag which, if set to True, will cause all graphs to be normalised to a starting value of 1.  This is for the normalisation of series type data." 
 601  ) 
 602  # Description. 
 603  uf.desc.append(Desc_container()) 
 604  uf.desc[-1].add_paragraph("This is used to create 2D Grace plots of the individual exponential curves used to find the R2eff or R1rho values.  This supplements the grace.write user function which is not capable of generating these curves in a reasonable format.") 
 605  uf.backend = plot_exp_curves 
 606  uf.menu_text = "&plot_exp_curves" 
 607  uf.gui_icon = "oxygen.actions.document-save" 
 608  uf.wizard_size = (800, 600) 
 609  uf.wizard_image = WIZARD_IMAGE_PATH + 'grace.png' 
 610   
 611   
 612  # The relax_disp.r1_fit user function. 
 613  uf = uf_info.add_uf('relax_disp.r1_fit') 
 614  uf.title = "Switch between fixed or fitted R1 values for optimisation." 
 615  uf.title_short = "R1 optimisation flag." 
 616  uf.add_keyarg( 
 617      name = "fit", 
 618      default = True, 
 619      py_type = "bool", 
 620      desc_short = "R1 optimisation flag", 
 621      desc = "The flag specifying if R1 values should be optimised or if loaded R1 values should be fixed during optimisation." 
 622  ) 
 623  # Description. 
 624  uf.desc.append(Desc_container()) 
 625  uf.desc[-1].add_paragraph("This user function allows the optimisation of R1 values to be turned on an off for the relaxation dispersion dispersion models.  If turned off, the current values of R1 will be fixed.  Otherwise the R1 values will be added to the model parameter set.  For models which do not support the R1 parameter for off-resonance effects, this setting will have no effect.  Only the models %s support R1 optimisation." % MODEL_LIST_FIT_R1) 
 626  uf.backend = relax_disp_uf.r1_fit 
 627  uf.menu_text = "r&1_fit" 
 628  uf.gui_icon = "oxygen.status.object-locked" 
 629  uf.wizard_size = (800, 500) 
 630  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 631   
 632   
 633  # The relax_disp.r2eff_err_estimate user function. 
 634  uf = uf_info.add_uf('relax_disp.r2eff_err_estimate') 
 635  uf.title = "Estimate R2eff errors by the Jacobian matrix." 
 636  uf.title_short = "Estimate R2eff errors." 
 637  uf.add_keyarg( 
 638      name = "spin_id", 
 639      py_type = "str", 
 640      arg_type = "spin ID", 
 641      desc_short = "spin ID to restrict value setting to", 
 642      desc = "The spin ID string to restrict value setting to.", 
 643      can_be_none = True 
 644  ) 
 645  uf.add_keyarg( 
 646      name = "epsrel", 
 647      py_type = "float", 
 648      default = 0.0, 
 649      desc_short = "parameter to remove linear-dependent columns.", 
 650      desc = "The parameter to remove linear-dependent columns when J is rank deficient.", 
 651      can_be_none = False 
 652  ) 
 653  uf.add_keyarg( 
 654      name = "verbosity", 
 655      default = 1, 
 656      py_type = "int", 
 657      desc_short = "amount of information to print.", 
 658      desc = "The higher the value, the greater the verbosity.", 
 659      can_be_none = False 
 660  ) 
 661  # Description. 
 662  uf.desc.append(Desc_container()) 
 663  uf.desc[-1].add_paragraph("This is a new experimental feature from version 3.3.") 
 664  uf.desc[-1].add_paragraph("This will estimate R2eff errors by using the exponential decay Jacobian matrix 'J' to compute the covariance matrix of the best-fit parameters.") 
 665  uf.desc[-1].add_paragraph("This can be an huge time saving step, when performing model fitting in R1rho.  Errors of R2eff values, are normally estimated by time-consuming Monte-Carlo simulations.") 
 666  uf.desc[-1].add_paragraph("This method is inspired from the GNU Scientific Library (GSL).") 
 667  uf.desc[-1].add_paragraph("The covariance matrix is given by: covar = Qxx = (J^T.W.J)^-1, where the weight matrix W is constructed by the multiplication of an Identity matrix I and a weight array w.  The weight array is 1/errors^2, which then gives W = I.w = I x 1/errors^2.") 
 668  uf.desc[-1].add_paragraph("Qxx is computed by QR decomposition, J^T.W.J=QR, Qxx=R^-1. Q^T.  The columns of R which satisfy: |R_{kk}| <= epsrel |R_{11}| are considered linearly-dependent and are excluded from the covariance matrix (the corresponding rows and columns of the covariance matrix are set to zero).") 
 669  uf.desc[-1].add_paragraph("The parameter 'epsrel' is used to remove linear-dependent columns when J is rank deficient.") 
 670  uf.backend = estimate_r2eff_err 
 671  uf.menu_text = "&r2eff_err_estimate" 
 672  uf.gui_icon = "relax.relax_fit" 
 673  uf.wizard_size = (800, 800) 
 674  uf.wizard_image = ANALYSIS_IMAGE_PATH + sep + 'blank_150x150.png' 
 675   
 676   
 677  # The relax_disp.r2eff_read user function. 
 678  uf = uf_info.add_uf('relax_disp.r2eff_read') 
 679  uf.title = "Read R2eff/R1rho values and errors from a file." 
 680  uf.title_short = "R2eff/R1rho value reading." 
 681  uf.add_keyarg( 
 682      name = "id", 
 683      py_type = "str", 
 684      desc_short = "partial experiment ID string", 
 685      desc = "The partial experiment ID string to identify this data with.  The full ID string will be constructed as this ID followed by an underscore and then the dispersion point value from the file.", 
 686      wiz_element_type = 'combo', 
 687      wiz_combo_iter = spectrum.get_ids, 
 688      wiz_read_only = True 
 689  ) 
 690  uf.add_keyarg( 
 691      name = "file", 
 692      py_type = "str", 
 693      arg_type = "file sel", 
 694      desc_short = "file name", 
 695      desc = "The name of the file.", 
 696      wiz_filesel_style = FD_SAVE 
 697  ) 
 698  uf.add_keyarg( 
 699      name = "dir", 
 700      py_type = "str", 
 701      arg_type = "dir", 
 702      desc_short = "directory name", 
 703      desc = "The directory name.", 
 704      can_be_none = True 
 705  ) 
 706  uf.add_keyarg( 
 707      name = "disp_frq", 
 708      py_type = "num", 
 709      desc_short = "CPMG frequency or spin-lock field strength (Hz)", 
 710      desc = "For CPMG-type data, the frequency of the CPMG pulse train.  For R1rho-type data, the spin-lock field strength nu1.  The units must be Hertz", 
 711      can_be_none = True 
 712  ) 
 713  uf.add_keyarg( 
 714      name = "spin_id_col", 
 715      py_type = "int", 
 716      arg_type = "free format", 
 717      desc_short = "spin ID string column", 
 718      desc = "The spin ID string column used by the generic file format (an alternative to the mol, res, and spin name and number columns).", 
 719      can_be_none = True 
 720  ) 
 721  uf.add_keyarg( 
 722      name = "mol_name_col", 
 723      py_type = "int", 
 724      arg_type = "free format", 
 725      desc_short = "molecule name column", 
 726      desc = "The molecule name column used by the generic file format (alternative to the spin ID column).", 
 727      can_be_none = True 
 728  ) 
 729  uf.add_keyarg( 
 730      name = "res_num_col", 
 731      py_type = "int", 
 732      arg_type = "free format", 
 733      desc_short = "residue number column", 
 734      desc = "The residue number column used by the generic file format (alternative to the spin ID column).", 
 735      can_be_none = True 
 736  ) 
 737  uf.add_keyarg( 
 738      name = "res_name_col", 
 739      py_type = "int", 
 740      arg_type = "free format", 
 741      desc_short = "residue name column", 
 742      desc = "The residue name column used by the generic file format (alternative to the spin ID column).", 
 743      can_be_none = True 
 744  ) 
 745  uf.add_keyarg( 
 746      name = "spin_num_col", 
 747      py_type = "int", 
 748      arg_type = "free format", 
 749      desc_short = "spin number column", 
 750      desc = "The spin number column used by the generic file format (alternative to the spin ID column).", 
 751      can_be_none = True 
 752  ) 
 753  uf.add_keyarg( 
 754      name = "spin_name_col", 
 755      py_type = "int", 
 756      arg_type = "free format", 
 757      desc_short = "spin name column", 
 758      desc = "The spin name column used by the generic file format (alternative to the spin ID column).", 
 759      can_be_none = True 
 760  ) 
 761  uf.add_keyarg( 
 762      name = "data_col", 
 763      py_type = "int", 
 764      arg_type = "free format", 
 765      desc_short = "data column", 
 766      desc = "The RDC data column.", 
 767      can_be_none = True 
 768  ) 
 769  uf.add_keyarg( 
 770      name = "error_col", 
 771      py_type = "int", 
 772      arg_type = "free format", 
 773      desc_short = "error column", 
 774      desc = "The experimental error column.", 
 775      can_be_none = True 
 776  ) 
 777  uf.add_keyarg( 
 778      name = "sep", 
 779      py_type = "str", 
 780      arg_type = "free format", 
 781      desc_short = "column separator", 
 782      desc = "The column separator used by the generic format (the default is white space).", 
 783      can_be_none = True 
 784  ) 
 785  # Description. 
 786  uf.desc.append(Desc_container()) 
 787  uf.desc[-1].add_paragraph("This will read R2eff/R1rho data directly from a file.  The data will be associated with an experiment ID string.  A partial ID is to be supplied and then the full ID string will be constructed as this ID followed by an underscore and then the dispersion point value from the file (as '%s_%s' % (id, disp_point)).  The full IDs must already exist and have been used to set the type of dispersion experiment the data is from, spectrometer proton frequency of the data, and if needed the time of the relaxation period.") 
 788  uf.desc[-1].add_paragraph("The format of this text file must be that each row corresponds to a unique spin system and that there is one file per dispersion point (i.e. per CPMG frequency nu_CPMG or per spin-lock field strength nu1).  The file must be in columnar format and information to identify the spin must be in columns of the file.") 
 789  uf.backend = r2eff_read 
 790  uf.menu_text = "&r2eff_read" 
 791  uf.gui_icon = "oxygen.actions.document-open" 
 792  uf.wizard_size = (1000, 600) 
 793  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 794   
 795   
 796  # The relax_disp.r2eff_read_spin user function. 
 797  uf = uf_info.add_uf('relax_disp.r2eff_read_spin') 
 798  uf.title = "Read R2eff/R1rho values and errors for a single spin from a file." 
 799  uf.title_short = "Spin R2eff/R1rho value reading." 
 800  uf.add_keyarg( 
 801      name = "id", 
 802      py_type = "str", 
 803      desc_short = "experiment ID string", 
 804      desc = "The experiment ID string to identify this data with.", 
 805      wiz_element_type = 'combo', 
 806      wiz_combo_iter = spectrum.get_ids, 
 807      wiz_read_only = True 
 808  ) 
 809  uf.add_keyarg( 
 810      name = "spin_id", 
 811      py_type = "str", 
 812      arg_type = "spin ID", 
 813      desc_short = "spin ID string", 
 814      desc = "The spin identification string.", 
 815      can_be_none = True 
 816  ) 
 817  uf.add_keyarg( 
 818      name = "file", 
 819      py_type = "str", 
 820      arg_type = "file sel", 
 821      desc_short = "file name", 
 822      desc = "The name of the file.", 
 823      wiz_filesel_style = FD_SAVE 
 824  ) 
 825  uf.add_keyarg( 
 826      name = "dir", 
 827      py_type = "str", 
 828      arg_type = "dir", 
 829      desc_short = "directory name", 
 830      desc = "The directory name.", 
 831      can_be_none = True 
 832  ) 
 833  uf.add_keyarg( 
 834      name = "disp_point_col", 
 835      default = None, 
 836      min = 1, 
 837      py_type = "int", 
 838      desc_short = "dispersion point column", 
 839      desc = "The column containing the CPMG frequency or spin-lock field strength (Hz).", 
 840      can_be_none = True 
 841  ) 
 842  uf.add_keyarg( 
 843      name = "offset_col", 
 844      default = None, 
 845      min = 1, 
 846      py_type = "int", 
 847      desc_short = "offset column", 
 848      desc = "The column containing the offset information for R1rho-type data.", 
 849      can_be_none = True 
 850  ) 
 851  uf.add_keyarg( 
 852      name = "data_col", 
 853      default = 2, 
 854      min = 1, 
 855      py_type = "int", 
 856      desc_short = "R2eff/R1rho data column", 
 857      desc = "The column containing the R2eff or R1rho data." 
 858  ) 
 859  uf.add_keyarg( 
 860      name = "error_col", 
 861      default = 3, 
 862      min = 1, 
 863      py_type = "int", 
 864      desc_short = "R2eff/R1rho error column", 
 865      desc = "The column containing the R2eff or R1rho error." 
 866  ) 
 867  uf.add_keyarg( 
 868      name = "sep", 
 869      py_type = "str", 
 870      desc_short = "column separator", 
 871      desc = "The column separator (the default is white space).", 
 872      wiz_element_type = "combo", 
 873      wiz_combo_choices = [",", ";", "\\t"], 
 874      can_be_none = True 
 875  ) 
 876  # Description. 
 877  uf.desc.append(Desc_container()) 
 878  uf.desc[-1].add_paragraph("This will read R2eff/R1rho data for a single spin directly from a file.  The data will be associated with an experiment ID string.  This ID can be used for setting the type of dispersion experiment the data is from, spectrometer proton frequency of the data, and the time of the relaxation period.") 
 879  uf.desc[-1].add_paragraph("The format of this text file must be that each row corresponds to a dispersion point (i.e. per CPMG frequency nu_CPMG or per spin-lock field strength nu1) and that there is one file per unique spin system.  The file must be in columnar format.  For R1rho data, the dispersion point column can be substituted for the offset values in Hertz.") 
 880  uf.backend = r2eff_read_spin 
 881  uf.menu_text = "&r2eff_read_spin" 
 882  uf.gui_icon = "oxygen.actions.document-open" 
 883  uf.wizard_size = (900, 700) 
 884  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 885   
 886   
 887  # The relax_disp.relax_time user function. 
 888  uf = uf_info.add_uf('relax_disp.relax_time') 
 889  uf.title = "Set the relaxation delay time associated with each spectrum." 
 890  uf.title_short = "Relaxation delay time setting." 
 891  uf.add_keyarg( 
 892      name = "spectrum_id", 
 893      py_type = "str", 
 894      desc_short = "spectrum ID string", 
 895      desc = "The spectrum ID string.", 
 896      wiz_element_type = 'combo', 
 897      wiz_combo_iter = spectrum.get_ids, 
 898      wiz_read_only = True 
 899  ) 
 900  uf.add_keyarg( 
 901      name = "time", 
 902      default = 0.0, 
 903      py_type = "num", 
 904      desc_short = "relaxation time", 
 905      desc = "The time, in seconds, of the relaxation period." 
 906  ) 
 907  # Description. 
 908  uf.desc.append(Desc_container()) 
 909  uf.desc[-1].add_paragraph("Peak intensities should be loaded before calling this user function via the spectrum.read_intensities user function.  The intensity values will then be associated with a spectrum identifier.  To associate each spectrum identifier with a time point in the relaxation curve prior to optimisation, this user function should be called.") 
 910  uf.backend = relax_time 
 911  uf.menu_text = "&relax_time" 
 912  uf.gui_icon = "oxygen.actions.chronometer" 
 913  uf.wizard_size = (800, 500) 
 914  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 915   
 916   
 917  # The relax_disp.select_model user function. 
 918  uf = uf_info.add_uf('relax_disp.select_model') 
 919  uf.title = "Select the relaxation dispersion model." 
 920  uf.title_short = "Relaxation dispersion model setup." 
 921  uf.display = True 
 922  uf.add_keyarg( 
 923      name = "model", 
 924      default = MODEL_R2EFF, 
 925      py_type = "str", 
 926      desc_short = "dispersion model", 
 927      desc = "The type of relaxation dispersion model to fit.", 
 928      wiz_element_type = "combo", 
 929      wiz_combo_choices = [ 
 930          "%s: {%s/%s, %s}" % (MODEL_R2EFF, r2eff, r1rho, i0), 
 931          "%s: {%s, ...}" % (MODEL_NOREX, r2), 
 932          "%s: {%s, ..., %s, %s}" % (MODEL_LM63, r2, phi_ex, kex), 
 933          "%s: {%s, ..., %s, kB, %s, kC}" % (MODEL_LM63_3SITE, r2, phi_exB, phi_exC), 
 934          "%s: {%s, ..., pA, %s, %s}" % (MODEL_CR72, r2, dw, kex), 
 935          "%s: {%s, %s, ..., pA, %s, %s}" % (MODEL_CR72_FULL, r2a, r2b, dw, kex), 
 936          "%s: {%s, ..., pA, %s, %s}" % (MODEL_IT99, r2, dw, tex), 
 937          "%s: {%s, ..., %s, k_AB}" % (MODEL_TSMFK01, r2a, dw), 
 938          "%s: {%s, ..., pA, %s, %s}" % (MODEL_B14, r2, dw, kex), 
 939          "%s: {%s, %s, ..., pA, %s, %s}" % (MODEL_B14_FULL, r2a, r2b, dw, kex), 
 940          "%s: {%s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_3D, r2, dw, kex), 
 941          "%s: {%s, %s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_3D_FULL, r2a, r2b, dw, kex), 
 942          "%s: {%s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_STAR, r2, dw, kex), 
 943          "%s: {%s, %s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_STAR_FULL, r2a, r2b, dw, kex), 
 944          "%s: {%s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_EXPANDED, r2, dw, kex), 
 945          "%s: {%s, ..., pA, %s, %s, %s}" % (MODEL_MMQ_CR72, r2, dw, dwH, kex), 
 946          "%s: {%s, ..., pA, %s, %s, %s}" % (MODEL_NS_MMQ_2SITE, r2, dw, dwH, kex), 
 947          "%s: {%s, ..., pA, %s, %s, %s, pB, %s, %s, %s}" % (MODEL_NS_MMQ_3SITE_LINEAR, r2, dw_AB, dwH_AB, kAB, dw_BC, dwH_BC, kBC), 
 948          "%s: {%s, ..., pA, %s, %s, %s, pB, %s, %s, %s, %s}" % (MODEL_NS_MMQ_3SITE, r2, dw_AB, dwH_AB, kAB, dw_BC, dwH_BC, kBC, kAC), 
 949          "%s: {%s, ..., %s, %s}" % (MODEL_M61, r1rho_prime, phi_ex, kex), 
 950          "%s: {%s, ..., pA, %s, %s}" % (MODEL_M61B, r1rho_prime, dw, kex), 
 951          "%s: {%s, ..., %s, %s}" % (MODEL_DPL94, r1rho_prime, phi_ex, kex), 
 952          "%s: {%s, ..., pA, %s, %s}" % (MODEL_TP02, r1rho_prime, dw, kex), 
 953          "%s: {%s, ..., pA, %s, %s}" % (MODEL_TAP03, r1rho_prime, dw, kex), 
 954          "%s: {%s, ..., pA, %s, %s}" % (MODEL_MP05, r1rho_prime, dw, kex), 
 955          "%s: {%s, ..., pA, %s, %s}" % (MODEL_NS_R1RHO_2SITE, r1rho_prime, dw, kex), 
 956          "%s: {%s, ..., pA, %s, %s, pB, %s, %s}" % (MODEL_NS_R1RHO_3SITE_LINEAR, r2, dw_AB, kAB, dw_BC, kBC), 
 957          "%s: {%s, ..., pA, %s, %s, pB, %s, %s, %s}" % (MODEL_NS_R1RHO_3SITE, r2, dw_AB, kAB, dw_BC, kBC, kAC) 
 958      ], 
 959      wiz_combo_data = [ 
 960          MODEL_R2EFF, 
 961          MODEL_NOREX, 
 962          MODEL_LM63, 
 963          MODEL_LM63_3SITE, 
 964          MODEL_CR72, 
 965          MODEL_CR72_FULL, 
 966          MODEL_IT99, 
 967          MODEL_TSMFK01, 
 968          MODEL_B14, 
 969          MODEL_B14_FULL, 
 970          MODEL_NS_CPMG_2SITE_3D, 
 971          MODEL_NS_CPMG_2SITE_3D_FULL, 
 972          MODEL_NS_CPMG_2SITE_STAR, 
 973          MODEL_NS_CPMG_2SITE_STAR_FULL, 
 974          MODEL_NS_CPMG_2SITE_EXPANDED, 
 975          MODEL_MMQ_CR72, 
 976          MODEL_NS_MMQ_2SITE, 
 977          MODEL_NS_MMQ_3SITE_LINEAR, 
 978          MODEL_NS_MMQ_3SITE, 
 979          MODEL_M61, 
 980          MODEL_M61B, 
 981          MODEL_DPL94, 
 982          MODEL_TP02, 
 983          MODEL_TAP03, 
 984          MODEL_MP05, 
 985          MODEL_NS_R1RHO_2SITE, 
 986          MODEL_NS_R1RHO_3SITE_LINEAR, 
 987          MODEL_NS_R1RHO_3SITE 
 988      ], 
 989      wiz_read_only = True 
 990  ) 
 991  # Description. 
 992  uf.desc.append(Desc_container()) 
 993  uf.desc[-1].add_paragraph("A number of different dispersion models are supported.  This includes both analytic models and numerical models.  Models which are independent of the experimental data type are:") 
 994  uf.desc[-1].add_item_list_element("'%s'" % MODEL_R2EFF, "This is the model used to determine the R2eff/R1rho values and errors required as the base data for all other models,") 
 995  uf.desc.append(Desc_container('The no chemical exchange models')) 
 996  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NOREX, "This is the model for no chemical exchange being present.") 
 997  # CPMG-type data. 
 998  uf.desc.append(Desc_container('The SQ CPMG-type experiments')) 
 999  uf.desc[-1].add_paragraph("The currently supported analytic models are:") 
1000  uf.desc[-1].add_item_list_element("'%s'" % MODEL_LM63, "The original Luz and Meiboom (1963) 2-site fast exchange equation with parameters {R20, ..., phi_ex, kex},") 
1001  uf.desc[-1].add_item_list_element("'%s'" % MODEL_LM63_3SITE, "The original Luz and Meiboom (1963) 3-site fast exchange equation with parameters {R20, ..., phi_ex, kex, phi_ex2, kex2},") 
1002  uf.desc[-1].add_item_list_element("'%s'" % MODEL_CR72, "The reduced Carver and Richards (1972) 2-site equation for most time scales whereby the simplification R20A = R20B is assumed.  The parameters are {R20, ..., pA, dw, kex},") 
1003  uf.desc[-1].add_item_list_element("'%s'" % MODEL_CR72_FULL, "The full Carver and Richards (1972) 2-site equation for most time scales with parameters {R20A, R20B, ..., pA, dw, kex},") 
1004  uf.desc[-1].add_item_list_element("'%s'" % MODEL_IT99, "The Ishima and Torchia (1999) 2-site model for all time scales with pA >> pB and with parameters {R20, ..., pA, dw, kex},") 
1005  uf.desc[-1].add_item_list_element("'%s'" % MODEL_TSMFK01, "The Tollinger, Kay et al. (2001) 2-site very-slow exchange model, range of microsecond to second time scale.  Applicable in the limit of slow exchange, when |R20A-R20B| << k_AB,kB << 1/tau_CP.  R20A is the transverse relaxation rate of site A in the absence of exchange.  2*tau_CP is is the time between successive 180 deg. pulses.  The parameters are {R20A, ..., dw, k_AB}.") 
1006  uf.desc[-1].add_item_list_element("'%s'" % MODEL_B14, "The Baldwin (2014) 2-site exact solution model for all time scales, whereby the simplification R20A = R20B is assumed. The parameters are {R20, ..., pA, dw, kex},") 
1007  uf.desc[-1].add_item_list_element("'%s'" % MODEL_B14_FULL, "The Baldwin (2014) 2-site exact solution model for all time scales with parameters {R20A, R20B, ..., pA, dw, kex},") 
1008  uf.desc[-1].add_paragraph("The currently supported numeric models are:") 
1009  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_CPMG_2SITE_3D, "The reduced numerical solution for the 2-site Bloch-McConnell equations using 3D magnetisation vectors whereby the simplification R20A = R20B is assumed.  Its parameters are {R20, ..., pA, dw, kex},") 
1010  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_CPMG_2SITE_3D_FULL, "The full numerical solution for the 2-site Bloch-McConnell equations using 3D magnetisation vectors.  Its parameters are {R20A, R20B, ..., pA, dw, kex},") 
1011  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_CPMG_2SITE_STAR, "The reduced numerical solution for the 2-site Bloch-McConnell equations using complex conjugate matrices whereby the simplification R20A = R20B is assumed.  It has the parameters {R20, ..., pA, dw, kex},") 
1012  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_CPMG_2SITE_STAR_FULL, "The full numerical solution for the 2-site Bloch-McConnell equations using complex conjugate matrices with parameters {R20A, R20B, ..., pA, dw, kex},") 
1013  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_CPMG_2SITE_EXPANDED, "The numerical solution for the 2-site Bloch-McConnell equations expanded using Maple by Nikolai Skrynnikov.  It has the parameters {R20, ..., pA, dw, kex}.") 
1014  # MMQ CPMG-type data. 
1015  uf.desc.append(Desc_container('The MMQ CPMG-type experiments')) 
1016  uf.desc[-1].add_paragraph("The currently supported models are:") 
1017  uf.desc[-1].add_item_list_element("'%s'" % MODEL_MMQ_CR72, "The the Carver and Richards (1972) 2-site model for most time scales expanded for MMQ CPMG data by Korzhnev et al., 2004, whereby the simplification R20A = R20B is assumed.  Its parameters are {R20, ..., pA, dw, dwH, kex}.") 
1018  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_MMQ_2SITE, "The numerical solution for the 2-site Bloch-McConnell equations for combined proton-heteronuclear SQ, ZQ, DQ, and MQ CPMG data whereby the simplification R20A = R20B is assumed.  Its parameters are {R20, ..., pA, dw, dwH, kex}.") 
1019  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_MMQ_3SITE_LINEAR, "The numerical solution for the 3-site Bloch-McConnell equations linearised with kAC = kCA = 0 for combined proton-heteronuclear SQ, ZQ, DQ, and MQ CPMG data whereby the simplification R20A = R20B = R20C is assumed.  Its parameters are {R20, ..., pA, dw(AB), dwH(AB), kex(AB), pB, dw(BC), dwH(BC), kex(BC)}.") 
1020  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_MMQ_3SITE, "The numerical solution for the 3-site Bloch-McConnell equations for combined proton-heteronuclear SQ, ZQ, DQ, and MQ CPMG data whereby the simplification R20A = R20B = R20C is assumed.  Its parameters are {R20, ..., pA, dw(AB), dwH(AB), kex(AB), pB, dw(BC), dwH(BC), kex(BC), kex(AC)}.") 
1021  # R1rho-type data. 
1022  uf.desc.append(Desc_container('The R1rho-type experiments')) 
1023  uf.desc[-1].add_paragraph("The currently supported analytic models are:") 
1024  uf.desc[-1].add_paragraph("On-resonance models are:") 
1025  uf.desc[-1].add_item_list_element("'%s'" % MODEL_M61, "The Meiboom (1961) 2-site fast exchange equation with parameters {R1rho', ..., phi_ex, kex},") 
1026  uf.desc[-1].add_item_list_element("'%s'" % MODEL_M61B, "The Meiboom (1961) 2-site equation for all time scales with pA >> pB and with parameters {R1rho', ..., pA, dw, kex},") 
1027  uf.desc[-1].add_paragraph("Off-resonance models are:") 
1028  uf.desc[-1].add_item_list_element("'%s'" % MODEL_DPL94, "The Davis, Perlman and London (1994) 2-site fast exchange equation with parameters {R1rho', ..., phi_ex, kex},") 
1029  uf.desc[-1].add_item_list_element("'%s'" % MODEL_TP02, "The Trott and Palmer (2002) 2-site equation for all time scales with parameters {R1rho', ..., pA, dw, kex}.") 
1030  uf.desc[-1].add_item_list_element("'%s'" % MODEL_TAP03, "The Trott, Abergel and Palmer (2003) off-resonance 2-site equation for all time scales with parameters {R1rho', ..., pA, dw, kex}.") 
1031  uf.desc[-1].add_item_list_element("'%s'" % MODEL_MP05, "The Miloushev and Palmer (2005) 2-site off-resonance equation for all time scales with parameters {R1rho', ..., pA, dw, kex}.") 
1032  uf.desc[-1].add_paragraph("The currently supported numeric models are:") 
1033  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_R1RHO_2SITE, "The numerical solution for the 2-site Bloch-McConnell equations using 3D magnetisation vectors whereby the simplification R20A = R20B.  Its parameters are {R1rho', ..., pA, dw, kex}.") 
1034  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_R1RHO_3SITE_LINEAR, "The numerical solution for the 3-site Bloch-McConnell equations using 3D magnetisation vectors whereby the simplification R20A = R20B = R20C is assumed and linearised with kAC = kCA = 0.  Its parameters are {R1rho', ..., pA, dw(AB), kex(AB), pB, dw(BC), kex(BC)}.") 
1035  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NS_R1RHO_3SITE, "The numerical solution for the 3-site Bloch-McConnell equations using 3D magnetisation vectors.  Its parameters are {R1rho', ..., pA, dw(AB), kex(AB), pB, dw(BC), kex(BC), kex(AC)}.") 
1036  # Prompt examples. 
1037  uf.desc.append(Desc_container("Prompt examples")) 
1038  uf.desc[-1].add_paragraph("To pick the 2-site fast exchange model for all selected spins, type one of:") 
1039  uf.desc[-1].add_prompt("relax> relax_disp.select_model('%s')" % MODEL_LM63) 
1040  uf.desc[-1].add_prompt("relax> relax_disp.select_model(model='%s')" % MODEL_LM63) 
1041  uf.backend = relax_disp_uf.select_model 
1042  uf.menu_text = "&select_model" 
1043  uf.gui_icon = "oxygen.actions.list-add" 
1044  uf.wizard_height_desc = 500 
1045  uf.wizard_size = (1000, 700) 
1046  uf.wizard_apply_button = False 
1047  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
1048   
1049   
1050  # The relax_disp.r20_from_min_r2eff user function. 
1051  uf = uf_info.add_uf('relax_disp.r20_from_min_r2eff') 
1052  uf.title = "Set the R20 parameter values to that of the minimum R2eff value." 
1053  uf.title_short = "Set R20 from the minimum R2eff." 
1054  uf.add_keyarg( 
1055      name = "force", 
1056      default = True, 
1057      py_type = "bool", 
1058      desc_short = "force flag", 
1059      desc = "A flag which if set to True will cause the R20 values to be overwritten if they already exist." 
1060  ) 
1061  # Description. 
1062  uf.desc.append(Desc_container()) 
1063  uf.desc[-1].add_paragraph("Set the R20 parameter values to that of the minimum R2eff value.  This user function will look through all R2eff values per magnetic field strength, find the minimum value, and set the R20, R20A, R20B, and R1rho' parameters of the model to this value.  This can serve a number of purposes including using the values for the chi-squared space mapping via the dx.map user function, speeding up optimisation by avoiding the grid search for these parameters, and as initial parameter values for other dispersion software.") 
1064  uf.desc[-1].add_paragraph("Instead of finding the initial values for the R20 parameter using the grid search, the minimum for the R2eff points can be used instead.  This is often a good initial position for minimisation.  For example for a two field CPMG experiment with model CR72, that would drop the number of uniform grid search points from 5D to 3D, i.e. two orders of magnitude faster.  When using the standard 21 grid increments per dimension, it would allow the grid search to be 441 times faster.  Note that the relaxation dispersion auto-analysis will take all pre-set parameter values into account and will automatically exclude these from the grid search.") 
1065  uf.desc[-1].add_paragraph("Note that for optimisation, that this is an experimental and unpublished feature of the dispersion analysis.  If R20 << min(R2eff), the grid search will be performed in a region of the optimisation space quite distant from the true minimum.  If unsure, do not activate this option, and let the grid search find a better starting value.") 
1066  uf.backend = r20_from_min_r2eff 
1067  uf.menu_text = "&r20_from_min_r2eff" 
1068  uf.gui_icon = "relax.grid_search" 
1069  uf.wizard_height_desc = 500 
1070  uf.wizard_size = (900, 600) 
1071  uf.wizard_apply_button = False 
1072   
1073   
1074  # The relax_disp.sherekhan_input user function. 
1075  uf = uf_info.add_uf('relax_disp.sherekhan_input') 
1076  uf.title = "Create the input files for Adam Mazur's ShereKhan program." 
1077  uf.title_short = "ShereKhan input file creation." 
1078  uf.add_keyarg( 
1079      name = "force", 
1080      default = False, 
1081      py_type = "bool", 
1082      desc_short = "force flag", 
1083      desc = "A flag which if set to True will cause the files to be overwritten if they already exist." 
1084  ) 
1085  uf.add_keyarg( 
1086      name = "spin_id", 
1087      py_type = "str", 
1088      desc_short = "spin ID string", 
1089      desc = "The spin identification string.", 
1090      can_be_none = True 
1091  ) 
1092  uf.add_keyarg( 
1093      name = "dir", 
1094      py_type = "str", 
1095      arg_type = "dir sel", 
1096      desc_short = "directory name", 
1097      desc = "The directory name to place ShereKhan cluster folders into.", 
1098      can_be_none = True 
1099  ) 
1100  # Description. 
1101  uf.desc.append(Desc_container()) 
1102  uf.desc[-1].add_paragraph("This creates the files required for the ShereKhan server located at http://sherekhan.bionmr.org/.  One file per spin cluster per field strength will be created.  These will be placed in the directory 'clusterx' and named 'sherekhan_frqy.in', where x is the cluster index starting from 1 and y is the magnetic field strength index starting from 1.") 
1103  uf.backend = sherekhan_input 
1104  uf.menu_text = "&sherekhan_input" 
1105  uf.gui_icon = "relax.sherekhan" 
1106  uf.wizard_size = (800, 500) 
1107  uf.wizard_apply_button = False 
1108  uf.wizard_image = WIZARD_IMAGE_PATH + 'sherekhan.png' 
1109   
1110   
1111  # The relax_disp.spin_lock_field user function. 
1112  uf = uf_info.add_uf('relax_disp.spin_lock_field') 
1113  uf.title = "Set the relaxation dispersion spin-lock field strength (nu1)." 
1114  uf.title_short = "Spin-lock field strength." 
1115  uf.add_keyarg( 
1116      name = "spectrum_id", 
1117      py_type = "str", 
1118      desc_short = "spectrum ID string", 
1119      desc = "The spectrum ID string to associate the spin-lock field strength to.", 
1120      wiz_element_type = 'combo', 
1121      wiz_combo_iter = spectrum.get_ids, 
1122      wiz_read_only = True 
1123  ) 
1124  uf.add_keyarg( 
1125      name = "field", 
1126      py_type = "num", 
1127      desc_short = "field strength nu1 (Hz)", 
1128      desc = "The spin-lock field strength, nu1, in Hz.", 
1129      can_be_none = True 
1130  ) 
1131  # Description. 
1132  uf.desc.append(Desc_container()) 
1133  uf.desc[-1].add_paragraph("This sets the spin-lock field strength, nu1, for the specified R1rho spectrum in Hertz.") 
1134  # Prompt examples. 
1135  uf.desc.append(Desc_container("Prompt examples")) 
1136  uf.desc[-1].add_paragraph("To set a spin-lock field strength of 2.1 kHz for the spectrum 'nu1_2.1kHz_relaxT_0.010', type one of:") 
1137  uf.desc[-1].add_prompt("relax> relax_disp.spin_lock_field(2100, 'nu1_2.1kHz_relaxT_0.010')") 
1138  uf.desc[-1].add_prompt("relax> relax_disp.spin_lock_field(field=2100, spectrum_id='nu1_2.1kHz_relaxT_0.010')") 
1139  uf.backend = spin_lock_field 
1140  uf.menu_text = "spin_lock_&field" 
1141  uf.wizard_size = (800, 500) 
1142  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
1143   
1144   
1145  # The relax_disp.spin_lock_offset user function. 
1146  uf = uf_info.add_uf('relax_disp.spin_lock_offset') 
1147  uf.title = "Set the relaxation dispersion spin-lock offset (omega_rf)." 
1148  uf.title_short = "Spin-lock offset." 
1149  uf.add_keyarg( 
1150      name = "spectrum_id", 
1151      py_type = "str", 
1152      desc_short = "spectrum ID string", 
1153      desc = "The spectrum ID string to associate the spin-lock offset to.", 
1154      wiz_element_type = 'combo', 
1155      wiz_combo_iter = spectrum.get_ids, 
1156      wiz_read_only = True 
1157  ) 
1158  uf.add_keyarg( 
1159      name = "offset", 
1160      py_type = "num", 
1161      desc_short = "spin-lock offset (ppm)", 
1162      desc = "The spin-lock offset, omega_rf, in ppm.", 
1163      can_be_none = True 
1164  ) 
1165  # Description. 
1166  uf.desc.append(Desc_container()) 
1167  uf.desc[-1].add_paragraph("This sets the spin-lock offset, omega_rf, for the specified R1rho spectrum in ppm.") 
1168  # Prompt examples. 
1169  uf.desc.append(Desc_container("Prompt examples")) 
1170  uf.desc[-1].add_paragraph("To set a spin-lock offset of 110.0 ppm for the spectrum 'nu1_2.1kHz_relaxT_0.010', type one of:") 
1171  uf.desc[-1].add_prompt("relax> relax_disp.spin_lock_offset('nu1_2.1kHz_relaxT_0.010', 110.0)") 
1172  uf.desc[-1].add_prompt("relax> relax_disp.spin_lock_offset(spectrum_id='nu1_2.1kHz_relaxT_0.010', offset=110.0)") 
1173  uf.backend = spin_lock_offset 
1174  uf.menu_text = "spin_lock_&offset" 
1175  uf.wizard_size = (800, 500) 
1176  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
1177   
1178   
1179  # The relax_disp.write_disp_curves user function. 
1180  uf = uf_info.add_uf('relax_disp.write_disp_curves') 
1181  uf.title = "Create text files of the dispersion curves for each spin system." 
1182  uf.title_short = "Dispersion curve writing." 
1183  uf.add_keyarg( 
1184      name = "dir", 
1185      py_type = "str", 
1186      arg_type = "dir sel", 
1187      desc_short = "directory name", 
1188      desc = "The directory name to place all of the spin system files into.", 
1189      can_be_none = True 
1190  ) 
1191  uf.add_keyarg( 
1192      name = "force", 
1193      default = False, 
1194      py_type = "bool", 
1195      desc_short = "force flag", 
1196      desc = "A flag which, if set to True, will cause the files to be overwritten." 
1197  ) 
1198  # Description. 
1199  uf.desc.append(Desc_container()) 
1200  uf.desc[-1].add_paragraph("This is used to created text files of the dispersion curves of R2eff/R1rho values, both measured and back calculated from the optimised dispersion model.  The columns of the text file will be the experiment name, the magnetic field strength (as the proton frequency in MHz), dispersion point (nu_CPMG or the spin-lock field strength), the experimental R2eff value, the back-calculated R2eff value, and the experimental R2eff error.  One file will be created per spin system with the name 'disp_x.out', where x is the spin ID string.") 
1201  uf.backend = write_disp_curves 
1202  uf.menu_text = "&write_disp_curves" 
1203  uf.gui_icon = "oxygen.actions.document-save" 
1204  uf.wizard_size = (700, 500) 
1205  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
1206