1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """The pcs user function definitions."""
24
25
26 import dep_check
27 if dep_check.wx_module:
28 from wx import FD_OPEN, FD_SAVE
29 else:
30 FD_OPEN = -1
31 FD_SAVE = -1
32
33
34 from graphics import WIZARD_IMAGE_PATH
35 from pipe_control import align_tensor, pcs, pipes
36 from pipe_control.mol_res_spin import get_spin_ids
37 from user_functions.data import Uf_info; uf_info = Uf_info()
38 from user_functions.objects import Desc_container
39
40
41
42 uf_class = uf_info.add_class('pcs')
43 uf_class.title = "Class for handling pseudo-contact shifts."
44 uf_class.menu_text = "&pcs"
45 uf_class.gui_icon = "relax.align_tensor"
46
47
48
49 uf = uf_info.add_uf('pcs.back_calc')
50 uf.title = "Back calculate the pseudo-contact shifts."
51 uf.title_short = "PCS back calculation."
52 uf.display = True
53 uf.add_keyarg(
54 name = "align_id",
55 py_type = "str",
56 desc_short = "alignment ID string",
57 desc = "The alignment ID string.",
58 wiz_element_type = 'combo',
59 wiz_combo_iter = align_tensor.get_align_ids,
60 wiz_read_only = True,
61 can_be_none = True
62 )
63
64 uf.desc.append(Desc_container())
65 uf.desc[-1].add_paragraph("This will back calculate the pseudo-contact shifts if the paramagnetic centre, temperature and magnetic field strength has been specified, an alignment tensor is present, and atomic positions have been loaded into the relax data store.")
66 uf.backend = pcs.back_calc
67 uf.menu_text = "&back_calc"
68 uf.gui_icon = "oxygen.categories.applications-education"
69 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
70 uf.wizard_apply_button = False
71
72
73
74 uf = uf_info.add_uf('pcs.calc_q_factors')
75 uf.title = "Calculate the PCS Q factor for the selected spins."
76 uf.title_short = "PCS Q factor calculation."
77 uf.display = True
78 uf.add_keyarg(
79 name = "spin_id",
80 py_type = "str",
81 desc_short = "spin ID string",
82 desc = "The spin ID string for restricting to subset of all selected spins.",
83 can_be_none = True
84 )
85
86 uf.desc.append(Desc_container())
87 uf.desc[-1].add_paragraph("For this to work, the back-calculated PCS data must first be generated by the analysis specific code. Otherwise a warning will be given.")
88
89 uf.desc.append(Desc_container("Prompt examples"))
90 uf.desc[-1].add_paragraph("To calculate the PCS Q factor for only the spins '@H26', '@H27', and '@H28', type one of:")
91 uf.desc[-1].add_prompt("relax> pcs.calc_q_factors('@H26 & @H27 & @H28')")
92 uf.desc[-1].add_prompt("relax> pcs.calc_q_factors(spin_id='@H26 & @H27 & @H28')")
93 uf.backend = pcs.q_factors
94 uf.menu_text = "&calc_q_factors"
95 uf.gui_icon = "oxygen.categories.applications-education"
96 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
97 uf.wizard_apply_button = False
98
99
100
101 uf = uf_info.add_uf('pcs.copy')
102 uf.title = "Copy PCS data from one data pipe to another."
103 uf.title_short = "PCS copying."
104 uf.add_keyarg(
105 name = "pipe_from",
106 py_type = "str",
107 desc_short = "source pipe",
108 desc = "The name of the pipe to copy the PCS data from.",
109 wiz_element_type = 'combo',
110 wiz_combo_iter = pipes.pipe_names,
111 can_be_none = True
112 )
113 uf.add_keyarg(
114 name = "pipe_to",
115 py_type = "str",
116 desc_short = "destination pipe",
117 desc = "The name of the pipe to copy the PCS data to.",
118 wiz_element_type = 'combo',
119 wiz_combo_iter = pipes.pipe_names,
120 can_be_none = True
121 )
122 uf.add_keyarg(
123 name = "align_id",
124 py_type = "str",
125 desc_short = "alignment ID string",
126 desc = "The alignment ID string.",
127 wiz_element_type = 'combo',
128 wiz_combo_iter = align_tensor.get_align_ids,
129 wiz_read_only = True,
130 can_be_none = True
131 )
132
133 uf.desc.append(Desc_container())
134 uf.desc[-1].add_paragraph("This function will copy PCS data from 'pipe_from' to 'pipe_to'. If align_id is not given then all PCS data will be copied, otherwise only a specific data set will be.")
135
136 uf.desc.append(Desc_container("Prompt examples"))
137 uf.desc[-1].add_paragraph("To copy all PCS data from pipe 'm1' to pipe 'm9', type one of:")
138 uf.desc[-1].add_prompt("relax> pcs.copy('m1', 'm9')")
139 uf.desc[-1].add_prompt("relax> pcs.copy(pipe_from='m1', pipe_to='m9')")
140 uf.desc[-1].add_prompt("relax> pcs.copy('m1', 'm9', None)")
141 uf.desc[-1].add_prompt("relax> pcs.copy(pipe_from='m1', pipe_to='m9', align_id=None)")
142 uf.desc[-1].add_paragraph("To copy only the 'Th' PCS data from 'm3' to 'm6', type one of:")
143 uf.desc[-1].add_prompt("relax> pcs.copy('m3', 'm6', 'Th')")
144 uf.desc[-1].add_prompt("relax> pcs.copy(pipe_from='m3', pipe_to='m6', align_id='Th')")
145 uf.backend = pcs.copy
146 uf.menu_text = "cop&y"
147 uf.gui_icon = "oxygen.actions.list-add"
148 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
149
150
151
152 uf = uf_info.add_uf('pcs.corr_plot')
153 uf.title = "Generate a correlation plot of the measured vs. the back-calculated PCSs."
154 uf.title_short = "Correlation plot generation."
155 uf.add_keyarg(
156 name = "format",
157 default = "grace",
158 py_type = "str",
159 desc_short = "format",
160 desc = "The format of the plot data.",
161 wiz_element_type = "combo",
162 wiz_combo_choices = ["grace"],
163 wiz_read_only = True,
164 can_be_none = True
165 )
166 uf.add_keyarg(
167 name = "file",
168 default = "pcs_corr_plot.agr",
169 py_type = "str",
170 arg_type = "file sel",
171 desc_short = "Grace file name",
172 desc = "The name of the Grace file to create.",
173 wiz_filesel_wildcard = "Grace files (*.agr)|*.agr;*.AGR",
174 wiz_filesel_style = FD_SAVE
175 )
176 uf.add_keyarg(
177 name = "dir",
178 py_type = "str",
179 arg_type = "dir",
180 desc_short = "directory name",
181 desc = "The directory name.",
182 can_be_none = True
183 )
184 uf.add_keyarg(
185 name = "force",
186 default = False,
187 py_type = "bool",
188 desc_short = "force flag",
189 desc = "A flag which if True will cause the file to be overwritten."
190 )
191
192 uf.desc.append(Desc_container())
193 uf.desc[-1].add_paragraph("Two formats are currently supported. If format is set to 'grace', then a Grace plot file will be created. If the format is not set then a plain text list of the measured and back-calculated data will be created.")
194
195 uf.desc.append(Desc_container("Prompt examples"))
196 uf.desc[-1].add_paragraph("To create a Grace plot of the data, type:")
197 uf.desc[-1].add_prompt("relax> pcs.corr_plot()")
198 uf.desc[-1].add_paragraph("To create a plain text list of the measured and back-calculated data, type one of:")
199 uf.desc[-1].add_prompt("relax> pcs.corr_plot(None)")
200 uf.desc[-1].add_prompt("relax> pcs.corr_plot(format=None)")
201 uf.backend = pcs.corr_plot
202 uf.menu_text = "corr_&plot"
203 uf.wizard_size = (800, 500)
204 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
205 uf.wizard_apply_button = False
206
207
208
209 uf = uf_info.add_uf('pcs.delete')
210 uf.title = "Delete the PCS data corresponding to the alignment ID."
211 uf.title_short = "PCS deletion."
212 uf.add_keyarg(
213 name = "align_id",
214 py_type = "str",
215 desc_short = "alignment ID string",
216 desc = "The alignment ID string of the data to delete.",
217 wiz_element_type = 'combo',
218 wiz_combo_iter = align_tensor.get_align_ids,
219 wiz_read_only = True,
220 can_be_none = True
221 )
222
223 uf.desc.append(Desc_container())
224 uf.desc[-1].add_paragraph("This will delete all PCS data associated with the alignment ID in the current data pipe.")
225
226 uf.desc.append(Desc_container("Prompt examples"))
227 uf.desc[-1].add_paragraph("To delete the PCS data corresponding to align_id='PH_gel', type:")
228 uf.desc[-1].add_prompt("relax> pcs.delete('PH_gel')")
229 uf.backend = pcs.delete
230 uf.menu_text = "&delete"
231 uf.gui_icon = "oxygen.actions.list-remove"
232 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
233
234
235
236 uf = uf_info.add_uf('pcs.display')
237 uf.title = "Display the PCS data corresponding to the alignment ID."
238 uf.title_short = "PCS data display."
239 uf.display = True
240 uf.add_keyarg(
241 name = "align_id",
242 py_type = "str",
243 desc_short = "alignment ID string",
244 desc = "The alignment ID string.",
245 wiz_element_type = 'combo',
246 wiz_combo_iter = align_tensor.get_align_ids,
247 wiz_read_only = True
248 )
249 uf.add_keyarg(
250 name = "bc",
251 default = False,
252 py_type = "bool",
253 desc_short = "back-calculation flag",
254 desc = "A flag which if set will display the back-calculated rather than measured RDCs."
255 )
256
257 uf.desc.append(Desc_container())
258 uf.desc[-1].add_paragraph("This will display all of the PCS data associated with the alignment ID in the current data pipe.")
259
260 uf.desc.append(Desc_container("Prompt examples"))
261 uf.desc[-1].add_paragraph("To display the 'phage' PCS data, type:")
262 uf.desc[-1].add_prompt("relax> pcs.display('phage')")
263 uf.backend = pcs.display
264 uf.menu_text = "di&splay"
265 uf.gui_icon = "oxygen.actions.document-preview"
266 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
267
268
269
270 uf = uf_info.add_uf('pcs.read')
271 uf.title = "Read the PCS data from file."
272 uf.title_short = "PCS data reading."
273 uf.add_keyarg(
274 name = "align_id",
275 py_type = "str",
276 desc_short = "alignment ID string",
277 desc = "The alignment ID string.",
278 wiz_element_type = 'combo',
279 wiz_combo_iter = align_tensor.get_align_ids
280 )
281 uf.add_keyarg(
282 name = "file",
283 py_type = "str",
284 arg_type = "file sel",
285 desc_short = "file name",
286 desc = "The name of the file containing the PCS data.",
287 wiz_filesel_style = FD_OPEN
288 )
289 uf.add_keyarg(
290 name = "dir",
291 py_type = "str",
292 arg_type = "dir",
293 desc_short = "directory name",
294 desc = "The directory where the file is located.",
295 can_be_none = True
296 )
297 uf.add_keyarg(
298 name = "spin_id_col",
299 py_type = "int",
300 arg_type = "free format",
301 desc_short = "spin ID column",
302 desc = "The spin ID string column (an alternative to the mol, res, and spin name and number columns).",
303 can_be_none = True
304 )
305 uf.add_keyarg(
306 name = "mol_name_col",
307 py_type = "int",
308 arg_type = "free format",
309 desc_short = "molecule name column",
310 desc = "The molecule name column (alternative to the spin_id_col).",
311 can_be_none = True
312 )
313 uf.add_keyarg(
314 name = "res_num_col",
315 py_type = "int",
316 arg_type = "free format",
317 desc_short = "residue number column",
318 desc = "The residue number column (alternative to the spin_id_col).",
319 can_be_none = True
320 )
321 uf.add_keyarg(
322 name = "res_name_col",
323 py_type = "int",
324 arg_type = "free format",
325 desc_short = "residue name column",
326 desc = "The residue name column (alternative to the spin_id_col).",
327 can_be_none = True
328 )
329 uf.add_keyarg(
330 name = "spin_num_col",
331 py_type = "int",
332 arg_type = "free format",
333 desc_short = "spin number column",
334 desc = "The spin number column (alternative to the spin_id_col).",
335 can_be_none = True
336 )
337 uf.add_keyarg(
338 name = "spin_name_col",
339 py_type = "int",
340 arg_type = "free format",
341 desc_short = "spin name column",
342 desc = "The spin name column (alternative to the spin_id_col).",
343 can_be_none = True
344 )
345 uf.add_keyarg(
346 name = "data_col",
347 py_type = "int",
348 arg_type = "free format",
349 desc_short = "data column",
350 desc = "The PCS data column.",
351 can_be_none = True
352 )
353 uf.add_keyarg(
354 name = "error_col",
355 py_type = "int",
356 arg_type = "free format",
357 desc_short = "error column",
358 desc = "The experimental error column.",
359 can_be_none = True
360 )
361 uf.add_keyarg(
362 name = "sep",
363 py_type = "str",
364 arg_type = "free format",
365 desc_short = "column separator",
366 desc = "The column separator (the default is white space).",
367 can_be_none = True
368 )
369 uf.add_keyarg(
370 name = "spin_id",
371 py_type = "str",
372 desc_short = "spin ID string",
373 desc = "The spin ID string to restrict the loading of data to certain spin subsets.",
374 can_be_none = True
375 )
376
377 uf.desc.append(Desc_container())
378 uf.desc[-1].add_paragraph("This will read PCS data from a file and associate it with an alignment ID, either a new ID or a preexisting one with no PCS data.")
379 uf.desc[-1].add_paragraph("The spin system can be identified in the file using two different formats. The first is the spin ID string column which can include the molecule name, the residue name and number, and the spin name and number. Alternatively the molecule name, residue number and name, and spin number and name columns can be supplied allowing this information to be in separate columns. Note that the numbering of columns starts at one. The spin ID can be used to restrict the reading to certain spin types, for example only 15N spins when only residue information is in the file.")
380
381 uf.desc.append(Desc_container("Prompt examples"))
382 uf.desc[-1].add_paragraph("The following commands will read the PCS data out of the file 'Tb.txt' where the columns are separated by the symbol ',', and store the PCSs under the ID 'Tb'.")
383 uf.desc[-1].add_prompt("relax> pcs.read('Tb', 'Tb.txt', sep=',')")
384 uf.desc[-1].add_paragraph("To read the 15N and 1H PCSs from the file 'Eu.txt', where the 15N values are in the 4th column and the 1H in the 9th, type both the following:")
385 uf.desc[-1].add_prompt("relax> pcs.read('Tb', 'Tb.txt', spin_id='@N', res_num_col=1, data_col=4)")
386 uf.desc[-1].add_prompt("relax> pcs.read('Tb', 'Tb.txt', spin_id='@H', res_num_col=1, data_col=9)")
387 uf.backend = pcs.read
388 uf.menu_text = "&read"
389 uf.gui_icon = "oxygen.actions.document-open"
390 uf.wizard_size = (900, 600)
391 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
392
393
394
395 uf = uf_info.add_uf('pcs.set_errors')
396 uf.title = "Set the errors for the PCSs."
397 uf.title_short = "PCS error setting."
398 uf.add_keyarg(
399 name = "align_id",
400 py_type = "str",
401 desc_short = "alignment ID string",
402 desc = "The optional alignment ID string.",
403 wiz_element_type = 'combo',
404 wiz_combo_iter = align_tensor.get_align_ids,
405 wiz_read_only = True,
406 can_be_none = True
407 )
408 uf.add_keyarg(
409 name = "spin_id",
410 py_type = "str",
411 arg_type = "spin ID",
412 desc_short = "spin ID string",
413 desc = "The optional spin ID string.",
414 wiz_combo_iter = get_spin_ids,
415 can_be_none = True
416 )
417 uf.add_keyarg(
418 name = "sd",
419 default = 0.1,
420 py_type = "num",
421 desc_short = "PCS error (ppm)",
422 desc = "The PCS standard deviation value in ppm."
423 )
424
425 uf.desc.append(Desc_container())
426 uf.desc[-1].add_paragraph("If the PCS errors have not already been read from a PCS data file or if they need to be changed, then the errors can be set via this user function.")
427 uf.backend = pcs.set_errors
428 uf.menu_text = "&set_errors"
429 uf.gui_icon = "oxygen.actions.edit-rename"
430 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
431
432
433
434 uf = uf_info.add_uf('pcs.structural_noise')
435 uf.title = "Determine the PCS error due to structural noise via simulation."
436 uf.title_short = "PCS structural noise simulation."
437 uf.display = True
438 uf.add_keyarg(
439 name = "align_id",
440 py_type = "str",
441 desc_short = "alignment ID string",
442 desc = "The optional alignment ID string.",
443 wiz_element_type = 'combo',
444 wiz_combo_iter = align_tensor.get_align_ids,
445 wiz_read_only = True,
446 can_be_none = True
447 )
448 uf.add_keyarg(
449 name = "rmsd",
450 default = 0.2,
451 py_type = "float",
452 desc_short = "structural RMSD",
453 desc = "The atomic position RMSD, in Angstrom, to randomise the spin positions with for the simulations."
454 )
455 uf.add_keyarg(
456 name = "sim_num",
457 default = 1000,
458 min = 3,
459 max = 10000000,
460 py_type = "int",
461 desc_short = "simulation number N",
462 desc = "The number of simulations, N, to perform to determine the structural noise component of the PCS errors."
463 )
464 uf.add_keyarg(
465 name = "file",
466 py_type = "str",
467 arg_type = "file sel",
468 desc_short = "Grace file name",
469 desc = "The optional name of the Grace file to plot the structural errors verses the paramagnetic centre to spin distances.",
470 wiz_filesel_wildcard = "Grace files (*.agr)|*.agr;*.AGR",
471 wiz_filesel_style = FD_SAVE,
472 can_be_none = True
473 )
474 uf.add_keyarg(
475 name = "dir",
476 py_type = "str",
477 arg_type = "dir",
478 desc_short = "directory name",
479 desc = "The directory name to place the Grace file into.",
480 can_be_none = True
481 )
482 uf.add_keyarg(
483 name = "force",
484 default = False,
485 py_type = "bool",
486 desc_short = "force flag",
487 desc = "A flag which if True will cause the file to be overwritten."
488 )
489
490 uf.desc.append(Desc_container())
491 uf.desc[-1].add_paragraph("The analysis of the pseudo-contact shift is influenced by two significant sources of noise - that of the NMR experiment and structural noise from the 3D molecular structure used. The closer the spin to the paramagnetic centre, the greater the influence of structural noise. This distance dependence is governed by the equation:")
492 uf.desc[-1].add_verbatim("""
493 sqrt(3) * abs(delta) * RMSD
494 sigma_dist = --------------------------- ,
495 r
496 """)
497 uf.desc[-1].add_paragraph("where sigma_dist is the distance component of the structural noise as a standard deviation, delta is the PCS value, RMSD is the atomic position root-mean-square deviation, and r is the paramagnetic centre to spin distance. When close to the paramagnetic centre, this error source can exceed that of the NMR experiment. The equation for the angular component of the structural noise is more complicated. The PCS error is influenced by distance, angle in the alignment frame, and the magnetic susceptibility tensor.")
498 uf.desc[-1].add_paragraph("For the simulation the following must already be set up in the current data pipe:")
499 uf.desc[-1].add_list_element("The position of the paramagnetic centre.")
500 uf.desc[-1].add_list_element("The alignment and magnetic susceptibility tensor.")
501 uf.desc[-1].add_paragraph("The protocol for the simulation is as follows:")
502 uf.desc[-1].add_list_element("The lanthanide or paramagnetic centre position will be fixed. Its motion is assumed to be on the femto- to pico- and nanosecond timescales. Hence the motion is averaged over the evolution of the PCS and can be ignored.")
503 uf.desc[-1].add_list_element("The positions of the nuclear spins will be randomised N times. For each simulation a random unit vector will be generated. Then a random distance along the unit vector will be generated by sampling from a Gaussian distribution centered at zero, the original spin position, with a standard deviation set to the given RMSD. Both positive and negative displacements will be used.")
504 uf.desc[-1].add_list_element("The PCS for the randomised position will be back calculated.")
505 uf.desc[-1].add_list_element("The PCS standard deviation will be calculated from the N randomised PCS values.")
506 uf.desc[-1].add_paragraph("The standard deviation will both be stored in the spin container data structure in the relax data store as well as being added to the already present PCS error (using variance addition). This will then be used in any optimisations involving the PCS.")
507 uf.desc[-1].add_paragraph("If the alignment ID string is not supplied, the procedure will be applied to the PCS data from all alignments.")
508 uf.backend = pcs.structural_noise
509 uf.menu_text = "&structural_noise"
510 uf.wizard_size = (1000, 700)
511 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
512 uf.wizard_apply_button = False
513
514
515
516 uf = uf_info.add_uf('pcs.weight')
517 uf.title = "Set optimisation weights on the PCS data."
518 uf.title_short = "PCS weighting."
519 uf.add_keyarg(
520 name = "align_id",
521 py_type = "str",
522 desc_short = "alignment ID string",
523 desc = "The alignment ID string.",
524 wiz_element_type = 'combo',
525 wiz_combo_iter = align_tensor.get_align_ids,
526 wiz_read_only = True
527 )
528 uf.add_keyarg(
529 name = "spin_id",
530 py_type = "str",
531 desc_short = "spin ID string",
532 desc = "The spin ID string."
533 )
534 uf.add_keyarg(
535 name = "weight",
536 default = 1.0,
537 py_type = "num",
538 desc_short = "weight",
539 desc = "The weighting value."
540 )
541
542 uf.desc.append(Desc_container())
543 uf.desc[-1].add_paragraph("This can be used to force the PCS to contribute more or less to the chi-squared optimisation statistic. The higher the value, the more importance the PCS will have.")
544 uf.backend = pcs.weight
545 uf.menu_text = "wei&ght"
546 uf.wizard_size = (700, 500)
547 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
548
549
550
551 uf = uf_info.add_uf('pcs.write')
552 uf.title = "Write the PCS data to file."
553 uf.title_short = "PCS data writing."
554 uf.add_keyarg(
555 name = "align_id",
556 py_type = "str",
557 desc_short = "alignment ID string",
558 desc = "The alignment ID string.",
559 wiz_element_type = 'combo',
560 wiz_combo_iter = align_tensor.get_align_ids,
561 wiz_read_only = True
562 )
563 uf.add_keyarg(
564 name = "file",
565 py_type = "str",
566 arg_type = "file sel",
567 desc_short = "file name",
568 desc = "The name of the file.",
569 wiz_filesel_style = FD_SAVE
570 )
571 uf.add_keyarg(
572 name = "dir",
573 py_type = "str",
574 arg_type = "dir",
575 desc_short = "directory name",
576 desc = "The directory name.",
577 can_be_none = True
578 )
579 uf.add_keyarg(
580 name = "bc",
581 default = False,
582 py_type = "bool",
583 desc_short = "back-calculation flag",
584 desc = "A flag which if set will write out the back-calculated rather than measured RDCs."
585 )
586 uf.add_keyarg(
587 name = "force",
588 default = False,
589 py_type = "bool",
590 desc_short = "force flag",
591 desc = "A flag which if True will cause the file to be overwritten."
592 )
593
594 uf.desc.append(Desc_container())
595 uf.desc[-1].add_paragraph("If no directory name is given, the file will be placed in the current working directory. The alignment ID is required for selecting which PCS data set will be written to file.")
596 uf.backend = pcs.write
597 uf.menu_text = "&write"
598 uf.gui_icon = "oxygen.actions.document-save"
599 uf.wizard_size = (800, 600)
600 uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
601