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