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,2006,2008-2009,2012-2014,2019 Edward d'Auvergne          # 
   4  # Copyright (C) 2008 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  from os import sep 
  29   
  30  # relax module imports. 
  31  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 
  32  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 
  33  from graphics import ANALYSIS_IMAGE_PATH, WIZARD_IMAGE_PATH 
  34  from pipe_control import pipes, spectrum 
  35  from pipe_control.mol_res_spin import get_spin_ids 
  36  from specific_analyses.relax_disp.catia import catia_execute, catia_input 
  37  from specific_analyses.relax_disp.cpmgfit import cpmgfit_execute, cpmgfit_input 
  38  from specific_analyses.relax_disp.estimate_r2eff import estimate_r2eff_err 
  39  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 
  40  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 
  41  from specific_analyses.relax_disp.nessy import nessy_input 
  42  from specific_analyses.relax_disp.parameters import copy 
  43  from specific_analyses.relax_disp.sherekhan import sherekhan_input 
  44  from specific_analyses.relax_disp import uf as relax_disp_uf 
  45  from user_functions.data import Uf_info; uf_info = Uf_info() 
  46  from user_functions.objects import Desc_container 
  47  from user_functions.wildcards import WILDCARD_GRACE_ALL 
  48   
  49   
  50  # The user function class. 
  51  uf_class = uf_info.add_class('relax_disp') 
  52  uf_class.title = "Class for relaxation curve fitting." 
  53  uf_class.menu_text = "&relax_disp" 
  54  uf_class.gui_icon = "relax.relax_disp" 
  55   
  56   
  57  # The relax_disp.catia_execute user function. 
  58  uf = uf_info.add_uf('relax_disp.catia_execute') 
  59  uf.title = "Perform a relaxation dispersion optimisation using Flemming Hansen's CATIA." 
  60  uf.title_short = "CATIA execution." 
  61  uf.add_keyarg( 
  62      name = "dir", 
  63      arg_type = "dir sel", 
  64      desc_short = "directory name", 
  65      desc = "The directory containing all of the CATIA input files.", 
  66      can_be_none = True 
  67  ) 
  68  uf.add_keyarg( 
  69      name = "binary", 
  70      default = "catia", 
  71      arg_type = "file sel read", 
  72      desc_short = "CATIA executable file", 
  73      desc = "The name of the executable CATIA program file.", 
  74      wiz_filesel_preview = False 
  75  ) 
  76  # Description. 
  77  uf.desc.append(Desc_container()) 
  78  uf.desc[-1].add_paragraph("CATIA will be executed as") 
  79  uf.desc[-1].add_prompt("$ catia < Fit.catia") 
  80  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.") 
  81  uf.backend = catia_execute 
  82  uf.gui_icon = "oxygen.categories.applications-education" 
  83  uf.menu_text = "catia_e&xecute" 
  84  uf.wizard_size = (800, 600) 
  85  uf.wizard_apply_button = False 
  86  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
  87   
  88   
  89  # The relax_disp.catia_input user function. 
  90  uf = uf_info.add_uf('relax_disp.catia_input') 
  91  uf.title = "Create the input files for Flemming Hansen's CATIA program." 
  92  uf.title_short = "CATIA input file creation." 
  93  uf.add_keyarg( 
  94      name = "dir", 
  95      default = "catia", 
  96      arg_type = "dir sel", 
  97      desc_short = "directory name", 
  98      desc = "The directory to place the CATIA input files, output directory, etc.", 
  99      can_be_none = True 
 100  ) 
 101  uf.add_keyarg( 
 102      name = "force", 
 103      default = False, 
 104      basic_types = ["bool"], 
 105      desc_short = "force flag", 
 106      desc = "A flag which if set to True will cause the files to be overwritten if they already exist." 
 107  ) 
 108  # Description. 
 109  uf.desc.append(Desc_container()) 
 110  uf.desc[-1].add_paragraph("This will create all of the input file required for CATIA as well as the CATIA results output directory.") 
 111  uf.backend = catia_input 
 112  uf.gui_icon = "oxygen.actions.list-add-relax-blue" 
 113  uf.menu_text = "&catia_input" 
 114  uf.wizard_size = (800, 600) 
 115  uf.wizard_apply_button = False 
 116  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 117   
 118   
 119  # The relax_disp.cluster user function. 
 120  uf = uf_info.add_uf('relax_disp.cluster') 
 121  uf.title = "Define clusters of spins for joint optimisation." 
 122  uf.title_short = "Spin clustering." 
 123  uf.add_keyarg( 
 124      name = "cluster_id", 
 125      basic_types = ["str"], 
 126      desc_short = "cluster ID", 
 127      desc = "The cluster identification string.", 
 128      wiz_element_type = 'combo', 
 129      wiz_combo_iter = relax_disp_uf.cluster_ids 
 130  ) 
 131  uf.add_keyarg( 
 132      name = "spin_id", 
 133      basic_types = ["str"], 
 134      desc_short = "spin ID string", 
 135      desc = "The spin identifier string for the spin or group of spins to add to the cluster.", 
 136      wiz_element_type = 'combo', 
 137      wiz_combo_iter = get_spin_ids, 
 138      can_be_none = True 
 139  ) 
 140  # Description. 
 141  uf.desc.append(Desc_container()) 
 142  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.") 
 143  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.") 
 144  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.") 
 145  # Prompt examples. 
 146  uf.desc.append(Desc_container("Prompt examples")) 
 147  uf.desc[-1].add_paragraph("To add the spins ':1@N' and ':3@N' to a new cluster called 'cluster', type one of:") 
 148  uf.desc[-1].add_prompt("relax> relax_disp.cluster('cluster', ':1,3@N')") 
 149  uf.desc[-1].add_prompt("relax> relax_disp.cluster(cluster_id='cluster', spin_id=':1,3@N')") 
 150  uf.backend = relax_disp_uf.cluster 
 151  uf.menu_text = "c&luster" 
 152  uf.gui_icon = "relax.cluster" 
 153  uf.wizard_height_desc = 500 
 154  uf.wizard_size = (800, 600) 
 155  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 156   
 157   
 158  # The relax_disp.cpmg_setup user function. 
 159  uf = uf_info.add_uf('relax_disp.cpmg_setup') 
 160  uf.title = "Set the CPMG pulse sequence information associated with a given spectrum." 
 161  uf.title_short = "CPMG experiment setup." 
 162  uf.add_keyarg( 
 163      name = "spectrum_id", 
 164      basic_types = ["str"], 
 165      desc_short = "spectrum ID string", 
 166      desc = "The spectrum ID string to associate the CPMG pulse sequence information to.", 
 167      wiz_element_type = 'combo', 
 168      wiz_combo_iter = spectrum.get_ids, 
 169      wiz_read_only = True 
 170  ) 
 171  uf.add_keyarg( 
 172      name = "cpmg_frq", 
 173      basic_types = ["number"], 
 174      desc_short = "CPMG frequency (Hz)", 
 175      desc = "The frequency, in Hz, of the CPMG pulse train.", 
 176      can_be_none = True 
 177  ) 
 178  uf.add_keyarg( 
 179      name = "ncyc_even", 
 180      default = True, 
 181      basic_types = ["bool"], 
 182      desc_short = "even ncyc flag", 
 183      desc = "A flag which if True means that the number of CPMG blocks must be even.  This is pulse sequence dependant." 
 184  ) 
 185  # Description. 
 186  uf.desc.append(Desc_container()) 
 187  uf.desc[-1].add_paragraph("This allows all information about CPMG pulse sequence required for a relaxation dispersion analysis to be specified.  This includes:") 
 188  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.") 
 189  uf.desc[-1].add_list_element("'ncyc_even' specifies if an even number of CPMG blocks are required for the pulse sequence.") 
 190  # Prompt examples. 
 191  uf.desc.append(Desc_container("Prompt examples")) 
 192  uf.desc[-1].add_paragraph("To identify the reference spectrum called 'reference_spectrum', type:") 
 193  uf.desc[-1].add_prompt("relax> relax_disp.cpmg_setup(spectrum_id='reference_spectrum', cpmg_frq=None)") 
 194  uf.desc[-1].add_paragraph("To set a frequency of 200 Hz for the spectrum '200_Hz_spectrum', type:") 
 195  uf.desc[-1].add_prompt("relax> relax_disp.cpmg_setup(spectrum_id='200_Hz_spectrum', cpmg_frq=200)") 
 196  uf.backend = cpmg_setup 
 197  uf.menu_text = "&cpmg_setup" 
 198  uf.wizard_size = (900, 600) 
 199  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 200   
 201   
 202  # The relax_disp.cpmgfit_execute user function. 
 203  uf = uf_info.add_uf('relax_disp.cpmgfit_execute') 
 204  uf.title = "Optimisation of the CPMG data using Art Palmer's CPMGFit program." 
 205  uf.title_short = "CPMGFit execution." 
 206  uf.add_keyarg( 
 207      name = "dir", 
 208      arg_type = "dir sel", 
 209      desc_short = "directory name", 
 210      desc = "The directory containing all of the CPMGFit input files.  If not given, this defaults to the model name in lower case.", 
 211      can_be_none = True 
 212  ) 
 213  uf.add_keyarg( 
 214      name = "force", 
 215      default = False, 
 216      basic_types = ["bool"], 
 217      desc_short = "force flag", 
 218      desc = "A flag which if set to True will cause the results files to be overwritten if they already exist." 
 219  ) 
 220  uf.add_keyarg( 
 221      name = "binary", 
 222      default = "cpmgfit", 
 223      arg_type = "file sel read", 
 224      desc_short = "CPMGFit executable file", 
 225      desc = "The name of the executable CPMGFit program file.", 
 226      wiz_filesel_preview = False 
 227  ) 
 228  # Description. 
 229  uf.desc.append(Desc_container()) 
 230  uf.desc[-1].add_paragraph("CPMGFit will be executed once per spin as:") 
 231  uf.desc[-1].add_prompt("$ cpmgfit -grid -xmgr -f dir/spin_x.in | tee dir/spin_x.out") 
 232  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.") 
 233  uf.backend = cpmgfit_execute 
 234  uf.menu_text = "&cpmgfit_execute" 
 235  uf.gui_icon = "oxygen.categories.applications-education" 
 236  uf.wizard_size = (800, 600) 
 237  uf.wizard_apply_button = False 
 238  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 239   
 240   
 241  # The relax_disp.cpmgfit_input user function. 
 242  uf = uf_info.add_uf('relax_disp.cpmgfit_input') 
 243  uf.title = "Create the input files for Art Palmer's CPMGFit program." 
 244  uf.title_short = "CPMGFit input file creation." 
 245  uf.add_keyarg( 
 246      name = "dir", 
 247      arg_type = "dir sel", 
 248      desc_short = "directory name", 
 249      desc = "The directory to place the files.  If not given, this defaults to the model name in lower case.", 
 250      can_be_none = True 
 251  ) 
 252  uf.add_keyarg( 
 253      name = "force", 
 254      default = False, 
 255      basic_types = ["bool"], 
 256      desc_short = "force flag", 
 257      desc = "A flag which if set to True will cause the files to be overwritten if they already exist." 
 258  ) 
 259  uf.add_keyarg( 
 260      name = "binary", 
 261      default = "cpmgfit", 
 262      arg_type = "file sel read", 
 263      desc_short = "CPMGFit executable file", 
 264      desc = "The name of the executable CPMGFit program file.", 
 265      wiz_filesel_preview = False 
 266  ) 
 267  uf.add_keyarg( 
 268      name = "spin_id", 
 269      basic_types = ["str"], 
 270      desc_short = "spin ID string", 
 271      desc = "The spin identification string.", 
 272      can_be_none = True 
 273  ) 
 274  # Description. 
 275  uf.desc.append(Desc_container()) 
 276  uf.desc[-1].add_paragraph("The following files are created:") 
 277  uf.desc[-1].add_list_element("'dir/spin_x.in',") 
 278  uf.desc[-1].add_list_element("'dir/run.sh'.") 
 279  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.") 
 280  uf.backend = cpmgfit_input 
 281  uf.menu_text = "&cpmgfit_input" 
 282  uf.gui_icon = "oxygen.actions.list-add-relax-blue" 
 283  uf.wizard_size = (800, 600) 
 284  uf.wizard_apply_button = False 
 285  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 286   
 287   
 288  # The relax_disp.exp_type user function. 
 289  uf = uf_info.add_uf('relax_disp.exp_type') 
 290  uf.title = "Select the relaxation dispersion experiment type." 
 291  uf.title_short = "Relaxation dispersion experiment type selection." 
 292  uf.add_keyarg( 
 293      name = "spectrum_id", 
 294      basic_types = ["str"], 
 295      desc_short = "spectrum ID string", 
 296      desc = "The spectrum ID string to associate the spin-lock field strength to.", 
 297      wiz_element_type = 'combo', 
 298      wiz_combo_iter = spectrum.get_ids, 
 299      wiz_read_only = True 
 300  ) 
 301  uf.add_keyarg( 
 302      name = "exp_type", 
 303      default = EXP_TYPE_CPMG_SQ, 
 304      basic_types = ["str"], 
 305      desc_short = "experiment type", 
 306      desc = "The type of relaxation dispersion experiment performed.", 
 307      wiz_element_type = "combo", 
 308      wiz_combo_choices = [ 
 309          "Single quantum (SQ) CPMG-type data", 
 310          "Zero quantum (ZQ) CPMG-type data", 
 311          "Double quantum (DQ) CPMG-type data", 
 312          "Multiple quantum (MQ) CPMG-type data", 
 313          "1H single quantum (SQ) CPMG-type data", 
 314          "1H multiple quantum (SQ) CPMG-type data", 
 315          "%s-type data" % r1rho 
 316      ], 
 317      wiz_combo_data = [ 
 318          EXP_TYPE_CPMG_SQ, 
 319          EXP_TYPE_CPMG_ZQ, 
 320          EXP_TYPE_CPMG_DQ, 
 321          EXP_TYPE_CPMG_MQ, 
 322          EXP_TYPE_CPMG_PROTON_SQ, 
 323          EXP_TYPE_CPMG_PROTON_MQ, 
 324          EXP_TYPE_R1RHO 
 325      ], 
 326      wiz_read_only = True 
 327  ) 
 328  # Description. 
 329  uf.desc.append(Desc_container()) 
 330  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.") 
 331  uf.desc[-1].add_paragraph("The currently supported experiments include:") 
 332  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_SQ), "The single quantum (SQ) CPMG-type experiments,") 
 333  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_ZQ), "The zero quantum (ZQ) CPMG-type experiments,") 
 334  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_DQ), "The double quantum (DQ) CPMG-type experiments,") 
 335  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_MQ), "The multiple quantum (MQ) CPMG-type experiments,") 
 336  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_PROTON_SQ), "The 1H single quantum (SQ) CPMG-type experiments,") 
 337  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_CPMG_PROTON_MQ), "The 1H multiple quantum (MQ) CPMG-type experiments,") 
 338  uf.desc[-1].add_item_list_element(repr(EXP_TYPE_R1RHO), "The R1rho-type experiments.") 
 339  # Prompt examples. 
 340  uf.desc.append(Desc_container("Prompt examples")) 
 341  uf.desc[-1].add_paragraph("To set the experiment type to 'SQ CPMG' for the spectrum ID 'nu_4500.0_800MHz', type one of:") 
 342  uf.desc[-1].add_prompt("relax> relax_disp.exp_type('nu_4500.0_800MHz', 'SQ CPMG')") 
 343  uf.desc[-1].add_prompt("relax> relax_disp.exp_type(spectrum_id='nu_4500.0_800MHz', exp_type='SQ CPMG')") 
 344  uf.backend = set_exp_type 
 345  uf.menu_text = "&exp_type" 
 346  uf.wizard_height_desc = 400 
 347  uf.wizard_size = (900, 600) 
 348  uf.wizard_apply_button = False 
 349  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 350   
 351   
 352  # The relax_disp.insignificance user function. 
 353  uf = uf_info.add_uf('relax_disp.insignificance') 
 354  uf.title = "Deselect all spins with insignificant dispersion." 
 355  uf.title_short = "Insignificant spin deselection." 
 356  uf.add_keyarg( 
 357      name = "level", 
 358      basic_types = ["float"], 
 359      default = 2.0, 
 360      desc_short = "insignificance level", 
 361      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.", 
 362      can_be_none = False 
 363  ) 
 364  # Description. 
 365  uf.desc.append(Desc_container()) 
 366  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.") 
 367  uf.backend = insignificance 
 368  uf.gui_icon = "relax.spin_grey" 
 369  uf.menu_text = "&insignificance" 
 370  uf.wizard_size = (800, 550) 
 371  uf.wizard_apply_button = False 
 372  uf.wizard_image = WIZARD_IMAGE_PATH + 'deselect.png' 
 373   
 374   
 375  # The relax_disp.nessy_input user function. 
 376  uf = uf_info.add_uf('relax_disp.nessy_input') 
 377  uf.title = "Create the input files for Michael Bieri's NESSY program." 
 378  uf.title_short = "NESSY input file creation." 
 379  uf.add_keyarg( 
 380      name = "dir", 
 381      arg_type = "dir sel", 
 382      desc_short = "directory name", 
 383      desc = "The directory to place the file and to use as the NESSY project directory.  If not given, this defaults to the current directory.", 
 384      can_be_none = True 
 385  ) 
 386  uf.add_keyarg( 
 387      name = "force", 
 388      default = False, 
 389      basic_types = ["bool"], 
 390      desc_short = "force flag", 
 391      desc = "A flag which if set to True will cause the files to be overwritten if they already exist." 
 392  ) 
 393  uf.add_keyarg( 
 394      name = "spin_id", 
 395      basic_types = ["str"], 
 396      desc_short = "spin ID string", 
 397      desc = "The spin identification string.", 
 398      can_be_none = True 
 399  ) 
 400  # Description. 
 401  uf.desc.append(Desc_container()) 
 402  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.") 
 403  uf.backend = nessy_input 
 404  uf.menu_text = "&nessy_input" 
 405  uf.gui_icon = "relax.nessy" 
 406  uf.wizard_size = (800, 600) 
 407  uf.wizard_apply_button = False 
 408  uf.wizard_image = WIZARD_IMAGE_PATH + 'nessy.png' 
 409   
 410   
 411  # The relax_disp.parameter_copy user function. 
 412  uf = uf_info.add_uf('relax_disp.parameter_copy') 
 413  uf.title = "Copy dispersion specific parameters values from one data pipe to another." 
 414  uf.title_short = "Dispersion parameter copying." 
 415  uf.add_keyarg( 
 416      name = "pipe_from", 
 417      basic_types = ["str"], 
 418      desc_short = "source data pipe", 
 419      desc = "The name of the pipe to copy from.", 
 420      wiz_element_type = 'combo', 
 421      wiz_combo_iter = pipes.pipe_names, 
 422      wiz_read_only = True 
 423  ) 
 424  uf.add_keyarg( 
 425      name = "pipe_to", 
 426      basic_types = ["str"], 
 427      desc_short = "destination data pipe", 
 428      desc = "The name of the pipe to copy to.", 
 429      wiz_element_type = 'combo', 
 430      wiz_combo_iter = pipes.pipe_names, 
 431      wiz_read_only = True 
 432  ) 
 433  # Description. 
 434  uf.desc.append(Desc_container()) 
 435  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.") 
 436  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.") 
 437  uf.desc.append(Desc_container("Prompt examples")) 
 438  uf.desc[-1].add_paragraph("To copy the CSA values from the data pipe 'm1' to 'm2', type:") 
 439  uf.desc[-1].add_prompt("relax> value.parameter_copy('m1', 'm2', 'csa')") 
 440  uf.backend = copy 
 441  uf.menu_text = "&parameter_copy" 
 442  uf.gui_icon = "oxygen.actions.list-add" 
 443  uf.wizard_size = (800, 500) 
 444  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 445   
 446   
 447  # The relax_disp.plot_disp_curves user function. 
 448  uf = uf_info.add_uf('relax_disp.plot_disp_curves') 
 449  uf.title = "Create 2D Grace plots of the dispersion curves for each spin system." 
 450  uf.title_short = "Dispersion curve plotting." 
 451  uf.add_keyarg( 
 452      name = "dir", 
 453      default = "grace", 
 454      arg_type = "dir sel", 
 455      desc_short = "directory name", 
 456      desc = "The directory name to place all of the spin system files into.", 
 457      can_be_none = True 
 458  ) 
 459  uf.add_keyarg( 
 460      name = "y_axis", 
 461      default = Y_AXIS_R2_EFF, 
 462      basic_types = ["str"], 
 463      desc_short = "Y axis data type", 
 464      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), 
 465      wiz_element_type = 'combo', 
 466      wiz_combo_choices = [ 
 467          "%s/%s for CPMG/%s experiments"%(r2eff, r1rho, r1rho), 
 468          "%s for %s experiments"%(r2, r1rho) 
 469      ], 
 470      wiz_combo_data = [Y_AXIS_R2_EFF, Y_AXIS_R2_R1RHO], 
 471      wiz_read_only = True 
 472  ) 
 473  uf.add_keyarg( 
 474      name = "x_axis", 
 475      default = X_AXIS_DISP, 
 476      basic_types = ["str"], 
 477      desc_short = "X axis data type", 
 478      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), 
 479      wiz_element_type = 'combo', 
 480      wiz_combo_choices = [ 
 481          "CPMG %s (Hz)/Spin-lock %s (Hz)"%(nu_cpmg, nu_1), 
 482          "Eff. field in rot. frame %s (rad/s)"%(w_eff), 
 483          "Rot. frame tilt ang. %s (rad)"%(theta) 
 484      ], 
 485      wiz_combo_data = [X_AXIS_DISP, X_AXIS_W_EFF, X_AXIS_THETA], 
 486      wiz_read_only = True 
 487  ) 
 488  uf.add_keyarg( 
 489      name = "num_points", 
 490      default = 1000, 
 491      min = 1, 
 492      max = 10000000, 
 493      basic_types = ["int"], 
 494      desc_short = "total number of interpolation points", 
 495      desc = "The total number of points to generate the interpolated dispersion curves with.  This value has no effect for the numeric CPMG-based models.", 
 496      can_be_none = False 
 497  ) 
 498  uf.add_keyarg( 
 499      name = "extend_hz", 
 500      basic_types = ["number"], 
 501      default = 500.0, 
 502      desc_short = "interpolated dispersion curve extension (in Hz)", 
 503      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.", 
 504      can_be_none = False 
 505  ) 
 506  uf.add_keyarg( 
 507      name = "extend_ppm", 
 508      basic_types = ["number"], 
 509      default = 500.0, 
 510      desc_short = "interpolated offset curve extension (in ppm)", 
 511      desc = "How far to extend the interpolated dispersion curves beyond the last dispersion point, i.e. the spin-lock offset value, in ppm.", 
 512      can_be_none = False 
 513  ) 
 514  uf.add_keyarg( 
 515      name = "interpolate", 
 516      default = INTERPOLATE_DISP, 
 517      basic_types = ["str"], 
 518      desc_short = "option to interpolate the fitted curves", 
 519      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), 
 520      wiz_element_type = 'combo', 
 521      wiz_combo_choices = [ 
 522          "Interpolate CPMG %s (Hz)/Spin-lock %s (Hz)"%(nu_cpmg, nu_1), 
 523          "Interpolate Spin-lock %s (ppm)"%(w_rf) 
 524      ], 
 525      wiz_combo_data = [INTERPOLATE_DISP, INTERPOLATE_OFFSET], 
 526      wiz_read_only = True 
 527  ) 
 528  uf.add_keyarg( 
 529      name = "force", 
 530      default = False, 
 531      basic_types = ["bool"], 
 532      desc_short = "force flag", 
 533      desc = "A flag which, if set to True, will cause the files to be overwritten." 
 534  ) 
 535  # Description. 
 536  uf.desc.append(Desc_container()) 
 537  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.") 
 538  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.") 
 539  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")) 
 540  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")) 
 541  uf.backend = plot_disp_curves 
 542  uf.menu_text = "&plot_disp_curves" 
 543  uf.gui_icon = "oxygen.actions.document-save" 
 544  uf.wizard_size = (950, 700) 
 545  uf.wizard_image = WIZARD_IMAGE_PATH + 'grace.png' 
 546   
 547   
 548  # The relax_disp.plot_exp_curves user function. 
 549  uf = uf_info.add_uf('relax_disp.plot_exp_curves') 
 550  uf.title = "Create 2D Grace plots of the exponential curves." 
 551  uf.title_short = "Exponential curve plotting." 
 552  uf.add_keyarg( 
 553      name = "file", 
 554      arg_type = "file sel write", 
 555      desc_short = "file name", 
 556      desc = "The name of the file.", 
 557      wiz_filesel_wildcard = WILDCARD_GRACE_ALL, 
 558  ) 
 559  uf.add_keyarg( 
 560      name = "dir", 
 561      default = "grace", 
 562      arg_type = "dir", 
 563      desc_short = "directory name", 
 564      desc = "The directory name.", 
 565      can_be_none = True 
 566  ) 
 567  uf.add_keyarg( 
 568      name = "force", 
 569      default = False, 
 570      basic_types = ["bool"], 
 571      desc_short = "force flag", 
 572      desc = "A flag which, if set to True, will cause the file to be overwritten." 
 573  ) 
 574  uf.add_keyarg( 
 575      name = "norm", 
 576      default = False, 
 577      basic_types = ["bool"], 
 578      desc_short = "normalisation flag", 
 579      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." 
 580  ) 
 581  # Description. 
 582  uf.desc.append(Desc_container()) 
 583  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.") 
 584  uf.backend = plot_exp_curves 
 585  uf.menu_text = "&plot_exp_curves" 
 586  uf.gui_icon = "oxygen.actions.document-save" 
 587  uf.wizard_size = (800, 600) 
 588  uf.wizard_image = WIZARD_IMAGE_PATH + 'grace.png' 
 589   
 590   
 591  # The relax_disp.r1_fit user function. 
 592  uf = uf_info.add_uf('relax_disp.r1_fit') 
 593  uf.title = "Switch between fixed or fitted R1 values for optimisation." 
 594  uf.title_short = "R1 optimisation flag." 
 595  uf.add_keyarg( 
 596      name = "fit", 
 597      default = True, 
 598      basic_types = ["bool"], 
 599      desc_short = "R1 optimisation flag", 
 600      desc = "The flag specifying if R1 values should be optimised or if loaded R1 values should be fixed during optimisation." 
 601  ) 
 602  # Description. 
 603  uf.desc.append(Desc_container()) 
 604  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) 
 605  uf.backend = relax_disp_uf.r1_fit 
 606  uf.menu_text = "r&1_fit" 
 607  uf.gui_icon = "oxygen.status.object-locked" 
 608  uf.wizard_size = (800, 500) 
 609  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 610   
 611   
 612  # The relax_disp.r2eff_err_estimate user function. 
 613  uf = uf_info.add_uf('relax_disp.r2eff_err_estimate') 
 614  uf.title = "Estimate R2eff errors by the Jacobian matrix." 
 615  uf.title_short = "Estimate R2eff errors." 
 616  uf.add_keyarg( 
 617      name = "spin_id", 
 618      arg_type = "spin ID", 
 619      desc_short = "spin ID to restrict value setting to", 
 620      desc = "The spin ID string to restrict value setting to.", 
 621      can_be_none = True 
 622  ) 
 623  uf.add_keyarg( 
 624      name = "epsrel", 
 625      basic_types = ["float"], 
 626      default = 0.0, 
 627      desc_short = "parameter to remove linear-dependent columns.", 
 628      desc = "The parameter to remove linear-dependent columns when J is rank deficient.", 
 629      can_be_none = False 
 630  ) 
 631  uf.add_keyarg( 
 632      name = "verbosity", 
 633      default = 1, 
 634      basic_types = ["int"], 
 635      desc_short = "amount of information to print.", 
 636      desc = "The higher the value, the greater the verbosity.", 
 637      can_be_none = False 
 638  ) 
 639  # Description. 
 640  uf.desc.append(Desc_container()) 
 641  uf.desc[-1].add_paragraph("This is a new experimental feature from version 3.3.") 
 642  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.") 
 643  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.") 
 644  uf.desc[-1].add_paragraph("This method is inspired from the GNU Scientific Library (GSL).") 
 645  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.") 
 646  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).") 
 647  uf.desc[-1].add_paragraph("The parameter 'epsrel' is used to remove linear-dependent columns when J is rank deficient.") 
 648  uf.backend = estimate_r2eff_err 
 649  uf.menu_text = "&r2eff_err_estimate" 
 650  uf.gui_icon = "relax.relax_fit" 
 651  uf.wizard_size = (800, 800) 
 652  uf.wizard_image = ANALYSIS_IMAGE_PATH + sep + 'blank_150x150.png' 
 653   
 654   
 655  # The relax_disp.r2eff_read user function. 
 656  uf = uf_info.add_uf('relax_disp.r2eff_read') 
 657  uf.title = "Read R2eff/R1rho values and errors from a file." 
 658  uf.title_short = "R2eff/R1rho value reading." 
 659  uf.add_keyarg( 
 660      name = "id", 
 661      basic_types = ["str"], 
 662      desc_short = "partial experiment ID string", 
 663      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.", 
 664      wiz_element_type = 'combo', 
 665      wiz_combo_iter = spectrum.get_ids, 
 666      wiz_read_only = True 
 667  ) 
 668  uf.add_keyarg( 
 669      name = "file", 
 670      arg_type = "file sel write", 
 671      desc_short = "file name", 
 672      desc = "The name of the file.", 
 673  ) 
 674  uf.add_keyarg( 
 675      name = "dir", 
 676      arg_type = "dir", 
 677      desc_short = "directory name", 
 678      desc = "The directory name.", 
 679      can_be_none = True 
 680  ) 
 681  uf.add_keyarg( 
 682      name = "disp_frq", 
 683      basic_types = ["number"], 
 684      desc_short = "CPMG frequency or spin-lock field strength (Hz)", 
 685      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", 
 686      can_be_none = True 
 687  ) 
 688  uf.add_keyarg( 
 689      name = "spin_id_col", 
 690      basic_types = ["int"], 
 691      arg_type = "free format", 
 692      desc_short = "spin ID string column", 
 693      desc = "The spin ID string column used by the generic file format (an alternative to the mol, res, and spin name and number columns).", 
 694      can_be_none = True 
 695  ) 
 696  uf.add_keyarg( 
 697      name = "mol_name_col", 
 698      basic_types = ["int"], 
 699      arg_type = "free format", 
 700      desc_short = "molecule name column", 
 701      desc = "The molecule name column used by the generic file format (alternative to the spin ID column).", 
 702      can_be_none = True 
 703  ) 
 704  uf.add_keyarg( 
 705      name = "res_num_col", 
 706      basic_types = ["int"], 
 707      arg_type = "free format", 
 708      desc_short = "residue number column", 
 709      desc = "The residue number column used by the generic file format (alternative to the spin ID column).", 
 710      can_be_none = True 
 711  ) 
 712  uf.add_keyarg( 
 713      name = "res_name_col", 
 714      basic_types = ["int"], 
 715      arg_type = "free format", 
 716      desc_short = "residue name column", 
 717      desc = "The residue name column used by the generic file format (alternative to the spin ID column).", 
 718      can_be_none = True 
 719  ) 
 720  uf.add_keyarg( 
 721      name = "spin_num_col", 
 722      basic_types = ["int"], 
 723      arg_type = "free format", 
 724      desc_short = "spin number column", 
 725      desc = "The spin number column used by the generic file format (alternative to the spin ID column).", 
 726      can_be_none = True 
 727  ) 
 728  uf.add_keyarg( 
 729      name = "spin_name_col", 
 730      basic_types = ["int"], 
 731      arg_type = "free format", 
 732      desc_short = "spin name column", 
 733      desc = "The spin name column used by the generic file format (alternative to the spin ID column).", 
 734      can_be_none = True 
 735  ) 
 736  uf.add_keyarg( 
 737      name = "data_col", 
 738      basic_types = ["int"], 
 739      arg_type = "free format", 
 740      desc_short = "data column", 
 741      desc = "The RDC data column.", 
 742      can_be_none = True 
 743  ) 
 744  uf.add_keyarg( 
 745      name = "error_col", 
 746      basic_types = ["int"], 
 747      arg_type = "free format", 
 748      desc_short = "error column", 
 749      desc = "The experimental error column.", 
 750      can_be_none = True 
 751  ) 
 752  uf.add_keyarg( 
 753      name = "sep", 
 754      basic_types = ["str"], 
 755      arg_type = "free format", 
 756      desc_short = "column separator", 
 757      desc = "The column separator used by the generic format (the default is white space).", 
 758      can_be_none = True 
 759  ) 
 760  # Description. 
 761  uf.desc.append(Desc_container()) 
 762  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.") 
 763  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.") 
 764  uf.backend = r2eff_read 
 765  uf.menu_text = "&r2eff_read" 
 766  uf.gui_icon = "oxygen.actions.document-open" 
 767  uf.wizard_size = (1000, 600) 
 768  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 769   
 770   
 771  # The relax_disp.r2eff_read_spin user function. 
 772  uf = uf_info.add_uf('relax_disp.r2eff_read_spin') 
 773  uf.title = "Read R2eff/R1rho values and errors for a single spin from a file." 
 774  uf.title_short = "Spin R2eff/R1rho value reading." 
 775  uf.add_keyarg( 
 776      name = "id", 
 777      basic_types = ["str"], 
 778      desc_short = "experiment ID string", 
 779      desc = "The experiment ID string to identify this data with.", 
 780      wiz_element_type = 'combo', 
 781      wiz_combo_iter = spectrum.get_ids, 
 782      wiz_read_only = True 
 783  ) 
 784  uf.add_keyarg( 
 785      name = "spin_id", 
 786      arg_type = "spin ID", 
 787      desc_short = "spin ID string", 
 788      desc = "The spin identification string.", 
 789      can_be_none = True 
 790  ) 
 791  uf.add_keyarg( 
 792      name = "file", 
 793      arg_type = "file sel write", 
 794      desc_short = "file name", 
 795      desc = "The name of the file.", 
 796  ) 
 797  uf.add_keyarg( 
 798      name = "dir", 
 799      arg_type = "dir", 
 800      desc_short = "directory name", 
 801      desc = "The directory name.", 
 802      can_be_none = True 
 803  ) 
 804  uf.add_keyarg( 
 805      name = "disp_point_col", 
 806      default = None, 
 807      min = 1, 
 808      basic_types = ["int"], 
 809      desc_short = "dispersion point column", 
 810      desc = "The column containing the CPMG frequency or spin-lock field strength (Hz).", 
 811      can_be_none = True 
 812  ) 
 813  uf.add_keyarg( 
 814      name = "offset_col", 
 815      default = None, 
 816      min = 1, 
 817      basic_types = ["int"], 
 818      desc_short = "offset column", 
 819      desc = "The column containing the offset information for R1rho-type data.", 
 820      can_be_none = True 
 821  ) 
 822  uf.add_keyarg( 
 823      name = "data_col", 
 824      default = 2, 
 825      min = 1, 
 826      basic_types = ["int"], 
 827      desc_short = "R2eff/R1rho data column", 
 828      desc = "The column containing the R2eff or R1rho data." 
 829  ) 
 830  uf.add_keyarg( 
 831      name = "error_col", 
 832      default = 3, 
 833      min = 1, 
 834      basic_types = ["int"], 
 835      desc_short = "R2eff/R1rho error column", 
 836      desc = "The column containing the R2eff or R1rho error." 
 837  ) 
 838  uf.add_keyarg( 
 839      name = "sep", 
 840      basic_types = ["str"], 
 841      desc_short = "column separator", 
 842      desc = "The column separator (the default is white space).", 
 843      wiz_element_type = "combo", 
 844      wiz_combo_choices = [",", ";", "\\t"], 
 845      can_be_none = True 
 846  ) 
 847  # Description. 
 848  uf.desc.append(Desc_container()) 
 849  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.") 
 850  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.") 
 851  uf.backend = r2eff_read_spin 
 852  uf.menu_text = "&r2eff_read_spin" 
 853  uf.gui_icon = "oxygen.actions.document-open" 
 854  uf.wizard_size = (900, 700) 
 855  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 856   
 857   
 858  # The relax_disp.relax_time user function. 
 859  uf = uf_info.add_uf('relax_disp.relax_time') 
 860  uf.title = "Set the relaxation delay time associated with each spectrum." 
 861  uf.title_short = "Relaxation delay time setting." 
 862  uf.add_keyarg( 
 863      name = "spectrum_id", 
 864      basic_types = ["str"], 
 865      desc_short = "spectrum ID string", 
 866      desc = "The spectrum ID string.", 
 867      wiz_element_type = 'combo', 
 868      wiz_combo_iter = spectrum.get_ids, 
 869      wiz_read_only = True 
 870  ) 
 871  uf.add_keyarg( 
 872      name = "time", 
 873      default = 0.0, 
 874      basic_types = ["number"], 
 875      desc_short = "relaxation time", 
 876      desc = "The time, in seconds, of the relaxation period." 
 877  ) 
 878  # Description. 
 879  uf.desc.append(Desc_container()) 
 880  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.") 
 881  uf.backend = relax_time 
 882  uf.menu_text = "&relax_time" 
 883  uf.gui_icon = "oxygen.actions.chronometer" 
 884  uf.wizard_size = (800, 500) 
 885  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
 886   
 887   
 888  # The relax_disp.select_model user function. 
 889  uf = uf_info.add_uf('relax_disp.select_model') 
 890  uf.title = "Select the relaxation dispersion model." 
 891  uf.title_short = "Relaxation dispersion model setup." 
 892  uf.display = True 
 893  uf.add_keyarg( 
 894      name = "model", 
 895      default = MODEL_R2EFF, 
 896      basic_types = ["str"], 
 897      desc_short = "dispersion model", 
 898      desc = "The type of relaxation dispersion model to fit.", 
 899      wiz_element_type = "combo", 
 900      wiz_combo_choices = [ 
 901          "%s: {%s/%s, %s}" % (MODEL_R2EFF, r2eff, r1rho, i0), 
 902          "%s: {%s, ...}" % (MODEL_NOREX, r2), 
 903          "%s: {%s, ..., %s, %s}" % (MODEL_LM63, r2, phi_ex, kex), 
 904          "%s: {%s, ..., %s, kB, %s, kC}" % (MODEL_LM63_3SITE, r2, phi_exB, phi_exC), 
 905          "%s: {%s, ..., pA, %s, %s}" % (MODEL_CR72, r2, dw, kex), 
 906          "%s: {%s, %s, ..., pA, %s, %s}" % (MODEL_CR72_FULL, r2a, r2b, dw, kex), 
 907          "%s: {%s, ..., pA, %s, %s}" % (MODEL_IT99, r2, dw, tex), 
 908          "%s: {%s, ..., %s, k_AB}" % (MODEL_TSMFK01, r2a, dw), 
 909          "%s: {%s, ..., pA, %s, %s}" % (MODEL_B14, r2, dw, kex), 
 910          "%s: {%s, %s, ..., pA, %s, %s}" % (MODEL_B14_FULL, r2a, r2b, dw, kex), 
 911          "%s: {%s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_3D, r2, dw, kex), 
 912          "%s: {%s, %s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_3D_FULL, r2a, r2b, dw, kex), 
 913          "%s: {%s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_STAR, r2, dw, kex), 
 914          "%s: {%s, %s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_STAR_FULL, r2a, r2b, dw, kex), 
 915          "%s: {%s, ..., pA, %s, %s}" % (MODEL_NS_CPMG_2SITE_EXPANDED, r2, dw, kex), 
 916          "%s: {%s, ..., pA, %s, %s, %s}" % (MODEL_MMQ_CR72, r2, dw, dwH, kex), 
 917          "%s: {%s, ..., pA, %s, %s, %s}" % (MODEL_NS_MMQ_2SITE, r2, dw, dwH, kex), 
 918          "%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), 
 919          "%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), 
 920          "%s: {%s, ..., %s, %s}" % (MODEL_M61, r1rho_prime, phi_ex, kex), 
 921          "%s: {%s, ..., pA, %s, %s}" % (MODEL_M61B, r1rho_prime, dw, kex), 
 922          "%s: {%s, ..., %s, %s}" % (MODEL_DPL94, r1rho_prime, phi_ex, kex), 
 923          "%s: {%s, ..., pA, %s, %s}" % (MODEL_TP02, r1rho_prime, dw, kex), 
 924          "%s: {%s, ..., pA, %s, %s}" % (MODEL_TAP03, r1rho_prime, dw, kex), 
 925          "%s: {%s, ..., pA, %s, %s}" % (MODEL_MP05, r1rho_prime, dw, kex), 
 926          "%s: {%s, ..., pA, %s, %s}" % (MODEL_NS_R1RHO_2SITE, r1rho_prime, dw, kex), 
 927          "%s: {%s, ..., pA, %s, %s, pB, %s, %s}" % (MODEL_NS_R1RHO_3SITE_LINEAR, r2, dw_AB, kAB, dw_BC, kBC), 
 928          "%s: {%s, ..., pA, %s, %s, pB, %s, %s, %s}" % (MODEL_NS_R1RHO_3SITE, r2, dw_AB, kAB, dw_BC, kBC, kAC) 
 929      ], 
 930      wiz_combo_data = [ 
 931          MODEL_R2EFF, 
 932          MODEL_NOREX, 
 933          MODEL_LM63, 
 934          MODEL_LM63_3SITE, 
 935          MODEL_CR72, 
 936          MODEL_CR72_FULL, 
 937          MODEL_IT99, 
 938          MODEL_TSMFK01, 
 939          MODEL_B14, 
 940          MODEL_B14_FULL, 
 941          MODEL_NS_CPMG_2SITE_3D, 
 942          MODEL_NS_CPMG_2SITE_3D_FULL, 
 943          MODEL_NS_CPMG_2SITE_STAR, 
 944          MODEL_NS_CPMG_2SITE_STAR_FULL, 
 945          MODEL_NS_CPMG_2SITE_EXPANDED, 
 946          MODEL_MMQ_CR72, 
 947          MODEL_NS_MMQ_2SITE, 
 948          MODEL_NS_MMQ_3SITE_LINEAR, 
 949          MODEL_NS_MMQ_3SITE, 
 950          MODEL_M61, 
 951          MODEL_M61B, 
 952          MODEL_DPL94, 
 953          MODEL_TP02, 
 954          MODEL_TAP03, 
 955          MODEL_MP05, 
 956          MODEL_NS_R1RHO_2SITE, 
 957          MODEL_NS_R1RHO_3SITE_LINEAR, 
 958          MODEL_NS_R1RHO_3SITE 
 959      ], 
 960      wiz_read_only = True 
 961  ) 
 962  # Description. 
 963  uf.desc.append(Desc_container()) 
 964  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:") 
 965  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,") 
 966  uf.desc.append(Desc_container('The no chemical exchange models')) 
 967  uf.desc[-1].add_item_list_element("'%s'" % MODEL_NOREX, "This is the model for no chemical exchange being present.") 
 968  # CPMG-type data. 
 969  uf.desc.append(Desc_container('The SQ CPMG-type experiments')) 
 970  uf.desc[-1].add_paragraph("The currently supported analytic models are:") 
 971  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},") 
 972  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},") 
 973  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},") 
 974  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},") 
 975  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},") 
 976  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}.") 
 977  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},") 
 978  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},") 
 979  uf.desc[-1].add_paragraph("The currently supported numeric models are:") 
 980  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},") 
 981  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},") 
 982  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},") 
 983  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},") 
 984  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}.") 
 985  # MMQ CPMG-type data. 
 986  uf.desc.append(Desc_container('The MMQ CPMG-type experiments')) 
 987  uf.desc[-1].add_paragraph("The currently supported models are:") 
 988  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}.") 
 989  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}.") 
 990  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)}.") 
 991  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)}.") 
 992  # R1rho-type data. 
 993  uf.desc.append(Desc_container('The R1rho-type experiments')) 
 994  uf.desc[-1].add_paragraph("The currently supported analytic models are:") 
 995  uf.desc[-1].add_paragraph("On-resonance models are:") 
 996  uf.desc[-1].add_item_list_element("'%s'" % MODEL_M61, "The Meiboom (1961) 2-site fast exchange equation with parameters {R1rho', ..., phi_ex, kex},") 
 997  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},") 
 998  uf.desc[-1].add_paragraph("Off-resonance models are:") 
 999  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},") 
1000  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}.") 
1001  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}.") 
1002  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}.") 
1003  uf.desc[-1].add_paragraph("The currently supported numeric models are:") 
1004  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}.") 
1005  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)}.") 
1006  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)}.") 
1007  # Prompt examples. 
1008  uf.desc.append(Desc_container("Prompt examples")) 
1009  uf.desc[-1].add_paragraph("To pick the 2-site fast exchange model for all selected spins, type one of:") 
1010  uf.desc[-1].add_prompt("relax> relax_disp.select_model('%s')" % MODEL_LM63) 
1011  uf.desc[-1].add_prompt("relax> relax_disp.select_model(model='%s')" % MODEL_LM63) 
1012  uf.backend = relax_disp_uf.select_model 
1013  uf.menu_text = "&select_model" 
1014  uf.gui_icon = "oxygen.actions.list-add" 
1015  uf.wizard_height_desc = 500 
1016  uf.wizard_size = (1000, 700) 
1017  uf.wizard_apply_button = False 
1018  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
1019   
1020   
1021  # The relax_disp.r20_from_min_r2eff user function. 
1022  uf = uf_info.add_uf('relax_disp.r20_from_min_r2eff') 
1023  uf.title = "Set the R20 parameter values to that of the minimum R2eff value." 
1024  uf.title_short = "Set R20 from the minimum R2eff." 
1025  uf.add_keyarg( 
1026      name = "force", 
1027      default = True, 
1028      basic_types = ["bool"], 
1029      desc_short = "force flag", 
1030      desc = "A flag which if set to True will cause the R20 values to be overwritten if they already exist." 
1031  ) 
1032  # Description. 
1033  uf.desc.append(Desc_container()) 
1034  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.") 
1035  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.") 
1036  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.") 
1037  uf.backend = r20_from_min_r2eff 
1038  uf.menu_text = "&r20_from_min_r2eff" 
1039  uf.gui_icon = "relax.grid_search" 
1040  uf.wizard_height_desc = 500 
1041  uf.wizard_size = (900, 600) 
1042  uf.wizard_apply_button = False 
1043   
1044   
1045  # The relax_disp.sherekhan_input user function. 
1046  uf = uf_info.add_uf('relax_disp.sherekhan_input') 
1047  uf.title = "Create the input files for Adam Mazur's ShereKhan program." 
1048  uf.title_short = "ShereKhan input file creation." 
1049  uf.add_keyarg( 
1050      name = "force", 
1051      default = False, 
1052      basic_types = ["bool"], 
1053      desc_short = "force flag", 
1054      desc = "A flag which if set to True will cause the files to be overwritten if they already exist." 
1055  ) 
1056  uf.add_keyarg( 
1057      name = "spin_id", 
1058      basic_types = ["str"], 
1059      desc_short = "spin ID string", 
1060      desc = "The spin identification string.", 
1061      can_be_none = True 
1062  ) 
1063  uf.add_keyarg( 
1064      name = "dir", 
1065      arg_type = "dir sel", 
1066      desc_short = "directory name", 
1067      desc = "The directory name to place ShereKhan cluster folders into.", 
1068      can_be_none = True 
1069  ) 
1070  # Description. 
1071  uf.desc.append(Desc_container()) 
1072  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.") 
1073  uf.backend = sherekhan_input 
1074  uf.menu_text = "&sherekhan_input" 
1075  uf.gui_icon = "relax.sherekhan" 
1076  uf.wizard_size = (800, 500) 
1077  uf.wizard_apply_button = False 
1078  uf.wizard_image = WIZARD_IMAGE_PATH + 'sherekhan.png' 
1079   
1080   
1081  # The relax_disp.spin_lock_field user function. 
1082  uf = uf_info.add_uf('relax_disp.spin_lock_field') 
1083  uf.title = "Set the relaxation dispersion spin-lock field strength (nu1)." 
1084  uf.title_short = "Spin-lock field strength." 
1085  uf.add_keyarg( 
1086      name = "spectrum_id", 
1087      basic_types = ["str"], 
1088      desc_short = "spectrum ID string", 
1089      desc = "The spectrum ID string to associate the spin-lock field strength to.", 
1090      wiz_element_type = 'combo', 
1091      wiz_combo_iter = spectrum.get_ids, 
1092      wiz_read_only = True 
1093  ) 
1094  uf.add_keyarg( 
1095      name = "field", 
1096      basic_types = ["number"], 
1097      desc_short = "field strength nu1 (Hz)", 
1098      desc = "The spin-lock field strength, nu1, in Hz.", 
1099      can_be_none = True 
1100  ) 
1101  # Description. 
1102  uf.desc.append(Desc_container()) 
1103  uf.desc[-1].add_paragraph("This sets the spin-lock field strength, nu1, for the specified R1rho spectrum in Hertz.") 
1104  # Prompt examples. 
1105  uf.desc.append(Desc_container("Prompt examples")) 
1106  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:") 
1107  uf.desc[-1].add_prompt("relax> relax_disp.spin_lock_field(2100, 'nu1_2.1kHz_relaxT_0.010')") 
1108  uf.desc[-1].add_prompt("relax> relax_disp.spin_lock_field(field=2100, spectrum_id='nu1_2.1kHz_relaxT_0.010')") 
1109  uf.backend = spin_lock_field 
1110  uf.menu_text = "spin_lock_&field" 
1111  uf.wizard_size = (800, 500) 
1112  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
1113   
1114   
1115  # The relax_disp.spin_lock_offset user function. 
1116  uf = uf_info.add_uf('relax_disp.spin_lock_offset') 
1117  uf.title = "Set the relaxation dispersion spin-lock offset (omega_rf)." 
1118  uf.title_short = "Spin-lock offset." 
1119  uf.add_keyarg( 
1120      name = "spectrum_id", 
1121      basic_types = ["str"], 
1122      desc_short = "spectrum ID string", 
1123      desc = "The spectrum ID string to associate the spin-lock offset to.", 
1124      wiz_element_type = 'combo', 
1125      wiz_combo_iter = spectrum.get_ids, 
1126      wiz_read_only = True 
1127  ) 
1128  uf.add_keyarg( 
1129      name = "offset", 
1130      basic_types = ["number"], 
1131      desc_short = "spin-lock offset (ppm)", 
1132      desc = "The spin-lock offset, omega_rf, in ppm.", 
1133      can_be_none = True 
1134  ) 
1135  # Description. 
1136  uf.desc.append(Desc_container()) 
1137  uf.desc[-1].add_paragraph("This sets the spin-lock offset, omega_rf, for the specified R1rho spectrum in ppm.") 
1138  # Prompt examples. 
1139  uf.desc.append(Desc_container("Prompt examples")) 
1140  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:") 
1141  uf.desc[-1].add_prompt("relax> relax_disp.spin_lock_offset('nu1_2.1kHz_relaxT_0.010', 110.0)") 
1142  uf.desc[-1].add_prompt("relax> relax_disp.spin_lock_offset(spectrum_id='nu1_2.1kHz_relaxT_0.010', offset=110.0)") 
1143  uf.backend = spin_lock_offset 
1144  uf.menu_text = "spin_lock_&offset" 
1145  uf.wizard_size = (800, 500) 
1146  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
1147   
1148   
1149  # The relax_disp.write_disp_curves user function. 
1150  uf = uf_info.add_uf('relax_disp.write_disp_curves') 
1151  uf.title = "Create text files of the dispersion curves for each spin system." 
1152  uf.title_short = "Dispersion curve writing." 
1153  uf.add_keyarg( 
1154      name = "dir", 
1155      arg_type = "dir sel", 
1156      desc_short = "directory name", 
1157      desc = "The directory name to place all of the spin system files into.", 
1158      can_be_none = True 
1159  ) 
1160  uf.add_keyarg( 
1161      name = "force", 
1162      default = False, 
1163      basic_types = ["bool"], 
1164      desc_short = "force flag", 
1165      desc = "A flag which, if set to True, will cause the files to be overwritten." 
1166  ) 
1167  # Description. 
1168  uf.desc.append(Desc_container()) 
1169  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.") 
1170  uf.backend = write_disp_curves 
1171  uf.menu_text = "&write_disp_curves" 
1172  uf.gui_icon = "oxygen.actions.document-save" 
1173  uf.wizard_size = (700, 500) 
1174  uf.wizard_image = ANALYSIS_IMAGE_PATH + 'relax_disp_200x200.png' 
1175