1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for the manipulation of the molecule-residue-spin data structures in the relax data store.
24
25 The functionality of this module is diverse:
26 - Documentation for the spin identification string.
27 - Functions for parsing or generating spin identification strings.
28 - The mol-res-spin selection object (derived from the Selection class).
29 - Generator functions for looping over molecules, residues, or spins.
30 - Functions for returning MoleculeContainer, ResidueContainer, and SpinContainer objects or information about these.
31 - Functions for copying, creating, deleting, displaying, naming, and numbering MoleculeContainer, ResidueContainer, and SpinContainer objects in the relax data store.
32 - Functions for counting spins or testing their existence.
33 """
34
35
36 from numpy import array, float64
37 from re import split
38 import sys
39 from textwrap import fill
40 from warnings import warn
41
42
43 from check_types import is_unicode
44 from data.mol_res_spin import MoleculeContainer, ResidueContainer, SpinContainer
45 from generic_fns import exp_info, pipes, relax_re
46 from relax_errors import RelaxError, RelaxNoSpinError, RelaxMultiMolIDError, RelaxMultiResIDError, RelaxMultiSpinIDError, RelaxResSelectDisallowError, RelaxSpinSelectDisallowError
47 from relax_warnings import RelaxWarning
48 from status import Status; status = Status()
49 from user_functions.objects import Desc_container
50
51
52 ALLOWED_MOL_TYPES = ['protein',
53 'DNA',
54 'RNA',
55 'organic molecule',
56 'inorganic molecule'
57 ]
58 """The list of allowable molecule types."""
59
60 id_string_doc = Desc_container("Spin ID string documentation")
61 id_string_doc.add_paragraph("The identification string is composed of three components: the molecule ID token beginning with the '#' character, the residue ID token beginning with the ':' character, and the atom or spin system ID token beginning with the '@' character. Each token can be composed of multiple elements - one per spin - separated by the ',' character and each individual element can either be a number (which must be an integer, in string format), a name, or a range of numbers separated by the '-' character. Negative numbers are supported. The full ID string specification is '#<mol_name> :<res_id>[, <res_id>[, <res_id>, ...]] @<atom_id>[, <atom_id>[, <atom_id>, ...]]', where the token elements are '<mol_name>', the name of the molecule, '<res_id>', the residue identifier which can be a number, name, or range of numbers, '<atom_id>', the atom or spin system identifier which can be a number, name, or range of numbers.")
62 id_string_doc.add_paragraph("If one of the tokens is left out then all elements will be assumed to match. For example if the string does not contain the '#' character then all molecules will match the string. If only the molecule ID component is specified, then all spins of the molecule will match.")
63 id_string_doc.add_paragraph("Regular expression can be used to select spins. For example the string '@H*' will select the protons 'H', 'H2', 'H98'.")
64
65
66
68 """An object containing mol-res-spin selections.
69
70 A Selection object represents either a set of selected molecules, residues and spins, or the union or intersection of two other Selection objects.
71 """
72
74 """Initialise a Selection object.
75
76 @param select_string: A mol-res-spin selection string.
77 @type select_string: string
78 """
79
80
81 if is_unicode(select_string):
82 select_string = str(select_string)
83
84 self._union = None
85 self._intersect = None
86
87 self.molecules = []
88 self.residues = []
89 self.spins = []
90
91 if not select_string:
92 return
93
94
95 and_index = select_string.rfind('&')
96 or_index = select_string.rfind('|')
97
98 if and_index > or_index:
99 sel0 = Selection(select_string[:and_index].strip())
100 sel1 = Selection(select_string[and_index+1:].strip())
101 self.intersection(sel0, sel1)
102
103 elif or_index > and_index:
104 sel0 = Selection(select_string[:or_index].strip())
105 sel1 = Selection(select_string[or_index+1:].strip())
106 self.union(sel0, sel1)
107
108
109 else:
110 mol_token, res_token, spin_token = tokenise(select_string)
111 self.molecules = parse_token(mol_token)
112 self.residues = parse_token(res_token)
113 self.spins = parse_token(spin_token)
114
115
117 """Replacement function for determining if an object matches the selection.
118
119 @param obj: The data object. This can be a MoleculeContainer, ResidueContainer, or SpinContainer instance or a type of these instances. If a tuple, only one type of object can be in the tuple.
120 @type obj: instance or type of instances.
121 @return: The answer of whether the object matches the selection.
122 @rtype: bool
123 """
124
125
126 if self._union:
127 return (obj in self._union[0]) or (obj in self._union[1])
128
129
130 elif self._intersect:
131 return (obj in self._intersect[0]) and (obj in self._intersect[1])
132
133
134 if isinstance(obj, str):
135 return self.__contains_spin_id(obj)
136
137
138 else:
139 return self.__contains_mol_res_spin_containers(obj)
140
141
143 """Are the MoleculeContainer, ResidueContainer, and/or SpinContainer in the selection.
144
145 @param obj: The data object. This can be a MoleculeContainer, ResidueContainer, or SpinContainer instance or a type of these instances. If a tuple, only one type of object can be in the tuple.
146 @type obj: instance or type of instances.
147 @return: The answer of whether the objects are found within the selection object.
148 @rtype: bool
149 """
150
151
152 mol = None
153 res = None
154 spin = None
155
156
157 if not isinstance(obj, tuple):
158 obj = (obj,)
159
160
161 if len(obj) > 3:
162 return False
163
164
165 for i in range(len(obj)):
166
167 if isinstance(obj[i], MoleculeContainer):
168
169 if mol != None:
170 raise RelaxError("Comparing two molecular containers simultaneously with the selection object is not supported.")
171
172
173 mol = obj[i]
174
175
176 elif isinstance(obj[i], ResidueContainer):
177
178 if res != None:
179 raise RelaxError("Comparing two residue containers simultaneously with the selection object is not supported.")
180
181
182 res = obj[i]
183
184
185 elif isinstance(obj[i], SpinContainer):
186
187 if spin != None:
188 raise RelaxError("Comparing two spin containers simultaneously with the selection object is not supported.")
189
190
191 spin = obj[i]
192
193
194 else:
195 return False
196
197
198 select_mol = False
199 select_res = False
200 select_spin = False
201
202
203 if mol:
204
205 if not self.molecules:
206 select_mol = True
207
208
209 elif relax_re.search(self.molecules, mol.name):
210 select_mol = True
211 else:
212
213 select_mol = True
214
215
216 if not select_mol:
217 return False
218
219
220 if res:
221
222 if not self.residues:
223 select_res = True
224
225
226 elif res.num in self.residues or relax_re.search(self.residues, res.name):
227 select_res = True
228 else:
229
230 select_res = True
231
232
233 if not select_res:
234 return False
235
236
237 if spin:
238
239 if not self.spins:
240 select_spin = True
241
242
243 elif spin.num in self.spins or relax_re.search(self.spins, spin.name):
244 select_spin = True
245 else:
246
247 select_spin = True
248
249
250 return select_mol and select_res and select_spin
251
252
254 """Is the molecule, residue, and/or spin of the spin_id string located in the selection.
255
256 Only the simple selections allowed by the tokenise function are currently supported.
257
258
259 @param spin_id: The spin identification string.
260 @type spin_id: str
261 @return: The answer of whether the molecule, residue, and/or spin corresponding to the spin_id string found within the selection object.
262 @rtype: bool
263 """
264
265
266 if spin_id == '':
267 warn(RelaxWarning("The spin ID string '' is empty."))
268 return False
269
270
271 mol_name, res_num, res_name, spin_num, spin_name = spin_id_to_data_list(spin_id)
272
273
274 return self.contains_spin(spin_num=spin_num, spin_name=spin_name, res_num=res_num, res_name=res_name, mol=mol_name)
275
276
278 """Determine if the molecule name, in string form, is contained in this selection object.
279
280 @keyword mol: The name of the molecule.
281 @type mol: str or None
282 @return: The answer of whether the molecule is contained withing the selection object.
283 @rtype: bool
284 """
285
286
287 if self._union:
288 return self._union[0].contains_mol(mol) or self._union[1].contains_mol(mol)
289
290
291 elif self._intersect:
292 return self._intersect[0].contains_mol(mol) and self._intersect[1].contains_mol(mol)
293
294
295 if relax_re.search(self.molecules, mol):
296 return True
297
298
299 if not self.molecules:
300 return True
301
302
303 return False
304
305
306 - def contains_res(self, res_num=None, res_name=None, mol=None):
307 """Determine if the residue name, in string form, is contained in this selection object.
308
309 @keyword res_num: The residue number.
310 @type res_num: int or None
311 @keyword res_name: The residue name.
312 @type res_name: str or None
313 @keyword mol: The molecule name.
314 @type mol: str or None
315 @return: The answer of whether the molecule is contained withing the selection object.
316 @rtype: bool
317 """
318
319
320 if self._union:
321 return self._union[0].contains_res(res_num, res_name, mol) or self._union[1].contains_res(res_num, res_name, mol)
322
323
324 elif self._intersect:
325 return self._intersect[0].contains_res(res_num, res_name, mol) and self._intersect[1].contains_res(res_num, res_name, mol)
326
327
328 select_mol = self.contains_mol(mol)
329
330
331 select_res = False
332
333
334 if res_num in self.residues or relax_re.search(self.residues, res_name):
335 select_res = True
336
337
338 if not self.residues:
339 select_res = True
340
341
342 return select_res and select_mol
343
344
345 - def contains_spin(self, spin_num=None, spin_name=None, res_num=None, res_name=None, mol=None):
346 """Determine if the spin is contained in this selection object.
347
348 @keyword spin_num: The spin number.
349 @type spin_num: int or None
350 @keyword spin_name: The spin name.
351 @type spin_name: str or None
352 @keyword res_num: The residue number.
353 @type res_num: int or None
354 @keyword res_name: The residue name.
355 @type res_name: str or None
356 @keyword mol: The molecule name.
357 @type mol: str or None
358 @return: The answer of whether the spin is contained withing the selection object.
359 @rtype: bool
360 """
361
362
363 if self._union:
364 return self._union[0].contains_spin(spin_num, spin_name, res_num, res_name, mol) or self._union[1].contains_spin(spin_num, spin_name, res_num, res_name, mol)
365
366
367 elif self._intersect:
368 return self._intersect[0].contains_spin(spin_num, spin_name, res_num, res_name, mol) and self._intersect[1].contains_spin(spin_num, spin_name, res_num, res_name, mol)
369
370
371 select_mol = self.contains_mol(mol)
372
373
374 select_res = self.contains_res(res_num, res_name, mol)
375
376
377 select_spin = False
378
379
380 if spin_num in self.spins or relax_re.search(self.spins, spin_name):
381 select_spin = True
382
383
384 if not self.spins:
385 select_spin = True
386
387
388 return select_spin and select_res and select_mol
389
390
392 """Determine if the selection object contains molecules.
393
394 @return: The answer of whether the selection contains molecules.
395 @rtype: bool
396 """
397
398
399 if self._union:
400 return self._union[0].has_molecules() or self._union[1].has_molecules()
401
402
403 elif self._intersect:
404 return self._intersect[0].has_molecules() and self._intersect[1].has_molecules()
405
406
407 if self.molecules:
408 return True
409
410
412 """Determine if the selection object contains residues.
413
414 @return: The answer of whether the selection contains residues.
415 @rtype: bool
416 """
417
418
419 if self._union:
420 return self._union[0].has_residues() or self._union[1].has_residues()
421
422
423 elif self._intersect:
424 return self._intersect[0].has_residues() and self._intersect[1].has_residues()
425
426
427 if self.residues:
428 return True
429
430
432 """Determine if the selection object contains spins.
433
434 @return: The answer of whether the selection contains spins.
435 @rtype: bool
436 """
437
438
439 if self._union:
440 return self._union[0].has_spins() or self._union[1].has_spins()
441
442
443 elif self._intersect:
444 return self._intersect[0].has_spins() and self._intersect[1].has_spins()
445
446
447 if self.spins:
448 return True
449
450
452 """Make this Selection object the intersection of two other Selection objects.
453
454 @param select_obj0: First Selection object in intersection.
455 @type select_obj0: Selection instance.
456 @param select_obj1: First Selection object in intersection.
457 @type select_obj1: Selection instance.
458 """
459
460
461 if self._union or self._intersect or self.molecules or self.residues or self.spins:
462 raise RelaxError("Cannot define multiple Boolean relationships between Selection objects")
463
464
465 self._intersect = (select_obj0, select_obj1)
466
467
468 - def union(self, select_obj0, select_obj1):
469 """Make this Selection object the union of two other Selection objects.
470
471 @param select_obj0: First Selection object in intersection.
472 @type select_obj0: Selection instance.
473 @param select_obj1: First Selection object in intersection.
474 @type select_obj1: Selection instance.
475 """
476
477
478 if self._union or self._intersect or self.molecules or self.residues or self.spins:
479 raise RelaxError("Cannot define multiple Boolean relationships between Selection objects")
480
481
482 self._union = (select_obj0, select_obj1)
483
484
485
487 """Determine if any spins have been named.
488
489 @keyword spin_id: The spin ID string.
490 @type spin_id: None or str
491 @return: True if a spin has been named or False if no spins have been named.
492 @rtype: bool
493 """
494
495
496 for spin in spin_loop(spin_id):
497
498 if spin.name != None:
499 return True
500
501
502 return False
503
504
506 """Generate the molecule and residue spin containers from the entity saveframe records.
507
508 @param star: The NMR-STAR dictionary object.
509 @type star: NMR_STAR instance
510 """
511
512
513 for data in star.entity.loop():
514
515 mol_name = data['mol_name']
516 if mol_name:
517
518 mol_name = mol_name.replace('(', '')
519 mol_name = mol_name.replace(')', '')
520
521
522 mol_name = mol_name.replace('[', '')
523 mol_name = mol_name.replace(']', '')
524
525
526 mol_name = mol_name.replace(',', ' ')
527
528
529 mol_type = data['mol_type']
530 polymer_type = data['polymer_type']
531
532
533 if mol_type == 'polymer':
534 map = {
535 'DNA/RNA hybrid': 'DNA',
536 'polydeoxyribonucleotide': 'DNA',
537 'polypeptide(D)': 'protein',
538 'polypeptide(L)': 'protein',
539 'polyribonucleotide': 'RNA',
540 'polysaccharide(D)': 'organic molecule',
541 'polysaccharide(L)': 'organic molecule'
542 }
543 mol_type = map[polymer_type]
544
545
546 create_molecule(mol_name=mol_name, mol_type=mol_type)
547
548
549 exp_info.thiol_state(data['thiol_state'])
550
551
552 for i in range(len(data['res_nums'])):
553 create_residue(data['res_nums'][i], data['res_names'][i], mol_name=mol_name)
554
555
557 """Generate the entity saveframe records for the NMR-STAR dictionary object.
558
559 @param star: The NMR-STAR dictionary object.
560 @type star: NMR_STAR instance
561 @keyword version: The BMRB NMR-STAR dictionary format to output to.
562 @type version: str
563 """
564
565
566 for mol in molecule_loop():
567
568 if not mol.name:
569 raise RelaxError("All molecules must be named.")
570
571
572 if not hasattr(mol, 'type') or not mol.type:
573 raise RelaxError("The molecule type for the '%s' molecule must be specified, please use the appropriate molecule user function to set this." % mol.name)
574
575
576 if not hasattr(cdp, 'exp_info') or not hasattr(cdp.exp_info, 'thiol_state'):
577 raise RelaxError("The thiol state of the molecule '%s' must be specified, please use the appropriate BMRB user function to set this." % mol.name)
578
579
580 res_names = get_residue_names("#" + mol.name)
581 res_nums = get_residue_nums("#" + mol.name)
582
583
584 polymer_seq_code = one_letter_code(res_names)
585
586
587 if mol.type in ['organic molecule', 'other']:
588 mol_type = 'non-polymer'
589 else:
590 mol_type = 'polymer'
591
592
593 polymer_type = mol.type
594 if polymer_type == 'protein':
595 polymer_type = 'polypeptide(L)'
596 if polymer_type == 'DNA':
597 polymer_type = 'polydeoxyribonucleotide'
598 if polymer_type == 'RNA':
599 polymer_type = 'polyribonucleotide'
600 if polymer_type == 'inorganic molecule':
601 polymer_type = 'other'
602
603
604 star.entity.add(mol_name=mol.name, mol_type=mol_type, polymer_type=polymer_type, polymer_seq_code=polymer_seq_code, thiol_state=cdp.exp_info.thiol_state, res_nums=res_nums, res_names=res_names)
605
606
607 -def copy_molecule(pipe_from=None, mol_from=None, pipe_to=None, mol_to=None):
608 """Copy the contents of a molecule container to a new molecule.
609
610 For copying to be successful, the mol_from identification string must match an existent molecule.
611
612
613 @param pipe_from: The data pipe to copy the molecule data from. This defaults to the current data pipe.
614 @type pipe_from: str
615 @param mol_from: The molecule identification string for the structure to copy the data from.
616 @type mol_from: str
617 @param pipe_to: The data pipe to copy the molecule data to. This defaults to the current data pipe.
618 @type pipe_to: str
619 @param mol_to: The molecule identification string for the structure to copy the data to.
620 @type mol_to: str
621 """
622
623
624 status.spin_lock.acquire(sys._getframe().f_code.co_name)
625 try:
626
627 if pipe_from == None:
628 pipe_from = pipes.cdp_name()
629 if pipe_to == None:
630 pipe_to = pipes.cdp_name()
631
632
633 pipes.test(pipe_to)
634
635
636 mol_from_token, res_from_token, spin_from_token = tokenise(mol_from)
637 mol_to_token, res_to_token, spin_to_token = tokenise(mol_to)
638
639
640 if spin_from_token != None or spin_to_token != None:
641 raise RelaxSpinSelectDisallowError
642
643
644 if res_from_token != None or res_to_token != None:
645 raise RelaxResSelectDisallowError
646
647
648 mol_name_to = return_single_molecule_info(mol_to_token)
649
650
651 mol_to_cont = return_molecule(mol_to, pipe_to)
652 if mol_to_cont and not mol_to_cont.is_empty():
653 raise RelaxError("The molecule " + repr(mol_to) + " already exists in the " + repr(pipe_to) + " data pipe.")
654
655
656 mol_from_cont = return_molecule(mol_from, pipe_from)
657
658
659 if mol_from_cont == None:
660 raise RelaxError("The molecule " + repr(mol_from) + " does not exist in the " + repr(pipe_from) + " data pipe.")
661
662
663 pipe = pipes.get_pipe(pipe_to)
664
665
666 if pipe.mol[0].name == None and len(pipe.mol) == 1:
667 pipe.mol[0] = mol_from_cont.__clone__()
668 else:
669 pipe.mol.append(mol_from_cont.__clone__())
670
671
672 if mol_name_to != None:
673 pipe.mol[-1].name = mol_name_to
674
675
676 metadata_update(pipe=pipe_to)
677
678
679 finally:
680 status.spin_lock.release(sys._getframe().f_code.co_name)
681
682
683 -def copy_residue(pipe_from=None, res_from=None, pipe_to=None, res_to=None):
684 """Copy the contents of the residue structure from one residue to a new residue.
685
686 For copying to be successful, the res_from identification string must match an existent residue. The new residue number must be unique.
687
688 @param pipe_from: The data pipe to copy the residue from. This defaults to the current data pipe.
689 @type pipe_from: str
690 @param res_from: The residue identification string for the structure to copy the data from.
691 @type res_from: str
692 @param pipe_to: The data pipe to copy the residue to. This defaults to the current data pipe.
693 @type pipe_to: str
694 @param res_to: The residue identification string for the structure to copy the data to.
695 @type res_to: str
696 """
697
698
699 status.spin_lock.acquire(sys._getframe().f_code.co_name)
700 try:
701
702 if pipe_from == None:
703 pipe_from = pipes.cdp_name()
704 if pipe_to == None:
705 pipe_to = pipes.cdp_name()
706
707
708 pipes.test(pipe_to)
709
710
711 pipe = pipes.get_pipe(pipe_to)
712
713
714 mol_from_token, res_from_token, spin_from_token = tokenise(res_from)
715 mol_to_token, res_to_token, spin_to_token = tokenise(res_to)
716
717
718 if spin_from_token != None or spin_to_token != None:
719 raise RelaxSpinSelectDisallowError
720
721
722 res_num_to, res_name_to = return_single_residue_info(res_to_token)
723
724
725 res_to_cont = return_residue(res_to, pipe_to)
726 if res_to_cont and not res_to_cont.is_empty():
727 raise RelaxError("The residue " + repr(res_to) + " already exists in the " + repr(pipe_to) + " data pipe.")
728
729
730 res_from_cont = return_residue(res_from, pipe_from)
731
732
733 if res_from_cont == None:
734 raise RelaxError("The residue " + repr(res_from) + " does not exist in the " + repr(pipe_from) + " data pipe.")
735
736
737 mol_to_container = return_molecule(res_to, pipe_to)
738 if mol_to_container == None:
739 mol_to_container = pipe.mol[0]
740
741
742 if mol_to_container.res[0].num == None and mol_to_container.res[0].name == None and len(mol_to_container.res) == 1:
743 mol_to_container.res[0] = res_from_cont.__clone__()
744 else:
745 mol_to_container.res.append(res_from_cont.__clone__())
746
747
748 if res_num_to != None:
749 mol_to_container.res[-1].num = res_num_to
750 if res_name_to != None:
751 mol_to_container.res[-1].name = res_name_to
752
753
754 metadata_update(pipe=pipe_to)
755
756
757 finally:
758 status.spin_lock.release(sys._getframe().f_code.co_name)
759
760
761 -def copy_spin(pipe_from=None, spin_from=None, pipe_to=None, spin_to=None):
762 """Copy the contents of the spin structure from one spin to a new spin.
763
764 For copying to be successful, the spin_from identification string must match an existent spin. The new spin number must be unique.
765
766
767 @param pipe_from: The data pipe to copy the spin from. This defaults to the current data pipe.
768 @type pipe_from: str
769 @param spin_from: The spin identification string for the structure to copy the data from.
770 @type spin_from: str
771 @param pipe_to: The data pipe to copy the spin to. This defaults to the current data pipe.
772 @type pipe_to: str
773 @param spin_to: The spin identification string for the structure to copy the data to.
774 @type spin_to: str
775 """
776
777
778 status.spin_lock.acquire(sys._getframe().f_code.co_name)
779 try:
780
781 if pipe_from == None:
782 pipe_from = pipes.cdp_name()
783 if pipe_to == None:
784 pipe_to = pipes.cdp_name()
785
786
787 pipes.test(pipe_to)
788
789
790 pipe = pipes.get_pipe(pipe_to)
791
792
793 mol_to_token, res_to_token, spin_to_token = tokenise(spin_to)
794
795
796 if spin_to_token:
797 spin_to_cont = return_spin(spin_to, pipe_to)
798 if spin_to_cont and not spin_to_cont.is_empty():
799 raise RelaxError("The spin " + repr(spin_to) + " already exists in the " + repr(pipe_from) + " data pipe.")
800
801
802 if not return_residue(spin_from, pipe_from):
803 raise RelaxError("The residue in " + repr(spin_from) + " does not exist in the " + repr(pipe_from) + " data pipe.")
804
805
806 spin_from_cont = return_spin(spin_from, pipe_from)
807 if spin_from_cont == None:
808 raise RelaxError("The spin " + repr(spin_from) + " does not exist in the " + repr(pipe_from) + " data pipe.")
809
810
811 res_to_cont = return_residue(spin_to, pipe_to)
812 if res_to_cont == None and spin_to:
813
814 raise RelaxError("The residue in " + repr(spin_to) + " does not exist in the " + repr(pipe_from) + " data pipe.")
815 if res_to_cont == None:
816 res_to_cont = pipe.mol[0].res[0]
817
818
819 if len(res_to_cont.spin) == 1 and res_to_cont.spin[0].is_empty():
820 res_to_cont.spin[0] = spin_from_cont.__clone__()
821 else:
822 res_to_cont.spin.append(spin_from_cont.__clone__())
823
824
825 spin_num_to, spin_name_to = return_single_spin_info(spin_to_token)
826
827
828 if spin_num_to != None:
829 res_to_cont.spin[-1].num = spin_num_to
830 if spin_name_to != None:
831 res_to_cont.spin[-1].name = spin_name_to
832
833
834 metadata_update(pipe=pipe_to)
835
836
837 finally:
838 status.spin_lock.release(sys._getframe().f_code.co_name)
839
840
842 """Count the number of molecules for which there is data.
843
844 @keyword selection: The selection string.
845 @type selection: str
846 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
847 @type pipe: str
848 @return: The number of non-empty molecules.
849 @rtype: int
850 """
851
852
853 if pipe == None:
854 pipe = pipes.cdp_name()
855
856
857 pipes.test(pipe)
858
859
860 if not exists_mol_res_spin_data(pipe=pipe):
861 return 0
862
863
864 mol_num = 0
865
866
867 for mol in molecule_loop(selection, pipe=pipe):
868 mol_num = mol_num + 1
869
870
871 return mol_num
872
873
875 """Count the number of residues for which there is data.
876
877 @keyword selection: The selection string.
878 @type selection: str
879 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
880 @type pipe: str
881 @return: The number of non-empty residues.
882 @rtype: int
883 """
884
885
886 if pipe == None:
887 pipe = pipes.cdp_name()
888
889
890 pipes.test(pipe)
891
892
893 if not exists_mol_res_spin_data(pipe=pipe):
894 return 0
895
896
897 res_num = 0
898
899
900 for res in residue_loop(selection, pipe=pipe):
901 res_num = res_num + 1
902
903
904 return res_num
905
906
907 -def count_spins(selection=None, pipe=None, skip_desel=True):
908 """Function for counting the number of spins for which there is data.
909
910 @keyword selection: The selection string.
911 @type selection: str
912 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
913 @type pipe: str
914 @keyword skip_desel: A flag which if true will cause deselected spins to be skipped in the count.
915 @type skip_desel: bool
916 @return: The number of non-empty spins.
917 @rtype: int
918 """
919
920
921 if pipe == None:
922 pipe = pipes.cdp_name()
923
924
925 pipes.test(pipe)
926
927
928 if not exists_mol_res_spin_data(pipe=pipe):
929 return 0
930
931
932 spin_num = 0
933
934
935 for spin in spin_loop(selection, pipe=pipe):
936
937 if skip_desel and not spin.select:
938 continue
939
940 spin_num = spin_num + 1
941
942
943 return spin_num
944
945
947 """Add a molecule into the relax data store.
948
949 @keyword mol_name: The name of the molecule.
950 @type mol_name: str
951 @keyword pipe: The data pipe to add the molecule to. Defaults to the current data pipe.
952 @type pipe: str or None
953 @keyword mol_type: The type of molecule.
954 @type mol_type: str
955 @return: The newly created molecule.
956 @rtype: MoleculeContainer instance
957 """
958
959
960 if pipe == None:
961 pipe = pipes.cdp_name()
962
963
964 pipes.test(pipe)
965
966
967 dp = pipes.get_pipe(pipe)
968
969
970 status.spin_lock.acquire(sys._getframe().f_code.co_name)
971 try:
972
973 if mol_type and mol_type not in ALLOWED_MOL_TYPES:
974 raise RelaxError("The molecule type '%s' must be one of %s" % (mol_type, ALLOWED_MOL_TYPES))
975
976
977 for i in range(len(dp.mol)):
978 if dp.mol[i].name == mol_name:
979 raise RelaxError("The molecule '" + repr(mol_name) + "' already exists in the relax data store.")
980
981
982 dp.mol.add_item(mol_name=mol_name, mol_type=mol_type)
983
984
985 mol = dp.mol[-1]
986
987
988 if len(dp.mol) == 2:
989 metadata_cleanup(pipe=pipe)
990 else:
991 metadata_cleanup(mol_index=len(dp.mol)-1, pipe=pipe)
992 metadata_update(mol_index=len(dp.mol)-1, pipe=pipe)
993
994
995 finally:
996 status.spin_lock.release(sys._getframe().f_code.co_name)
997
998
999 return mol
1000
1001
1002 -def create_residue(res_num=None, res_name=None, mol_name=None, pipe=None):
1003 """Add a residue into the relax data store (and molecule if necessary).
1004
1005 @keyword res_num: The number of the new residue.
1006 @type res_num: int
1007 @keyword res_name: The name of the new residue.
1008 @type res_name: str
1009 @keyword mol_name: The name of the molecule to add the residue to.
1010 @type mol_name: str
1011 @keyword pipe: The data pipe to add the residue to. Defaults to the current data pipe.
1012 @type pipe: str or None
1013 @return: The newly created residue.
1014 @rtype: ResidueContainer instance
1015 """
1016
1017
1018 if pipe == None:
1019 pipe = pipes.cdp_name()
1020
1021
1022 pipes.test(pipe)
1023
1024
1025 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1026 try:
1027
1028 mol_cont = return_molecule(generate_spin_id(pipe_name=pipe, mol_name=mol_name), pipe=pipe)
1029 if mol_cont == None:
1030 mol_cont = create_molecule(mol_name=mol_name, pipe=pipe)
1031
1032
1033 mol_cont.res.add_item(res_num=res_num, res_name=res_name)
1034
1035
1036 res = mol_cont.res[-1]
1037
1038
1039 if len(mol_cont.res) == 2:
1040 metadata_cleanup(mol_index=mol_cont._mol_index, pipe=pipe)
1041 else:
1042 metadata_cleanup(mol_index=mol_cont._mol_index, res_index=len(mol_cont.res)-1, pipe=pipe)
1043 metadata_update(mol_index=mol_cont._mol_index, res_index=len(mol_cont.res)-1, pipe=pipe)
1044
1045
1046 finally:
1047 status.spin_lock.release(sys._getframe().f_code.co_name)
1048
1049
1050 return res
1051
1052
1053 -def create_pseudo_spin(spin_name=None, spin_num=None, res_id=None, members=None, averaging=None, pipe=None):
1054 """Add a pseudo-atom spin container into the relax data store.
1055
1056 @param spin_name: The name of the new pseudo-spin.
1057 @type spin_name: str
1058 @param spin_num: The identification number of the new spin.
1059 @type spin_num: int
1060 @param res_id: The molecule and residue identification string.
1061 @type res_id: str
1062 @keyword pipe: The data pipe to add the spin to. Defaults to the current data pipe.
1063 @type pipe: str or None
1064 """
1065
1066
1067 if pipe == None:
1068 pipe = pipes.cdp_name()
1069
1070
1071 pipes.test()
1072
1073
1074 dp = pipes.get_pipe(pipe)
1075
1076
1077 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1078 try:
1079
1080 mol_token, res_token, spin_token = tokenise(res_id)
1081
1082
1083 if spin_token != None:
1084 raise RelaxSpinSelectDisallowError
1085
1086
1087 if res_id:
1088 res_to_cont, mol_index, res_index = return_residue(res_id, pipe=pipe, indices=True)
1089 if res_to_cont == None:
1090 raise RelaxError("The residue in " + repr(res_id) + " does not exist in the current data pipe.")
1091 else:
1092 res_to_cont = dp.mol[0].res[0]
1093 mol_index = 0
1094 res_index = 0
1095
1096
1097 if averaging not in ['linear']:
1098 raise RelaxError("The '%s' averaging technique is unknown." % averaging)
1099
1100
1101 positions = []
1102 for atom in members:
1103
1104 spin = return_spin(atom, pipe=pipe)
1105
1106
1107 if spin == None:
1108 raise RelaxNoSpinError(atom)
1109
1110
1111 if not hasattr(spin, 'pos') or spin.pos == None:
1112 raise RelaxError("Positional information is not available for the atom '%s'." % atom)
1113
1114
1115 pos = spin.pos
1116
1117
1118 multi_model = True
1119 if type(pos[0]) in [float, float64]:
1120 multi_model = False
1121 pos = [pos]
1122
1123
1124 positions.append([])
1125 for i in range(len(pos)):
1126 positions[-1].append(pos[i].tolist())
1127
1128
1129 for atom in members:
1130
1131 spin = return_spin(atom, pipe=pipe)
1132
1133
1134 if res_id:
1135 spin.pseudo_name = res_id + '@' + spin_name
1136 else:
1137 spin.pseudo_name = '@' + spin_name
1138 spin.pseudo_num = spin_num
1139
1140
1141 res_to_cont.spin.add_item(spin_num=spin_num, spin_name=spin_name)
1142 spin = res_to_cont.spin[-1]
1143 spin_index = len(res_to_cont.spin) - 1
1144
1145
1146 spin.averaging = averaging
1147 spin.members = members
1148 if averaging == 'linear':
1149
1150 ave = linear_ave(positions)
1151
1152
1153 if multi_model:
1154 spin.pos = ave
1155 else:
1156 spin.pos = ave[0]
1157
1158
1159 metadata_cleanup(mol_index=mol_index, res_index=res_index, pipe=pipe)
1160 metadata_update(mol_index=mol_index, res_index=res_index, pipe=pipe)
1161
1162
1163 finally:
1164 status.spin_lock.release(sys._getframe().f_code.co_name)
1165
1166
1167 -def create_spin(spin_num=None, spin_name=None, res_num=None, res_name=None, mol_name=None, pipe=None):
1168 """Add a spin into the relax data store (and molecule and residue if necessary).
1169
1170 @keyword spin_num: The number of the new spin.
1171 @type spin_num: int
1172 @keyword spin_name: The name of the new spin.
1173 @type spin_name: str
1174 @keyword res_num: The number of the residue to add the spin to.
1175 @type res_num: int
1176 @keyword res_name: The name of the residue to add the spin to.
1177 @type res_name: str
1178 @keyword mol_name: The name of the molecule to add the spin to.
1179 @type mol_name: str
1180 @keyword pipe: The data pipe to add the spin to. Defaults to the current data pipe.
1181 @type pipe: str or None
1182 @return: The newly created spin.
1183 @rtype: SpinContainer instance
1184 """
1185
1186
1187 if pipe == None:
1188 pipe = pipes.cdp_name()
1189
1190
1191 pipes.test()
1192
1193
1194 dp = pipes.get_pipe(pipe)
1195
1196
1197 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1198 try:
1199
1200 mol_index = index_molecule(mol_name, pipe=pipe)
1201 if mol_index == None:
1202 create_molecule(mol_name=mol_name, pipe=pipe)
1203 mol_index = len(dp.mol) - 1
1204
1205
1206 res_index = index_residue(res_num=res_num, res_name=res_name, mol_index=mol_index, pipe=pipe)
1207 if res_index == None:
1208 create_residue(mol_name=mol_name, res_num=res_num, res_name=res_name, pipe=pipe)
1209 res_index = len(dp.mol[mol_index].res) - 1
1210
1211
1212 res_cont = dp.mol[mol_index].res[res_index]
1213
1214
1215 if len(res_cont.spin) == 1 and res_cont.spin[0].is_empty():
1216 spin_cont = res_cont.spin[0]
1217 spin_cont.name = spin_name
1218 spin_cont.num = spin_num
1219
1220
1221 else:
1222 res_cont.spin.add_item(spin_num=spin_num, spin_name=spin_name)
1223 spin_cont = res_cont.spin[-1]
1224
1225
1226 spin_index = len(res_cont.spin) - 1
1227 spin_id = generate_spin_id(pipe_cont=dp, mol_name=mol_name, res_num=res_num, res_name=res_name, spin_num=spin_num, spin_name=spin_name)
1228
1229
1230 if len(res_cont.spin) == 2:
1231 metadata_cleanup(mol_index=mol_index, res_index=res_index, pipe=pipe)
1232 else:
1233 metadata_cleanup(mol_index=mol_index, res_index=res_index, spin_index=spin_index, pipe=pipe)
1234 metadata_update(mol_index=mol_index, res_index=res_index, spin_index=spin_index, pipe=pipe)
1235
1236
1237 finally:
1238 status.spin_lock.release(sys._getframe().f_code.co_name)
1239
1240
1241 return spin_cont
1242
1243
1245 """Convert the global index into the molecule, residue, and spin indices.
1246
1247 @param global_index: The global spin index, spanning the molecule and residue containers.
1248 @type global_index: int
1249 @param pipe: The data pipe containing the spin. Defaults to the current data pipe.
1250 @type pipe: str
1251 @return: The corresponding molecule, residue, and spin indices.
1252 @rtype: tuple of int
1253 """
1254
1255
1256 if pipe == None:
1257 pipe = pipes.cdp_name()
1258
1259
1260 pipes.test(pipe)
1261
1262
1263 spin_num = 0
1264 for mol_index, res_index, spin_index in spin_index_loop(pipe=pipe):
1265
1266 if spin_num == global_index:
1267 return mol_index, res_index, spin_index
1268
1269
1270 spin_num = spin_num + 1
1271
1272
1274 """Function for deleting molecules from the current data pipe.
1275
1276 @param mol_id: The molecule identifier string.
1277 @type mol_id: str
1278 """
1279
1280
1281 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1282 try:
1283
1284 mol_token, res_token, spin_token = tokenise(mol_id)
1285
1286
1287 if spin_token != None:
1288 raise RelaxSpinSelectDisallowError
1289
1290
1291 if res_token != None:
1292 raise RelaxResSelectDisallowError
1293
1294
1295 molecules = parse_token(mol_token)
1296
1297
1298 indices = []
1299
1300
1301 for i in range(len(cdp.mol)):
1302
1303 if cdp.mol[i].name in molecules:
1304 indices.append(i)
1305
1306
1307 indices.reverse()
1308
1309
1310 for index in indices:
1311 metadata_prune(mol_index=index)
1312
1313
1314 for index in indices:
1315 cdp.mol.pop(index)
1316
1317
1318 if len(cdp.mol) == 0:
1319 cdp.mol.add_item()
1320
1321
1322 finally:
1323 status.spin_lock.release(sys._getframe().f_code.co_name)
1324
1325
1327 """Function for deleting residues from the current data pipe.
1328
1329 @param res_id: The molecule and residue identifier string.
1330 @type res_id: str
1331 """
1332
1333
1334 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1335 try:
1336
1337 mol_token, res_token, spin_token = tokenise(res_id)
1338
1339
1340 if spin_token != None:
1341 raise RelaxSpinSelectDisallowError
1342
1343
1344 residues = parse_token(res_token)
1345
1346
1347 for mol in molecule_loop(res_id):
1348
1349 indices = []
1350
1351
1352 for i in range(len(mol.res)):
1353
1354 if mol.res[i].num in residues or mol.res[i].name in residues:
1355 indices.append(i)
1356
1357
1358 indices.reverse()
1359
1360
1361 for index in indices:
1362 metadata_prune(mol_index=mol._mol_index, res_index=index)
1363
1364
1365 for index in indices:
1366 mol.res.pop(index)
1367
1368
1369 if len(mol.res) == 0:
1370 mol.res.add_item()
1371
1372
1373 finally:
1374 status.spin_lock.release(sys._getframe().f_code.co_name)
1375
1376
1378 """Function for deleting spins from the current data pipe.
1379
1380 @param spin_id: The molecule, residue, and spin identifier string.
1381 @type spin_id: str
1382 """
1383
1384
1385 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1386 try:
1387
1388
1389 mol_token, res_token, spin_token = tokenise(spin_id)
1390
1391
1392 spins = parse_token(spin_token)
1393
1394
1395 for res in residue_loop(spin_id):
1396
1397 indices = []
1398
1399
1400 for i in range(len(res.spin)):
1401
1402 if res.spin[i].num in spins or res.spin[i].name in spins:
1403 indices.append(i)
1404
1405
1406 indices.reverse()
1407
1408
1409 for index in indices:
1410 metadata_prune(mol_index=res._mol_index, res_index=res._res_index, spin_index=index)
1411
1412
1413 for index in indices:
1414 res.spin.pop(index)
1415
1416
1417 if len(res.spin) == 0:
1418 res.spin.add_item()
1419
1420
1421 finally:
1422 status.spin_lock.release(sys._getframe().f_code.co_name)
1423
1424
1426 """Function for displaying the information associated with the molecule.
1427
1428 @param mol_id: The molecule identifier string.
1429 @type mol_id: str
1430 """
1431
1432
1433 mol_token, res_token, spin_token = tokenise(mol_id)
1434
1435
1436 if res_token != None:
1437 raise RelaxResSelectDisallowError
1438 if spin_token != None:
1439 raise RelaxSpinSelectDisallowError
1440
1441
1442 if mol_token:
1443 mol_sel = '#' + mol_token
1444 else:
1445 mol_sel = None
1446
1447
1448 print("\n\n%-15s %-15s" % ("Molecule", "Number of residues"))
1449
1450
1451 for mol in molecule_loop(mol_sel):
1452
1453 print("%-15s %-15s" % (mol.name, repr(len(mol.res))))
1454
1455
1457 """Function for displaying the information associated with the residue.
1458
1459 @param res_id: The molecule and residue identifier string.
1460 @type res_id: str
1461 """
1462
1463
1464 mol_token, res_token, spin_token = tokenise(res_id)
1465
1466
1467 if spin_token != None:
1468 raise RelaxSpinSelectDisallowError
1469
1470
1471 print("\n\n%-15s %-15s %-15s %-15s" % ("Molecule", "Res number", "Res name", "Number of spins"))
1472
1473
1474 for res, mol_name in residue_loop(res_id, full_info=True):
1475 print("%-15s %-15s %-15s %-15s" % (mol_name, repr(res.num), res.name, repr(len(res.spin))))
1476
1477
1479 """Function for displaying the information associated with the spin.
1480
1481 @param spin_id: The molecule and residue identifier string.
1482 @type spin_id: str
1483 """
1484
1485
1486 print("\n\n%-15s %-15s %-15s %-15s %-15s" % ("Molecule", "Res number", "Res name", "Spin number", "Spin name"))
1487
1488
1489 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
1490
1491 print("%-15s %-15s %-15s %-15s %-15s" % (mol_name, repr(res_num), res_name, repr(spin.num), spin.name))
1492
1493
1495 """Function for determining if any molecule-residue-spin data exists.
1496
1497 @keyword pipe: The data pipe in which the molecule-residue-spin data will be checked for.
1498 @type pipe: str
1499 @return: The answer to the question about the existence of data.
1500 @rtype: bool
1501 """
1502
1503
1504 if pipe == None:
1505 pipe = pipes.cdp_name()
1506
1507
1508 pipes.test(pipe)
1509
1510
1511 dp = pipes.get_pipe(pipe)
1512
1513
1514 if dp.mol.is_empty():
1515 return False
1516
1517
1518 return True
1519
1520
1521 -def find_index(selection=None, pipe=None, global_index=True):
1522 """Find and return the spin index or indices for the selection string.
1523
1524 @keyword selection: The spin selection identifier.
1525 @type selection: str
1526 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
1527 @type pipe: str
1528 @keyword global_index: A flag which if True will cause the global index to be returned. If False, then the molecule, residue, and spin indices will be returned.
1529 @type global_index: bool
1530 @return: The global spin index or the molecule, residue, and spin indices.
1531 @rtype: int or tuple of 3 int
1532 """
1533
1534
1535 if pipe == None:
1536 pipe = pipes.cdp_name()
1537
1538
1539 pipes.test(pipe)
1540
1541
1542 dp = pipes.get_pipe(pipe)
1543
1544
1545 select_obj = Selection(selection)
1546
1547
1548 global_i = -1
1549 mol_index = -1
1550
1551
1552 for mol in dp.mol:
1553
1554 mol_index = mol_index + 1
1555
1556
1557 res_index = -1
1558
1559
1560 for res in mol.res:
1561
1562 res_index = res_index + 1
1563
1564
1565 spin_index = -1
1566
1567
1568 for spin in res.spin:
1569
1570 spin_index = spin_index + 1
1571 global_i = global_i + 1
1572
1573
1574 if (mol, res, spin) in select_obj:
1575
1576 if global_index:
1577 return global_i
1578 else:
1579 return mol_index, res_index, spin_index
1580
1581
1583 """Determine the first residue number.
1584
1585 @return: The number of the first residue.
1586 @rtype: int
1587 """
1588
1589
1590 mol = return_molecule(selection)
1591
1592
1593 return mol.res[0].num
1594
1595
1596 -def generate_spin_id(pipe_cont=None, pipe_name=None, mol_name=None, res_num=None, res_name=None, spin_num=None, spin_name=None):
1597 """Generate the spin selection string.
1598
1599 @keyword pipe_cont: The data pipe object.
1600 @type pipe_cont: PipeContainer instance
1601 @keyword pipe_name: The data pipe name.
1602 @type pipe_name: str
1603 @keyword mol_name: The molecule name.
1604 @type mol_name: str or None
1605 @keyword res_num: The residue number.
1606 @type res_num: int or None
1607 @keyword res_name: The residue name.
1608 @type res_name: str or None
1609 @keyword spin_num: The spin number.
1610 @type spin_num: int or None
1611 @keyword spin_name: The spin name.
1612 @type spin_name: str or None
1613 @return: The spin identification string.
1614 @rtype: str
1615 """
1616
1617
1618 if pipe_cont == None:
1619 pipe_cont = pipes.get_pipe(pipe_name)
1620
1621
1622 id = ""
1623
1624
1625 if mol_name != None:
1626 id = id + "#" + mol_name
1627
1628
1629 res_num_id = ''
1630 res_name_id = ''
1631 if res_num != None:
1632 res_num_id = id + ":" + str(res_num)
1633 res_num_exists = res_num_id in pipe_cont.mol._spin_id_lookup
1634 if res_name != None:
1635 res_name_id = id + ":" + res_name
1636 res_name_exists = res_name_id in pipe_cont.mol._spin_id_lookup
1637
1638
1639 if res_name != None and res_num != None:
1640 if res_num_exists and res_name_exists:
1641 id = res_num_id
1642 elif not res_num_exists or not res_name_exists:
1643 id = res_num_id
1644 elif res_num_exists:
1645 id = res_num_id
1646 elif res_name_exists:
1647 id = res_name_id
1648 elif res_num != None:
1649 id = res_num_id
1650 elif res_name != None:
1651 id = res_name_id
1652 elif res_num != None:
1653 id = res_num_id
1654 elif res_name != None:
1655 id = res_name_id
1656
1657
1658 spin_num_id = ''
1659 spin_name_id = ''
1660 spin_num_exists = False
1661 spin_name_exists = False
1662 if spin_num != None:
1663 spin_num_id = id + "@" + str(spin_num)
1664 spin_num_exists = spin_num_id in pipe_cont.mol._spin_id_lookup
1665 if spin_name != None:
1666 spin_name_id = id + "@" + spin_name
1667 spin_name_exists = spin_name_id in pipe_cont.mol._spin_id_lookup
1668
1669
1670 if spin_name != None and spin_num != None:
1671 if spin_num_exists and spin_name_exists:
1672 id = spin_name_id
1673 elif not spin_num_exists or not spin_name_exists:
1674 id = spin_name_id
1675 elif spin_name_exists:
1676 id = spin_name_id
1677 elif spin_num_exists:
1678 id = spin_num_id
1679 elif spin_name != None:
1680 id = spin_name_id
1681 elif spin_num != None:
1682 id = spin_num_id
1683 elif spin_name != None:
1684 id = spin_name_id
1685 elif spin_num != None:
1686 id = spin_num_id
1687
1688
1689 return id
1690
1691
1692 -def generate_spin_id_data_array(data=None, mol_name_col=None, res_num_col=None, res_name_col=None, spin_num_col=None, spin_name_col=None):
1693 """Generate the spin selection string from the given data array.
1694
1695 @param data: An array containing the molecule, residue, and/or spin data.
1696 @type data: list of str
1697 @param mol_name_col: The column containing the molecule name information.
1698 @type mol_name_col: int or None
1699 @param res_name_col: The column containing the residue name information.
1700 @type res_name_col: int or None
1701 @param res_num_col: The column containing the residue number information.
1702 @type res_num_col: int or None
1703 @param spin_name_col: The column containing the spin name information.
1704 @type spin_name_col: int or None
1705 @param spin_num_col: The column containing the spin number information.
1706 @type spin_num_col: int or None
1707 @return: The spin identification string.
1708 @rtype: str
1709 """
1710
1711
1712 id = ""
1713
1714
1715 if mol_name_col and data[mol_name_col-1] not in [None, 'None']:
1716 id = id + "#" + data[mol_name_col-1]
1717
1718
1719 if res_num_col and data[res_num_col-1] not in [None, 'None']:
1720 id = id + ":" + str(data[res_num_col-1])
1721 elif res_name_col and data[res_name_col-1] not in [None, 'None']:
1722 id = id + ":" + data[res_name_col-1]
1723
1724
1725 if spin_num_col and data[spin_num_col-1] not in [None, 'None']:
1726 id = id + "@" + str(data[spin_num_col-1])
1727 elif spin_name_col and data[spin_name_col-1] not in [None, 'None']:
1728 id = id + "@" + data[spin_name_col-1]
1729
1730
1731 return id
1732
1733
1734 -def generate_spin_id_unique(pipe_cont=None, pipe_name=None, mol=None, res=None, spin=None, mol_name=None, res_num=None, res_name=None, spin_num=None, spin_name=None):
1735 """Generate a list of spin ID variants for the given set of molecule, residue and spin indices.
1736
1737 @keyword pipe_cont: The data pipe object.
1738 @type pipe_cont: PipeContainer instance
1739 @keyword pipe_name: The data pipe name.
1740 @type pipe_name: str
1741 @keyword mol: The molecule container.
1742 @type mol: MoleculeContainer instance
1743 @keyword res: The residue container.
1744 @type res: ResidueContainer instance
1745 @keyword spin: The spin container.
1746 @type spin: SpinContainer instance
1747 @keyword mol_name: The molecule name (an alternative to the molecule container).
1748 @type mol_name: str or None
1749 @keyword res_num: The residue number (an alternative to the residue container).
1750 @type res_num: int or None
1751 @keyword res_name: The residue name (an alternative to the residue container).
1752 @type res_name: str or None
1753 @keyword spin_num: The spin number (an alternative to the spin container).
1754 @type spin_num: int or None
1755 @keyword spin_name: The spin name (an alternative to the spin container).
1756 @type spin_name: str or None
1757 @return: The unique spin ID.
1758 @rtype: str
1759 """
1760
1761
1762 if pipe_cont == None:
1763 pipe_cont = pipes.get_pipe(pipe_name)
1764
1765
1766 if mol == None:
1767 mol = return_molecule_by_name(pipe_cont=pipe_cont, mol_name=mol_name)
1768 if mol != None and res == None:
1769 if res_name != None or res_num != None:
1770 res = return_residue_by_info(mol=mol, res_name=res_name, res_num=res_num)
1771 elif len(mol.res) == 1:
1772 res = mol.res[0]
1773 if res != None and spin == None:
1774 if spin_name != None or spin_num != None:
1775 spin = return_spin_by_info(res=res, spin_name=spin_name, spin_num=spin_num)
1776 elif len(res.spin) == 1:
1777 spin = res.spin[0]
1778
1779
1780 if mol:
1781 mol_name = mol.name
1782 if res:
1783 res_name = res.name
1784 res_num = res.num
1785 if spin:
1786 spin_name = spin.name
1787 spin_num = spin.num
1788
1789
1790 unique_res_name = True
1791 if res and res.name != None and mol._res_name_count[res.name] > 1:
1792 unique_res_name = False
1793 unique_res_num = True
1794 if res and res.num != None and mol._res_num_count[res.num] > 1:
1795 unique_res_num = False
1796 unique_spin_name = True
1797 if spin and spin.name != None and res._spin_name_count[spin.name] > 1:
1798 unique_spin_name = False
1799 unique_spin_num = True
1800 if spin and spin.num != None and res._spin_num_count[spin.num] > 1:
1801 unique_spin_num = False
1802
1803
1804 if unique_res_num and unique_spin_name:
1805 return generate_spin_id(pipe_cont=pipe_cont, mol_name=mol_name, res_num=res_num, spin_name=spin_name)
1806 if unique_res_num and unique_spin_num:
1807 return generate_spin_id(pipe_cont=pipe_cont, mol_name=mol_name, res_num=res_num, spin_num=spin_num)
1808 if unique_res_name and unique_spin_num:
1809 return generate_spin_id(pipe_cont=pipe_cont, mol_name=mol_name, res_name=res_name, spin_num=spin_num)
1810 if unique_res_name and unique_spin_name:
1811 return generate_spin_id(pipe_cont=pipe_cont, mol_name=mol_name, res_name=res_name, spin_name=spin_name)
1812
1813
1815 """Return a list of the molecule ID strings.
1816
1817 @param selection: The molecule selection identifier.
1818 @type selection: str
1819 @return: The molecule ID strings.
1820 @rtype: list of str
1821 """
1822
1823
1824 if not pipes.cdp_name():
1825 return []
1826
1827
1828 mol_ids = []
1829 for mol, mol_id in molecule_loop(selection, return_id=True):
1830 mol_ids.append(mol_id)
1831
1832
1833 return mol_ids
1834
1835
1837 """Return a list of the molecule names.
1838
1839 @param selection: The molecule selection identifier.
1840 @type selection: str
1841 @return: The molecule names.
1842 @rtype: list of str
1843 """
1844
1845
1846 if not pipes.cdp_name():
1847 return []
1848
1849
1850 mol_names = []
1851 for mol in molecule_loop(selection):
1852 mol_names.append(mol.name)
1853
1854
1855 return mol_names
1856
1857
1859 """Return a list of the residue ID strings.
1860
1861 @param selection: The molecule and residue selection identifier.
1862 @type selection: str
1863 @return: The residue ID strings.
1864 @rtype: list of str
1865 """
1866
1867
1868 if not pipes.cdp_name():
1869 return []
1870
1871
1872 res_ids = []
1873 for res, res_id in residue_loop(selection, return_id=True):
1874 res_ids.append(res_id)
1875
1876
1877 return res_ids
1878
1879
1881 """Return a list of the residue names.
1882
1883 @param selection: The molecule and residue selection identifier.
1884 @type selection: str
1885 @return: The residue names.
1886 @rtype: list of str
1887 """
1888
1889
1890 if not pipes.cdp_name():
1891 return []
1892
1893
1894 res_names = []
1895 for res in residue_loop(selection):
1896 res_names.append(res.name)
1897
1898
1899 return res_names
1900
1901
1903 """Return a list of the residue numbers.
1904
1905 @param selection: The molecule and residue selection identifier.
1906 @type selection: str
1907 @return: The residue numbers.
1908 @rtype: list of str
1909 """
1910
1911
1912 if not pipes.cdp_name():
1913 return []
1914
1915
1916 res_nums = []
1917 for res in residue_loop(selection):
1918 res_nums.append(res.num)
1919
1920
1921 return res_nums
1922
1923
1925 """Return a list of the spin ID strings.
1926
1927 @param selection: The molecule and spin selection identifier.
1928 @type selection: str
1929 @return: The spin ID strings.
1930 @rtype: list of str
1931 """
1932
1933
1934 if not pipes.cdp_name():
1935 return []
1936
1937
1938 spin_ids = []
1939 for spin, spin_id in spin_loop(selection, return_id=True):
1940 spin_ids.append(spin_id)
1941
1942
1943 return spin_ids
1944
1945
1947 """Return the index of the molecule of the given name.
1948
1949 @keyword mol_name: The name of the molecule.
1950 @type mol_name: str or None
1951 @keyword pipe: The data pipe, defaulting to the current data pipe.
1952 @type pipe: str or None
1953 @return: The index of the molecule, if it exists.
1954 @rtype: int or None
1955 """
1956
1957
1958 if pipe == None:
1959 pipe = pipes.cdp_name()
1960
1961
1962 pipes.test(pipe)
1963
1964
1965 dp = pipes.get_pipe(pipe)
1966
1967
1968 if mol_name == None and len(dp.mol) == 1:
1969 return 0
1970
1971
1972 i = 0
1973 for mol in dp.mol:
1974
1975 if mol.name == mol_name:
1976 return i
1977
1978
1979 i += 1
1980
1981
1982 return None
1983
1984
1985 -def index_residue(res_num=None, res_name=None, mol_index=None, pipe=None):
1986 """Return the index of the residue.
1987
1988 @keyword res_num: The number of the residue.
1989 @type res_num: int
1990 @keyword res_name: The name of the residue.
1991 @type res_name: str
1992 @keyword mol_index: The index of the molecule.
1993 @type mol_index: str
1994 @keyword pipe: The data pipe, defaulting to the current data pipe.
1995 @type pipe: str or None
1996 @return: The index of the residue, if it exists.
1997 @rtype: int or None
1998 """
1999
2000
2001 if pipe == None:
2002 pipe = pipes.cdp_name()
2003
2004
2005 pipes.test(pipe)
2006
2007
2008 dp = pipes.get_pipe(pipe)
2009
2010
2011 if len(dp.mol[mol_index].res) == 1 and res_num == dp.mol[mol_index].res[0].num and res_name == dp.mol[mol_index].res[0].name:
2012 return 0
2013
2014
2015 i = 0
2016 for res in dp.mol[mol_index].res:
2017
2018 if res_num != None and res.num == res_num:
2019 return i
2020
2021
2022 if res_num == None and res_name != None and res.name == res_name:
2023 return i
2024
2025
2026 i += 1
2027
2028
2029 return None
2030
2031
2033 """Determine the last residue number.
2034
2035 @param selection: The molecule selection identifier.
2036 @type selection: str
2037 @return: The number of the last residue.
2038 @rtype: int
2039 """
2040
2041
2042 mol = return_molecule(selection)
2043
2044
2045 return mol.res[-1].num
2046
2047
2049 """Perform linear averaging of the atomic positions.
2050
2051 @param positions: The atomic positions. The first index is that of the positions to be averaged over. The second index is over the different models. The last index is over the x, y, and z coordinates.
2052 @type positions: list of lists of numpy float arrays
2053 @return: The averaged positions as a list of vectors.
2054 @rtype: list of numpy float arrays
2055 """
2056
2057
2058 ave = []
2059 for model_index in range(len(positions[0])):
2060
2061 ave.append(array([0.0, 0.0, 0.0]))
2062
2063
2064 for coord_index in range(3):
2065
2066 for atom_index in range(len(positions)):
2067 ave[model_index][coord_index] = ave[model_index][coord_index] + positions[atom_index][model_index][coord_index]
2068
2069
2070 ave[model_index][coord_index] = ave[model_index][coord_index] / len(positions)
2071
2072
2073 return ave
2074
2075
2146
2147
2253
2254
2325
2326
2411
2412
2414 """Generator function for looping over all the molecules of the given selection.
2415
2416 @param selection: The molecule selection identifier.
2417 @type selection: str
2418 @param pipe: The data pipe containing the molecule. Defaults to the current data pipe.
2419 @type pipe: str
2420 @keyword return_id: A flag which if True will cause the molecule identification string of the molecule spin to be returned in addition to the spin container.
2421 @type return_id: bool
2422 @return: The molecule specific data container.
2423 @rtype: instance of the MoleculeContainer class.
2424 """
2425
2426
2427 if pipe == None:
2428 pipe = pipes.cdp_name()
2429
2430
2431 pipes.test(pipe)
2432
2433
2434 dp = pipes.get_pipe(pipe)
2435
2436
2437 if not exists_mol_res_spin_data(pipe=pipe):
2438 return
2439
2440
2441 select_obj = Selection(selection)
2442
2443
2444 for mol in dp.mol:
2445
2446 if mol not in select_obj:
2447 continue
2448
2449
2450 if return_id:
2451 mol_id = generate_spin_id(pipe_cont=dp, mol_name=mol.name)
2452
2453
2454 if return_id:
2455 yield mol, mol_id
2456 else:
2457 yield mol
2458
2459
2461 """Name the molecules.
2462
2463 @param mol_id: The molecule identification string.
2464 @type mol_id: str
2465 @param name: The new molecule name.
2466 @type name: str
2467 @keyword force: A flag which if True will cause the named molecule to be renamed.
2468 @type force: bool
2469 """
2470
2471
2472 status.spin_lock.acquire(sys._getframe().f_code.co_name)
2473 try:
2474
2475
2476 mol = return_molecule(mol_id)
2477
2478
2479 select_obj = Selection(mol_id)
2480 if select_obj.has_residues():
2481 raise RelaxResSelectDisallowError
2482 if select_obj.has_spins():
2483 raise RelaxSpinSelectDisallowError
2484
2485
2486 if mol:
2487 if mol.name and not force:
2488 warn(RelaxWarning("The molecule '%s' is already named. Set the force flag to rename." % mol_id))
2489 else:
2490 mol.name = name
2491
2492
2493 metadata_cleanup(mol_index=mol._mol_index)
2494 metadata_update(mol_index=mol._mol_index)
2495
2496
2497 finally:
2498 status.spin_lock.release(sys._getframe().f_code.co_name)
2499
2500
2502 """Name the residues.
2503
2504 @param res_id: The residue identification string.
2505 @type res_id: str
2506 @param name: The new residue name.
2507 @type name: str
2508 @keyword force: A flag which if True will cause the named residue to be renamed.
2509 @type force: bool
2510 """
2511
2512
2513 status.spin_lock.acquire(sys._getframe().f_code.co_name)
2514 try:
2515
2516 select_obj = Selection(res_id)
2517 if select_obj.has_spins():
2518 raise RelaxSpinSelectDisallowError
2519
2520
2521 for res, mol_name in residue_loop(res_id, full_info=True):
2522 if res.name and not force:
2523 warn(RelaxWarning("The residue '%s' is already named. Set the force flag to rename." % generate_spin_id(mol_name=mol_name, res_num=res.num, res_name=res.name)))
2524 else:
2525 res.name = name
2526
2527
2528 metadata_cleanup(mol_index=res._mol_index, res_index=res._res_index)
2529 metadata_update(mol_index=res._mol_index, res_index=res._res_index)
2530
2531
2532 finally:
2533 status.spin_lock.release(sys._getframe().f_code.co_name)
2534
2535
2536 -def name_spin(spin_id=None, name=None, pipe=None, force=False):
2537 """Name the spins.
2538
2539 @keyword spin_id: The spin identification string.
2540 @type spin_id: str
2541 @keyword name: The new spin name.
2542 @type name: str
2543 @param pipe: The data pipe to operate on. Defaults to the current data pipe.
2544 @type pipe: str
2545 @keyword force: A flag which if True will cause the named spin to be renamed. If None, then the warning messages will not mention the need to change this flag to rename.
2546 @type force: bool or None
2547 """
2548
2549
2550 if pipe == None:
2551 pipe = pipes.cdp_name()
2552
2553
2554 pipes.test(pipe)
2555
2556
2557 status.spin_lock.acquire(sys._getframe().f_code.co_name)
2558 try:
2559
2560 for spin, id in spin_loop(spin_id, pipe=pipe, return_id=True):
2561 if spin.name and force != True:
2562 if force == False:
2563 warn(RelaxWarning("The spin '%s' is already named. Set the force flag to rename." % id))
2564 else:
2565 warn(RelaxWarning("The spin '%s' is already named." % id))
2566 else:
2567 spin.name = name
2568
2569
2570 metadata_cleanup(mol_index=spin._mol_index, res_index=spin._res_index, spin_index=spin._spin_index)
2571 metadata_update(mol_index=spin._mol_index, res_index=spin._res_index, spin_index=spin._spin_index)
2572
2573
2574 finally:
2575 status.spin_lock.release(sys._getframe().f_code.co_name)
2576
2577
2579 """Number the residues.
2580
2581 @param res_id: The residue identification string.
2582 @type res_id: str
2583 @param number: The new residue number.
2584 @type number: int
2585 @keyword force: A flag which if True will cause the numbered residue to be renumbered.
2586 @type force: bool
2587 """
2588
2589
2590 status.spin_lock.acquire(sys._getframe().f_code.co_name)
2591 try:
2592
2593 i = 0
2594 for res in residue_loop(res_id):
2595 i = i + 1
2596
2597
2598 if i > 1:
2599 raise RelaxError("The numbering of multiple residues is disallowed, each residue requires a unique number.")
2600
2601
2602 select_obj = Selection(res_id)
2603 if select_obj.has_spins():
2604 raise RelaxSpinSelectDisallowError
2605
2606
2607 for res, mol_name in residue_loop(res_id, full_info=True):
2608 if res.num and not force:
2609 warn(RelaxWarning("The residue '%s' is already numbered. Set the force flag to renumber." % generate_spin_id(mol_name=mol_name, res_num=res.num, res_name=res.name)))
2610 else:
2611 res.num = number
2612
2613
2614 metadata_cleanup(mol_index=res._mol_index, res_index=res._res_index)
2615 metadata_update(mol_index=res._mol_index, res_index=res._res_index)
2616
2617
2618 finally:
2619 status.spin_lock.release(sys._getframe().f_code.co_name)
2620
2621
2622 -def number_spin(spin_id=None, number=None, force=False):
2623 """Number the spins.
2624
2625 @param spin_id: The spin identification string.
2626 @type spin_id: str
2627 @param number: The new spin number.
2628 @type number: int
2629 @keyword force: A flag which if True will cause the numbered spin to be renumbered.
2630 @type force: bool
2631 """
2632
2633
2634 status.spin_lock.acquire(sys._getframe().f_code.co_name)
2635 try:
2636
2637 i = 0
2638 for spin in spin_loop(spin_id):
2639 i = i + 1
2640
2641
2642 if number != None and i > 1:
2643 raise RelaxError("The numbering of multiple spins is disallowed, as each spin requires a unique number.")
2644
2645
2646 for spin, id in spin_loop(spin_id, return_id=True):
2647 if spin.num and not force:
2648 warn(RelaxWarning("The spin '%s' is already numbered. Set the force flag to renumber." % id))
2649 else:
2650 spin.num = number
2651
2652
2653 metadata_cleanup(mol_index=spin._mol_index, res_index=spin._res_index, spin_index=spin._spin_index)
2654 metadata_update(mol_index=spin._mol_index, res_index=spin._res_index, spin_index=spin._spin_index)
2655
2656
2657 finally:
2658 status.spin_lock.release(sys._getframe().f_code.co_name)
2659
2660
2662 """Convert the list of residue names into a string of one letter residue codes.
2663
2664 Standard amino acids are converted to the one letter code. Unknown residues are labelled as 'X'.
2665
2666
2667 @param res_names: A list of residue names.
2668 @type res_names: list or str
2669 @return: The one letter codes for the residues.
2670 @rtype: str
2671 """
2672
2673
2674 aa_table = [
2675 ['Alanine', 'ALA', 'A'],
2676 ['Arginine', 'ARG', 'R'],
2677 ['Asparagine', 'ASN', 'N'],
2678 ['Aspartic acid', 'ASP', 'D'],
2679 ['Cysteine', 'CYS', 'C'],
2680 ['Glutamic acid', 'GLU', 'E'],
2681 ['Glutamine', 'GLN', 'Q'],
2682 ['Glycine', 'GLY', 'G'],
2683 ['Histidine', 'HIS', 'H'],
2684 ['Isoleucine', 'ILE', 'I'],
2685 ['Leucine', 'LEU', 'L'],
2686 ['Lysine', 'LYS', 'K'],
2687 ['Methionine', 'MET', 'M'],
2688 ['Phenylalanine', 'PHE', 'F'],
2689 ['Proline', 'PRO', 'P'],
2690 ['Serine', 'SER', 'S'],
2691 ['Threonine', 'THR', 'T'],
2692 ['Tryptophan', 'TRP', 'W'],
2693 ['Tyrosine', 'TYR', 'Y'],
2694 ['Valine', 'VAL', 'V']
2695 ]
2696
2697
2698 seq = ''
2699 for res in res_names:
2700
2701 match = False
2702 for i in range(len(aa_table)):
2703 if res.upper() == aa_table[i][1]:
2704 seq = seq + aa_table[i][2]
2705 match = True
2706 break
2707
2708
2709 if not match:
2710 seq = seq + 'X'
2711
2712
2713 return seq
2714
2715
2717 """Parse the token string and return a list of identifying numbers and names.
2718
2719 Firstly the token is split by the ',' character into its individual elements and all whitespace stripped from the elements. Numbers are converted to integers, names are left as strings, and ranges are converted into the full list of integers.
2720
2721
2722 @param token: The identification string, the elements of which are separated by commas. Each element can be either a single number, a range of numbers (two numbers separated by '-'), or a name.
2723 @type token: str
2724 @keyword verbosity: A flag which if True will cause a number of printouts to be activated.
2725 @type verbosity: bool
2726 @return: A list of identifying numbers and names.
2727 @rtype: list of int and str
2728 """
2729
2730
2731 if token == None:
2732 return []
2733
2734
2735 if not isinstance(token, list):
2736 tokens = [token]
2737 else:
2738 tokens = token
2739
2740
2741 id_list = []
2742 for token in tokens:
2743
2744 elements = split(',', token)
2745
2746
2747 for element in elements:
2748
2749 element = element.strip()
2750
2751
2752 indices= []
2753 for i in range(1, len(element)):
2754 if element[i] == '-':
2755 indices.append(i)
2756
2757
2758 valid_range = True
2759 if indices:
2760
2761 if len(indices) > 2:
2762 if verbosity:
2763 print("The range element " + repr(element) + " is invalid. Assuming the '-' character does not specify a range.")
2764 valid_range = False
2765
2766
2767 try:
2768 start = int(element[:indices[0]])
2769 end = int(element[indices[0]+1:])
2770 except ValueError:
2771 if verbosity:
2772 print("The range element " + repr(element) + " is invalid as either the start or end of the range are not integers. Assuming the '-' character does not specify a range.")
2773 valid_range = False
2774
2775
2776 if valid_range and start >= end:
2777 if verbosity:
2778 print("The starting number of the range element " + repr(element) + " needs to be less than the end number. Assuming the '-' character does not specify a range.")
2779 valid_range = False
2780
2781
2782 if valid_range:
2783 for i in range(start, end+1):
2784 id_list.append(i)
2785
2786
2787 else:
2788 id_list.append(element)
2789
2790
2791 else:
2792
2793 try:
2794 element = int(element)
2795 except ValueError:
2796 pass
2797
2798
2799 id_list.append(element)
2800
2801
2802 return id_list
2803
2804
2805 -def residue_loop(selection=None, pipe=None, full_info=False, return_id=False):
2806 """Generator function for looping over all the residues of the given selection.
2807
2808 @param selection: The residue selection identifier.
2809 @type selection: str
2810 @param pipe: The data pipe containing the residue. Defaults to the current data pipe.
2811 @type pipe: str
2812 @param full_info: A flag specifying if the amount of information to be returned. If false, only the data container is returned. If true, the molecule name, residue number, and residue name is additionally returned.
2813 @type full_info: boolean
2814 @keyword return_id: A flag which if True will cause the molecule identification string of the molecule spin to be returned in addition to the spin container.
2815 @type return_id: bool
2816 @return: The residue specific data container and, if full_info=True, the molecule name.
2817 @rtype: instance of the ResidueContainer class. If full_info=True, the type is the tuple (ResidueContainer, str).
2818 """
2819
2820
2821 if pipe == None:
2822 pipe = pipes.cdp_name()
2823
2824
2825 pipes.test(pipe)
2826
2827
2828 dp = pipes.get_pipe(pipe)
2829
2830
2831 if not exists_mol_res_spin_data(pipe=pipe):
2832 return
2833
2834
2835 select_obj = Selection(selection)
2836
2837
2838 for mol in dp.mol:
2839
2840 for res in mol.res:
2841
2842 if (mol, res) not in select_obj:
2843 continue
2844
2845
2846 if return_id:
2847 res_id = generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num, res_name=res.name)
2848
2849
2850 if full_info and return_id:
2851 yield res, mol.name, res_id
2852 elif full_info:
2853 yield res, mol.name
2854 elif return_id:
2855 yield res, res_id
2856 else:
2857 yield res
2858
2859
2861 """Function for returning the molecule data container of the given selection.
2862
2863 @param selection: The molecule selection identifier.
2864 @type selection: str
2865 @param pipe: The data pipe containing the molecule. Defaults to the current data pipe.
2866 @type pipe: str
2867 @return: The molecule specific data container.
2868 @rtype: instance of the MoleculeContainer class.
2869 """
2870
2871
2872 if pipe == None:
2873 pipe = pipes.cdp_name()
2874
2875
2876 pipes.test(pipe)
2877
2878
2879 dp = pipes.get_pipe(pipe)
2880
2881
2882 select_obj = Selection(selection)
2883
2884
2885 mol_num = 0
2886 mol_container = None
2887 for mol in dp.mol:
2888
2889 if mol not in select_obj:
2890 continue
2891
2892
2893 if selection == None and mol.name != None:
2894 continue
2895
2896
2897 mol_container = mol
2898
2899
2900 mol_num = mol_num + 1
2901
2902
2903 if mol_num > 1:
2904 raise RelaxMultiMolIDError(selection)
2905
2906
2907 return mol_container
2908
2909
2911 """Return the molecule container matching the given name.
2912
2913 @keyword pipe_cont: The data pipe object.
2914 @type pipe_cont: PipeContainer instance
2915 @keyword pipe_name: The data pipe name.
2916 @type pipe_name: str
2917 @keyword mol_name: The molecule name. If not supplied and only a single molecule container exists, then that container will be returned.
2918 @type mol_name: str
2919 @return: The molecule container object.
2920 @rtype: MoleculeContainer instance
2921 """
2922
2923
2924 if pipe_cont == None:
2925 pipe_cont = pipes.get_pipe(pipe)
2926
2927
2928 if mol_name == None:
2929
2930 if len(pipe_cont.mol) > 1:
2931 raise RelaxError("Cannot return the molecule with no name as more than one molecule exists.")
2932
2933
2934 return pipe_cont.mol[0]
2935
2936
2937 for mol in pipe_cont.mol:
2938
2939 if mol.name == mol_name:
2940 return mol
2941
2942
2944 """Function for returning the residue data container of the given selection.
2945
2946 @param selection: The residue selection identifier.
2947 @type selection: str
2948 @param pipe: The data pipe containing the residue. Defaults to the current data pipe.
2949 @type pipe: str
2950 @return: The residue specific data container, and the molecule and residue indices if asked.
2951 @rtype: instance of the ResidueContainer class.
2952 """
2953
2954
2955 if pipe == None:
2956 pipe = pipes.cdp_name()
2957
2958
2959 pipes.test(pipe)
2960
2961
2962 dp = pipes.get_pipe(pipe)
2963
2964
2965 select_obj = Selection(selection)
2966
2967
2968 res = None
2969 res_num = 0
2970 res_container = None
2971 for i in range(len(dp.mol)):
2972
2973 if dp.mol[i] not in select_obj:
2974 continue
2975
2976
2977 mol_index = i
2978
2979
2980 for j in range(len(dp.mol[i].res)):
2981
2982 if dp.mol[i].res[j] not in select_obj:
2983 continue
2984
2985
2986 res_container = dp.mol[i].res[j]
2987 res_index = j
2988
2989
2990 res_num = res_num + 1
2991
2992
2993 if res_num > 1:
2994 raise RelaxMultiResIDError(selection)
2995
2996
2997 if indices:
2998 return res_container, mol_index, res_index
2999 else:
3000 return res_container
3001
3002
3004 """Return the residue container matching the given name.
3005
3006 @keyword mol: The molecule container.
3007 @type mol: MoleculeContainer instance
3008 @keyword res_name: The residue name. If not supplied and only a single residue container exists, then that container will be returned.
3009 @type res_name: str
3010 @keyword res_num: The residue number. If not supplied and only a single residue container exists, then that container will be returned.
3011 @type res_num: str
3012 @return: The residue container object.
3013 @rtype: ResidueContainer instance
3014 """
3015
3016
3017 if res_name == None and res_num == None:
3018
3019 if len(mol.res) > 1:
3020 raise RelaxError("Cannot return the residue with no name or number as more than one residue exists.")
3021
3022
3023 return mol.res[0]
3024
3025
3026 for res in mol.res:
3027
3028 if res_name != None and res_num != None:
3029 if res.name == res_name and res.num == res_num:
3030 return res
3031 elif res_name != None:
3032 if res.name == res_name:
3033 return res
3034 elif res_num != None:
3035 if res.num == res_num:
3036 return res
3037
3038
3039 -def return_spin(spin_id=None, pipe=None, full_info=False, multi=False):
3040 """Return the spin data container corresponding to the given spin ID string.
3041
3042 @keyword spin_id: The unique spin ID string.
3043 @type spin_id: str
3044 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
3045 @type pipe: str
3046 @keyword full_info: A flag specifying if the amount of information to be returned. If false, only the data container is returned. If true, the molecule name, residue number, and residue name is additionally returned.
3047 @type full_info: bool
3048 @keyword multi: A flag which if True will allow multiple spins to be returned.
3049 @type multi: bool
3050 @return: The spin system specific data container and, if full_info=True, the molecule name, residue number, and residue name.
3051 @rtype: SpinContainer instance of list of instances or tuple of (str, int, str, SpinContainer instance or list of instances)
3052 """
3053
3054
3055 if pipe == None:
3056 pipe = pipes.cdp_name()
3057
3058
3059 dp = pipes.get_pipe(pipe)
3060
3061
3062 if spin_id not in dp.mol._spin_id_lookup:
3063 return None
3064
3065
3066 else:
3067 mol_index, res_index, spin_index = dp.mol._spin_id_lookup[spin_id]
3068
3069
3070 if full_info and multi:
3071 return [dp.mol[mol_index].name], [dp.mol[mol_index].res[res_index].num], [dp.mol[mol_index].res[res_index].name], [dp.mol[mol_index].res[res_index].spin[spin_index]]
3072 elif full_info:
3073 return dp.mol[mol_index].name, dp.mol[mol_index].res[res_index].num, dp.mol[mol_index].res[res_index].name, dp.mol[mol_index].res[res_index].spin[spin_index]
3074 elif multi:
3075 return [dp.mol[mol_index].res[res_index].spin[spin_index]]
3076 else:
3077 return dp.mol[mol_index].res[res_index].spin[spin_index]
3078
3079
3081 """Return the spin container matching the given name.
3082
3083 @keyword res: The residue container.
3084 @type res: ResidueContainer instance
3085 @keyword spin_name: The spin name. If not supplied and only a single spin container exists, then that container will be returned.
3086 @type spin_name: str
3087 @keyword spin_num: The spin number. If not supplied and only a single spin container exists, then that container will be returned.
3088 @type spin_num: str
3089 @return: The spin container object.
3090 @rtype: SpinContainer instance
3091 """
3092
3093
3094 if spin_name == None and spin_num == None:
3095
3096 if len(res.spin) > 1:
3097 raise RelaxError("Cannot return the spin with no name or number as more than one spin exists.")
3098
3099
3100 return res.spin[0]
3101
3102
3103 for spin in res.spin:
3104
3105 if spin_name != None and spin_num != None:
3106 if spin.name == spin_name and spin.num == spin_num:
3107 return spin
3108 elif spin_name != None:
3109 if spin.name == spin_name:
3110 return spin
3111 elif spin_num != None:
3112 if spin.num == spin_num:
3113 return spin
3114
3115
3117 """Function for returning the spin data container of the given selection.
3118
3119 If more than one selection is given, then the boolean AND operation will be used to pull out the spin.
3120
3121
3122 @keyword selection: The spin selection identifier.
3123 @type selection: str
3124 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
3125 @type pipe: str
3126 @keyword full_info: A flag specifying if the amount of information to be returned. If false, only the data container is returned. If true, the molecule name, residue number, and residue name is additionally returned.
3127 @type full_info: bool
3128 @keyword multi: A flag which if True will allow multiple spins to be returned.
3129 @type multi: bool
3130 @return: The spin system specific data container and, if full_info=True, the molecule name, residue number, and residue name.
3131 @rtype: SpinContainer instance of list of instances or tuple of (str, int, str, SpinContainer instance or list of instances)
3132 """
3133
3134
3135 if is_unicode(selection):
3136 selection = str(selection)
3137
3138
3139 if pipe == None:
3140 pipe = pipes.cdp_name()
3141
3142
3143 dp = pipes.get_pipe(pipe)
3144
3145
3146 select_obj = Selection(selection)
3147
3148
3149 spin_num = 0
3150 spins = []
3151 mol_names = []
3152 res_nums = []
3153 res_names = []
3154 spin_ids = []
3155 for mol in dp.mol:
3156
3157 if mol not in select_obj:
3158 continue
3159
3160
3161 for res in mol.res:
3162
3163 if res not in select_obj:
3164 continue
3165
3166
3167 for spin in res.spin:
3168
3169 if spin not in select_obj:
3170 continue
3171
3172
3173 mol_names.append(mol.name)
3174 res_nums.append(res.num)
3175 res_names.append(res.name)
3176 spins.append(spin)
3177
3178
3179 spin_num = spin_num + 1
3180
3181
3182 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num, res_name=res.name, spin_num=spin.num, spin_name=spin.name))
3183
3184
3185 if not multi and spin_num > 1:
3186 raise RelaxMultiSpinIDError(selection, spin_ids)
3187
3188
3189 if full_info and multi:
3190 return mol_names, res_nums, res_names, spins
3191 elif full_info:
3192 return mol_names[0], res_nums[0], res_names[0], spins[0]
3193 elif multi:
3194 return spins
3195 elif len(spins):
3196 return spins[0]
3197 else:
3198 return None
3199
3200
3202 """Function for returning the spin data container corresponding to the global index.
3203
3204 @param global_index: The global spin index, spanning the molecule and residue containers.
3205 @type global_index: int
3206 @param pipe: The data pipe containing the spin. Defaults to the current data pipe.
3207 @type pipe: str
3208 @keyword return_spin_id: A flag which if True will cause both the spin container and spin identification string to be returned.
3209 @type return_spin_id: bool
3210 @return: The spin specific data container (additionally the spin identification string if return_spin_id is set).
3211 @rtype: instance of the SpinContainer class (or tuple of SpinContainer and str)
3212 """
3213
3214
3215 if pipe == None:
3216 pipe = pipes.cdp_name()
3217
3218
3219 pipes.test(pipe)
3220
3221
3222 spin_num = 0
3223 for spin, mol_name, res_num, res_name in spin_loop(full_info=True, pipe=pipe):
3224
3225 if spin_num == global_index:
3226
3227 if return_spin_id:
3228
3229 spin_id = generate_spin_id(pipe_name=pipe, mol_name=mol_name, res_num=res_num, res_name=res_name, spin_num=spin.num, spin_name=spin.name)
3230
3231
3232 return spin, spin_id
3233
3234
3235 else:
3236 return spin
3237
3238
3239 spin_num = spin_num + 1
3240
3241
3243 """Return the molecule, residue and spin indices corresponding to the given spin ID string.
3244
3245 @keyword spin_id: The unique spin ID string.
3246 @type spin_id: str
3247 @param pipe: The data pipe containing the spin. Defaults to the current data pipe.
3248 @type pipe: str
3249 @return: The molecule, residue and spin indices.
3250 @rtype: list of int
3251 """
3252
3253
3254 if pipe == None:
3255 pipe = pipes.cdp_name()
3256
3257
3258 dp = pipes.get_pipe(pipe)
3259
3260
3261 if spin_id not in dp.mol._spin_id_lookup:
3262
3263 select_obj = Selection(spin_id)
3264
3265
3266 for i in range(len(dp.mol)):
3267
3268 if dp.mol[i] not in select_obj:
3269 continue
3270
3271
3272 mol_index = i
3273
3274
3275 for j in range(len(dp.mol[i].res)):
3276
3277 if dp.mol[i].res[j] not in select_obj:
3278 continue
3279
3280
3281 res_index = j
3282
3283
3284 for k in range(len(dp.mol[i].res[j].spin)):
3285
3286 if dp.mol[i].res[j].spin[k] not in select_obj:
3287 continue
3288
3289
3290 spin_index = k
3291
3292
3293 break
3294
3295
3296 else:
3297 mol_index, res_index, spin_index = dp.mol._spin_id_lookup[spin_id]
3298
3299
3300 return mol_index, res_index, spin_index
3301
3302
3304 """Return the single molecule name corresponding to the molecule token.
3305
3306 @param molecule_token: The molecule identification string.
3307 @type molecule_token: str
3308 @return: The molecule name.
3309 @rtype: str
3310 """
3311
3312
3313 molecule_info = parse_token(molecule_token)
3314
3315
3316 mol_name = None
3317 for info in molecule_info:
3318
3319 if mol_name == None:
3320 mol_name = info
3321 else:
3322 raise RelaxError("The molecule identifier " + repr(molecule_token) + " does not correspond to a single molecule.")
3323
3324
3325 if mol_name != None and not isinstance(mol_name, str):
3326 mol_name = str(mol_name)
3327
3328
3329 return mol_name
3330
3331
3333 """Return the single residue number and name corresponding to the residue token.
3334
3335 @param residue_token: The residue identification string.
3336 @type residue_token: str
3337 @return: A tuple containing the residue number and the residue name.
3338 @rtype: (int, str)
3339 """
3340
3341
3342 residue_info = parse_token(residue_token)
3343
3344
3345 res_num = None
3346 res_name = None
3347 for info in residue_info:
3348
3349 if isinstance(info, str):
3350 if res_name == None:
3351 res_name = info
3352 else:
3353 raise RelaxError("The residue identifier " + repr(residue_token) + " does not correspond to a single residue.")
3354
3355
3356 if isinstance(info, int):
3357 if res_num == None:
3358 res_num = info
3359 else:
3360 raise RelaxError("The residue identifier " + repr(residue_token) + " does not correspond to a single residue.")
3361
3362
3363 return res_num, res_name
3364
3365
3367 """Return the single spin number and name corresponding to the spin token.
3368
3369 @param spin_token: The spin identification string.
3370 @type spin_token: str
3371 @return: A tuple containing the spin number and the spin name.
3372 @rtype: (int, str)
3373 """
3374
3375
3376 spin_info = parse_token(spin_token)
3377
3378
3379 spin_num = None
3380 spin_name = None
3381 for info in spin_info:
3382
3383 if isinstance(info, str):
3384 if spin_name == None:
3385 spin_name = info
3386 else:
3387 raise RelaxError("The spin identifier " + repr(spin_token) + " does not correspond to a single spin.")
3388
3389
3390 if isinstance(info, int):
3391 if spin_num == None:
3392 spin_num = info
3393 else:
3394 raise RelaxError("The spin identifier " + repr(spin_token) + " does not correspond to a single spin.")
3395
3396
3397 return spin_num, spin_name
3398
3399
3401 """Test if the sequence data in both pipes are the same.
3402
3403 @param pipe1: The first data pipe.
3404 @type pipe1: str
3405 @param pipe2: The second data pipe.
3406 @type pipe2: str
3407 @return: True if the sequence data matches, False otherwise.
3408 @rtype: bool
3409 """
3410
3411
3412 pipes.test(pipe1)
3413 pipes.test(pipe2)
3414
3415
3416 pipe1 = pipes.get_pipe(pipe1)
3417 pipe2 = pipes.get_pipe(pipe2)
3418
3419
3420 if len(pipe1.mol) != len(pipe2.mol):
3421 return False
3422
3423
3424 for i in range(len(pipe1.mol)):
3425
3426 if len(pipe1.mol[i].res) != len(pipe2.mol[i].res):
3427 return False
3428
3429
3430 for j in range(len(pipe1.mol[i].res)):
3431
3432 if len(pipe1.mol[i].res[j].spin) != len(pipe2.mol[i].res[j].spin):
3433 return False
3434
3435
3436 for k in range(len(pipe1.mol[i].res[j].spin)):
3437
3438 if pipe1.mol[i].res[j].spin[k].num != pipe2.mol[i].res[j].spin[k].num:
3439 return False
3440
3441
3442 if pipe1.mol[i].res[j].spin[k].name != pipe2.mol[i].res[j].spin[k].name:
3443 return False
3444
3445
3446 return True
3447
3448
3450 """Set the element type of the spins.
3451
3452 @keyword spin_id: The spin identification string.
3453 @type spin_id: str
3454 @keyword element: The IUPAC element name.
3455 @type element: str
3456 @param pipe: The data pipe to operate on. Defaults to the current data pipe.
3457 @type pipe: str
3458 @keyword force: A flag which if True will cause the element to be changed.
3459 @type force: bool
3460 """
3461
3462
3463 valid_names = ['H',
3464 'C',
3465 'N',
3466 'O',
3467 'F',
3468 'Na',
3469 'P',
3470 'Cd'
3471 ]
3472
3473
3474 if element not in valid_names:
3475 raise RelaxError("The element name '%s' is not valid and should be one of the IUPAC names %s." % (element, valid_names))
3476
3477
3478 if pipe == None:
3479 pipe = pipes.cdp_name()
3480
3481
3482 pipes.test(pipe)
3483
3484
3485 for spin, id in spin_loop(spin_id, pipe=pipe, return_id=True):
3486 if hasattr(spin, 'element') and spin.element and not force:
3487 warn(RelaxWarning("The element type of the spin '%s' is already set. Set the force flag to True to rename." % id))
3488 else:
3489 spin.element = element
3490
3491
3493 """Set the nuclear isotope type of the spins.
3494
3495 @keyword spin_id: The spin identification string.
3496 @type spin_id: str
3497 @keyword isotope: The nuclear isotope type.
3498 @type isotope: str
3499 @param pipe: The data pipe to operate on. Defaults to the current data pipe.
3500 @type pipe: str
3501 @keyword force: A flag which if True will cause the isotope type to be changed. If None, then the warning messages will not mention the need to change this flag to rename.
3502 @type force: bool or None
3503 """
3504
3505
3506 supported_types = [
3507 '1H',
3508 '2H',
3509 '13C',
3510 '14N',
3511 '15N',
3512 '17O',
3513 '19F',
3514 '23Na',
3515 '31P',
3516 '113Cd'
3517 ]
3518
3519
3520 if isotope not in supported_types:
3521 raise RelaxError("The nuclear isotope type '%s' is currently not supported." % isotope)
3522
3523
3524 if pipe == None:
3525 pipe = pipes.cdp_name()
3526
3527
3528 pipes.test(pipe)
3529
3530
3531 for spin, id in spin_loop(spin_id, pipe=pipe, return_id=True):
3532 if hasattr(spin, 'isotope') and spin.isotope and force != True:
3533 if force == False:
3534 warn(RelaxWarning("The nuclear isotope type of the spin '%s' is already set. Change the force flag to True to reset." % id))
3535 else:
3536 warn(RelaxWarning("The nuclear isotope type of the spin '%s' is already set." % id))
3537 else:
3538 spin.isotope = isotope
3539
3540
3542 """Convert the single spin ID string into a list of the mol, res, and spin names and numbers.
3543
3544 @param id: The spin ID string.
3545 @type id: str
3546 @return: The molecule name, the residue number and name, and the spin number and name.
3547 @rtype: str, int, str, int, str
3548 """
3549
3550
3551 mol_token, res_token, spin_token = tokenise(id)
3552 mol_info = parse_token(mol_token)
3553 res_info = parse_token(res_token)
3554 spin_info = parse_token(spin_token)
3555
3556
3557 mol_name = None
3558 if len(mol_info) > 1:
3559 raise RelaxError("The single spin ID '%s' should only belong to one molecule, not %s." % (id, mol_info))
3560 if len(mol_info) == 1:
3561 mol_name = mol_info[0]
3562
3563
3564 res_names = []
3565 res_nums = []
3566 for i in range(len(res_info)):
3567 try:
3568 res_nums.append(int(res_info[i]))
3569 except ValueError:
3570 res_names.append(res_info[i])
3571
3572
3573 res_num = None
3574 if len(res_nums) > 1:
3575 raise RelaxError("The single spin ID '%s' should only belong to one residue number, not %s." % (id, res_info))
3576 elif len(res_nums) == 1:
3577 res_num = res_nums[0]
3578
3579
3580 res_name = None
3581 if len(res_names) > 1:
3582 raise RelaxError("The single spin ID '%s' should only belong to one residue name, not %s." % (id, res_info))
3583 elif len(res_names) == 1:
3584 res_name = res_names[0]
3585
3586
3587 spin_names = []
3588 spin_nums = []
3589 for i in range(len(spin_info)):
3590 try:
3591 spin_nums.append(int(spin_info[i]))
3592 except ValueError:
3593 spin_names.append(spin_info[i])
3594
3595
3596 spin_num = None
3597 if len(spin_nums) > 1:
3598 raise RelaxError("The single spin ID '%s' should only belong to one spin number, not %s." % (id, spin_info))
3599 elif len(spin_nums) == 1:
3600 spin_num = spin_nums[0]
3601
3602
3603 spin_name = None
3604 if len(spin_names) > 1:
3605 raise RelaxError("The single spin ID '%s' should only belong to one spin name, not %s." % (id, spin_info))
3606 elif len(spin_names) == 1:
3607 spin_name = spin_names[0]
3608
3609
3610 return mol_name, res_num, res_name, spin_num, spin_name
3611
3612
3613 -def spin_id_variants(dp=None, mol_index=None, res_index=None, spin_index=None):
3614 """Generate a list of spin ID variants for the given set of molecule, residue and spin indices.
3615
3616 @keyword dp: The data pipe to work on.
3617 @type dp: PipeContainer instance
3618 @keyword mol_index: The molecule index.
3619 @type mol_index: int
3620 @keyword res_index: The residue index.
3621 @type res_index: int
3622 @keyword spin_index: The spin index.
3623 @type spin_index: int
3624 @return: The list of all spin IDs matching the spin.
3625 @rtype: list of str
3626 """
3627
3628
3629 spin_ids = []
3630 mol = dp.mol[mol_index]
3631 res = dp.mol[mol_index].res[res_index]
3632 spin = dp.mol[mol_index].res[res_index].spin[spin_index]
3633 mol_count = len(dp.mol)
3634 res_count = len(mol.res)
3635 spin_count = len(res.spin)
3636
3637
3638 unique_top_level_res_name = True
3639 unique_top_level_res_num = True
3640 unique_top_level_spin_name = True
3641 unique_top_level_spin_num = True
3642 if res.name != None and dp.mol._res_name_count[res.name] > 1:
3643 unique_top_level_res_name = False
3644 if res.num != None and dp.mol._res_num_count[res.num] > 1:
3645 unique_top_level_res_num = False
3646 if spin.name != None and dp.mol._spin_name_count[spin.name] > 1:
3647 unique_top_level_spin_name = False
3648 if spin.num != None and dp.mol._spin_num_count[spin.num] > 1:
3649 unique_top_level_spin_num = False
3650
3651
3652 unique_mol_level_res_name = True
3653 unique_mol_level_res_num = True
3654 unique_mol_level_spin_name = True
3655 unique_mol_level_spin_num = True
3656 if res.name != None and mol._res_name_count[res.name] > 1:
3657 unique_mol_level_res_name = False
3658 if res.num != None and mol._res_num_count[res.num] > 1:
3659 unique_mol_level_res_num = False
3660 if spin.name != None and mol._spin_name_count[spin.name] > 1:
3661 unique_mol_level_spin_name = False
3662 if spin.num != None and mol._spin_num_count[spin.num] > 1:
3663 unique_mol_level_spin_num = False
3664
3665
3666 unique_res_level_spin_name = True
3667 unique_res_level_spin_num = True
3668 if spin.name != None and res._spin_name_count[spin.name] > 1:
3669 unique_res_level_spin_name = False
3670 if spin.num != None and res._spin_num_count[spin.num] > 1:
3671 unique_res_level_spin_num = False
3672
3673
3674 if mol.name != None:
3675
3676 if res.name != None:
3677
3678 if spin.name != None and unique_mol_level_res_name and unique_res_level_spin_name:
3679 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name, spin_name=spin.name))
3680
3681
3682 if spin.num != None and unique_mol_level_res_name and unique_res_level_spin_num:
3683 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name, spin_num=spin.num))
3684
3685
3686 if spin_count == 1 and unique_mol_level_res_name:
3687 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name))
3688
3689
3690 if res.num != None:
3691
3692 if spin.name != None and unique_mol_level_res_num and unique_res_level_spin_name:
3693 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num, spin_name=spin.name))
3694
3695
3696 if spin.num != None and unique_mol_level_res_num and unique_res_level_spin_num:
3697 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num, spin_num=spin.num))
3698
3699
3700 if spin_count == 1 and unique_mol_level_res_num:
3701 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num))
3702
3703
3704 if spin.name != None and unique_mol_level_spin_name:
3705 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, spin_name=spin.name))
3706
3707
3708 if spin.num != None and unique_mol_level_spin_num:
3709 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, spin_num=spin.num))
3710
3711
3712 if spin_count == 1 and res_count == 1:
3713 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name))
3714
3715
3716 if res.name != None:
3717
3718 if spin.name != None and unique_top_level_res_name and unique_res_level_spin_name:
3719 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name, spin_name=spin.name))
3720
3721
3722 if spin.num != None and unique_top_level_res_name and unique_res_level_spin_num:
3723 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name, spin_num=spin.num))
3724
3725
3726 if spin_count == 1 and unique_top_level_res_name:
3727 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name))
3728
3729
3730 if res.num != None:
3731
3732 if spin.name != None and unique_top_level_res_num and unique_res_level_spin_name:
3733 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num, spin_name=spin.name))
3734
3735
3736 if spin.num != None and unique_top_level_res_num and unique_res_level_spin_num:
3737 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num, spin_num=spin.num))
3738
3739
3740 if spin_count == 1 and unique_top_level_res_num:
3741 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num))
3742
3743
3744 if spin.name != None and unique_top_level_spin_name:
3745 spin_ids.append(generate_spin_id(pipe_cont=dp, spin_name=spin.name))
3746
3747
3748 if spin.num != None and unique_top_level_spin_num:
3749 spin_ids.append(generate_spin_id(pipe_cont=dp, spin_num=spin.num))
3750
3751
3752 return spin_ids
3753
3754
3756 """Generate a list of spin ID variants to eliminate for the given set of molecule, residue and spin indices.
3757
3758 @keyword dp: The data pipe to work on.
3759 @type dp: PipeContainer instance
3760 @keyword mol_index: The molecule index.
3761 @type mol_index: int
3762 @keyword res_index: The residue index.
3763 @type res_index: int
3764 @keyword spin_index: The spin index.
3765 @type spin_index: int
3766 @return: The list of all spin IDs matching the spin.
3767 @rtype: list of str
3768 """
3769
3770
3771 spin_ids = []
3772 mol = dp.mol[mol_index]
3773 res = dp.mol[mol_index].res[res_index]
3774 spin = dp.mol[mol_index].res[res_index].spin[spin_index]
3775 mol_count = len(dp.mol)
3776 res_count = len(mol.res)
3777 spin_count = len(res.spin)
3778
3779
3780 unique_top_level_res_name = True
3781 unique_top_level_res_num = True
3782 unique_top_level_spin_name = True
3783 unique_top_level_spin_num = True
3784 if res.name != None and dp.mol._res_name_count[res.name] > 1:
3785 unique_top_level_res_name = False
3786 if res.num != None and dp.mol._res_num_count[res.num] > 1:
3787 unique_top_level_res_num = False
3788 if spin.name != None and dp.mol._spin_name_count[spin.name] > 1:
3789 unique_top_level_spin_name = False
3790 if spin.num != None and dp.mol._spin_num_count[spin.num] > 1:
3791 unique_top_level_spin_num = False
3792
3793
3794 unique_mol_level_res_name = True
3795 unique_mol_level_res_num = True
3796 unique_mol_level_spin_name = True
3797 unique_mol_level_spin_num = True
3798 if res.name != None and mol._res_name_count[res.name] > 1:
3799 unique_mol_level_res_name = False
3800 if res.num != None and mol._res_num_count[res.num] > 1:
3801 unique_mol_level_res_num = False
3802 if spin.name != None and mol._spin_name_count[spin.name] > 1:
3803 unique_mol_level_spin_name = False
3804 if spin.num != None and mol._spin_num_count[spin.num] > 1:
3805 unique_mol_level_spin_num = False
3806
3807
3808 unique_res_level_spin_name = True
3809 unique_res_level_spin_num = True
3810 if spin.name != None and res._spin_name_count[spin.name] > 1:
3811 unique_res_level_spin_name = False
3812 if spin.num != None and res._spin_num_count[spin.num] > 1:
3813 unique_res_level_spin_num = False
3814
3815
3816 if mol.name != None:
3817
3818 if res.name != None:
3819
3820 if spin.name != None and (not unique_mol_level_res_name or not unique_res_level_spin_name):
3821 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name, spin_name=spin.name))
3822
3823
3824 if spin.num != None and (not unique_mol_level_res_name or not unique_res_level_spin_num):
3825 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name, spin_num=spin.num))
3826
3827
3828 if not unique_mol_level_res_name or spin_count > 1:
3829 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name))
3830
3831
3832 if res.num != None:
3833
3834 if spin.name != None and (not unique_mol_level_res_num or not unique_res_level_spin_name):
3835 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num, spin_name=spin.name))
3836
3837
3838 if spin.num != None and (not unique_mol_level_res_num or not unique_res_level_spin_num):
3839 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num, spin_num=spin.num))
3840
3841
3842 if not unique_mol_level_res_num or spin_count > 1:
3843 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num))
3844
3845
3846 if spin.name != None and not unique_mol_level_spin_name:
3847 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, spin_name=spin.name))
3848
3849
3850 if spin.num != None and not unique_mol_level_spin_num:
3851 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, spin_num=spin.num))
3852
3853
3854 if res_count > 1 or spin_count > 1:
3855 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name))
3856
3857
3858 if res.name != None:
3859
3860 if spin.name != None and (not unique_top_level_res_name and not unique_top_level_spin_name):
3861 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name, spin_name=spin.name))
3862
3863
3864 if spin.num != None and (not unique_top_level_res_name and not unique_top_level_spin_num):
3865 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name, spin_num=spin.num))
3866
3867
3868 if not unique_top_level_res_name or spin_count > 1:
3869 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name))
3870
3871
3872 if res.num != None:
3873
3874 if spin.name != None and (not unique_top_level_res_num and not unique_top_level_spin_name):
3875 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num, spin_name=spin.name))
3876
3877
3878 if spin.num != None and (not unique_top_level_res_num and not unique_top_level_spin_num):
3879 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num, spin_num=spin.num))
3880
3881
3882 if not unique_top_level_res_num or spin_count > 1:
3883 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num))
3884
3885
3886 if spin.name != None and not unique_top_level_spin_name:
3887 spin_ids.append(generate_spin_id(pipe_cont=dp, spin_name=spin.name))
3888
3889
3890 if spin.num != None and not unique_top_level_spin_num:
3891 spin_ids.append(generate_spin_id(pipe_cont=dp, spin_num=spin.num))
3892
3893
3894 return spin_ids
3895
3896
3898 """Generate a list of spin ID variants to eliminate for the given set of molecule, residue and spin indices.
3899
3900 @keyword dp: The data pipe to work on.
3901 @type dp: PipeContainer instance
3902 @keyword mol_index: The molecule index.
3903 @type mol_index: int
3904 @keyword res_index: The residue index.
3905 @type res_index: int
3906 @keyword spin_index: The spin index.
3907 @type spin_index: int
3908 @return: The list of all spin IDs matching the spin.
3909 @rtype: list of str
3910 """
3911
3912
3913 spin_ids = []
3914 mol = dp.mol[mol_index]
3915 res = dp.mol[mol_index].res[res_index]
3916 spin = dp.mol[mol_index].res[res_index].spin[spin_index]
3917 mol_count = len(dp.mol)
3918 res_count = len(mol.res)
3919 spin_count = len(res.spin)
3920
3921
3922 if mol.name != None:
3923
3924 if res.name != None:
3925
3926 if spin.name != None:
3927 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name, spin_name=spin.name))
3928
3929
3930 if spin.num != None:
3931 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name, spin_num=spin.num))
3932
3933
3934 if spin_count == 1:
3935 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_name=res.name))
3936
3937
3938 if res.num != None:
3939
3940 if spin.name != None:
3941 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num, spin_name=spin.name))
3942
3943
3944 if spin.num != None:
3945 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num, spin_num=spin.num))
3946
3947
3948 if spin_count == 1:
3949 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, res_num=res.num))
3950
3951
3952 if spin.name != None and res_count == 1:
3953 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, spin_name=spin.name))
3954
3955
3956 if spin.num != None and res_count == 1:
3957 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name, spin_num=spin.num))
3958
3959
3960 if res_count == 1 and spin_count == 1:
3961 spin_ids.append(generate_spin_id(pipe_cont=dp, mol_name=mol.name))
3962
3963
3964 if res.name != None:
3965
3966 if spin.name != None and mol_count == 1:
3967 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name, spin_name=spin.name))
3968
3969
3970 if spin.num != None and mol_count == 1:
3971 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name, spin_num=spin.num))
3972
3973
3974 if mol_count == 1 and spin_count == 1:
3975 spin_ids.append(generate_spin_id(pipe_cont=dp, res_name=res.name))
3976
3977
3978 if res.num != None:
3979
3980 if spin.name != None and mol_count == 1:
3981 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num, spin_name=spin.name))
3982
3983
3984 if spin.num != None and mol_count == 1:
3985 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num, spin_num=spin.num))
3986
3987
3988 if mol_count == 1 and spin_count == 1:
3989 spin_ids.append(generate_spin_id(pipe_cont=dp, res_num=res.num))
3990
3991
3992 if spin.name != None and mol_count == 1 and res_count == 1:
3993 spin_ids.append(generate_spin_id(pipe_cont=dp, spin_name=spin.name))
3994
3995
3996 if spin.num != None and mol_count == 1 and res_count == 1:
3997 spin_ids.append(generate_spin_id(pipe_cont=dp, spin_num=spin.num))
3998
3999
4000 return spin_ids
4001
4002
4003 -def spin_in_list(spin_list, mol_name_col=None, res_num_col=None, res_name_col=None, spin_num_col=None, spin_name_col=None, mol_name=None, res_num=None, res_name=None, spin_num=None, spin_name=None):
4004 """Function for determining if the spin is located within the list of spins.
4005
4006 @param spin_list: The list of spins. The first dimension corresponds to different spins, the second corresponds to the spin information columns.
4007 @type spin_list: list of lists of str
4008 @keyword mol_name_col: The column containing the molecule name information.
4009 @type mol_name_col: int or None
4010 @keyword res_num_col: The column containing the residue number information.
4011 @type res_num_col: int or None
4012 @keyword res_name_col: The column containing the residue name information.
4013 @type res_name_col: int or None
4014 @keyword spin_num_col: The column containing the spin number information.
4015 @type spin_num_col: int or None
4016 @keyword spin_name_col: The column containing the spin name information.
4017 @type spin_name_col: int or None
4018 @keyword mol_name: The molecule name.
4019 @type mol_name: str or None
4020 @keyword res_num: The residue number.
4021 @type res_num: int or None
4022 @keyword res_name: The residue name.
4023 @type res_name: str or None
4024 @keyword spin_num: The spin number.
4025 @type spin_num: int or None
4026 @keyword spin_name: The spin name.
4027 @type spin_name: str or None
4028 @return: The answer of whether the spin is within the list.
4029 @rtype: bool
4030 """
4031
4032
4033 select_obj = Selection(generate_spin_id(mol_name=mol_name, res_num=res_num, res_name=res_name, spin_num=spin_num, spin_name=spin_name))
4034
4035
4036 for spin in spin_list:
4037
4038 spin_id = generate_spin_id_data_array(data=file_data[i], mol_name_col=mol_name_col, res_num_col=res_num_col, res_name_col=res_name_col, spin_num_col=spin_num_col, spin_name_col=spin_name_col)
4039
4040
4041 if spin_id in select_obj:
4042 return True
4043
4044
4045 return False
4046
4047
4049 """Generator function for looping over all selected spins, returning the mol-res-spin indices.
4050
4051 @param selection: The spin system selection identifier.
4052 @type selection: str
4053 @param pipe: The data pipe containing the spin. Defaults to the current data pipe.
4054 @type pipe: str
4055 @return: The molecule, residue, and spin index.
4056 @rtype: tuple of 3 int
4057 """
4058
4059
4060 if pipe == None:
4061 pipe = pipes.cdp_name()
4062
4063
4064 pipes.test(pipe)
4065
4066
4067 dp = pipes.get_pipe(pipe)
4068
4069
4070 if not exists_mol_res_spin_data(pipe=pipe):
4071 return
4072
4073
4074 select_obj = Selection(selection)
4075
4076
4077 for mol_index in range(len(dp.mol)):
4078
4079 mol = dp.mol[mol_index]
4080
4081
4082 for res_index in range(len(dp.mol[mol_index].res)):
4083
4084 res = dp.mol[mol_index].res[res_index]
4085
4086
4087 for spin_index in range(len(dp.mol[mol_index].res[res_index].spin)):
4088
4089 spin = dp.mol[mol_index].res[res_index].spin[spin_index]
4090
4091
4092 if (mol, res, spin) not in select_obj:
4093 continue
4094
4095
4096 yield mol_index, res_index, spin_index
4097
4098
4099 -def spin_loop(selection=None, pipe=None, full_info=False, return_id=False):
4100 """Generator function for looping over all the spin systems of the given selection.
4101
4102 @keyword selection: The spin system selection identifier.
4103 @type selection: str
4104 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
4105 @type pipe: str
4106 @keyword full_info: A flag which if True will cause the the molecule name, residue number, and residue name to be returned in addition to the spin container.
4107 @type full_info: bool
4108 @keyword return_id: A flag which if True will cause the spin identification string of the current spin to be returned in addition to the spin container.
4109 @type return_id: bool
4110 @return: The spin system specific data container. If full_info is True, a tuple of the spin container, the molecule name, residue number, and residue name. If return_id is True, a tuple of the spin container and spin id. If both flags are True, then a tuple of the spin container, the molecule name, residue number, residue name, and spin id.
4111 @rtype: If full_info and return_id are False, SpinContainer instance. If full_info is True and return_id is false, a tuple of (SpinContainer instance, str, int, str). If full_info is False and return_id is True, a tuple of (SpinContainer instance, str). If full_info and return_id are False, a tuple of (SpinContainer instance, str, int, str, str)
4112 """
4113
4114
4115 if pipe == None:
4116 pipe = pipes.cdp_name()
4117
4118
4119 pipes.test(pipe)
4120
4121
4122 dp = pipes.get_pipe(pipe)
4123
4124
4125 if not exists_mol_res_spin_data(pipe=pipe):
4126 return
4127
4128
4129 select_obj = Selection(selection)
4130
4131
4132 for mol in dp.mol:
4133
4134 for res in mol.res:
4135
4136 for spin in res.spin:
4137
4138 if (mol, res, spin) not in select_obj:
4139 continue
4140
4141
4142 if return_id:
4143 spin_id = generate_spin_id_unique(pipe_cont=dp, mol=mol, res=res, spin=spin)
4144
4145
4146 if full_info and return_id:
4147 yield spin, mol.name, res.num, res.name, spin_id
4148 elif full_info:
4149 yield spin, mol.name, res.num, res.name
4150 elif return_id:
4151 yield spin, spin_id
4152 else:
4153 yield spin
4154
4155
4157 """Split the input selection string returning the mol_token, res_token, and spin_token strings.
4158
4159 The mol_token is identified as the text from the '#' to either the ':' or '@' characters or the end of the string.
4160
4161 The res_token is identified as the text from the ':' to either the '@' character or the end of the string.
4162
4163 The spin_token is identified as the text from the '@' to the end of the string.
4164
4165
4166 @param selection: The selection identifier.
4167 @type selection: str
4168 @return: The mol_token, res_token, and spin_token.
4169 @rtype: 3-tuple of str or None
4170 """
4171
4172
4173 if selection == None:
4174 return None, None, None
4175
4176
4177
4178 mol_info = ''
4179 res_info = ''
4180 spin_info = ''
4181 pos = 'mol'
4182 for i in range(len(selection)):
4183
4184 if selection[i] == '|':
4185 raise RelaxError("The boolean operator '|' is not supported for individual spin selections.")
4186
4187
4188 if selection[i] == ':':
4189 if pos == 'spin':
4190 raise RelaxError("Invalid selection string '%s'." % selection)
4191 pos = 'res'
4192
4193
4194 if selection[i] == '@':
4195 pos = 'spin'
4196
4197
4198 if pos == 'mol':
4199 mol_info = mol_info + selection[i]
4200 if pos == 'res':
4201 res_info = res_info + selection[i]
4202 if pos == 'spin':
4203 spin_info = spin_info + selection[i]
4204
4205
4206
4207
4208
4209
4210 if mol_info:
4211
4212 if '&' in mol_info:
4213 raise RelaxError("The boolean operator '&' is not supported for the molecule component of individual spin IDs.")
4214
4215
4216
4217
4218
4219
4220 if ':' in mol_info or '@' in mol_info or mol_info[0] != '#' or mol_info.count('#') != 1:
4221 raise RelaxError("Invalid molecule selection '%s'." % mol_info)
4222
4223
4224 mol_token = mol_info[1:]
4225
4226
4227 else:
4228 mol_token = None
4229
4230
4231
4232
4233
4234
4235 if res_info:
4236
4237 if res_info.count('&') > 1:
4238 raise RelaxError("Only one '&' boolean operator is supported for the residue component of individual spin IDs.")
4239
4240
4241 res_token = split('&', res_info)
4242
4243
4244 for i in range(len(res_token)):
4245
4246
4247
4248
4249
4250 if '#' in res_token[i] or '@' in res_token[i] or res_token[i][0] != ':' or res_token[i].count(':') != 1:
4251 raise RelaxError("Invalid residue selection '%s'." % res_info)
4252
4253
4254 res_token[i] = res_token[i][1:]
4255
4256
4257 if len(res_token) == 1:
4258 res_token = res_token[0]
4259
4260
4261 else:
4262 res_token = None
4263
4264
4265
4266
4267
4268
4269 if spin_info:
4270
4271 if spin_info.count('&') > 1:
4272 raise RelaxError("Only one '&' boolean operator is supported for the spin component of individual spin IDs.")
4273
4274
4275 spin_token = split('&', spin_info)
4276
4277
4278 for i in range(len(spin_token)):
4279
4280
4281
4282
4283
4284 if '#' in spin_token[i] or ':' in spin_token[i] or spin_token[i][0] != '@' or spin_token[i].count('@') != 1:
4285 raise RelaxError("Invalid spin selection '%s'." % spin_info)
4286
4287
4288 spin_token[i] = spin_token[i][1:]
4289
4290
4291 if len(spin_token) == 1:
4292 spin_token = spin_token[0]
4293
4294
4295 else:
4296 spin_token = None
4297
4298
4299
4300
4301
4302
4303 if mol_token == None and res_token == None and spin_token == None:
4304 raise RelaxError("The selection string '%s' is invalid." % selection)
4305
4306
4307 return mol_token, res_token, spin_token
4308
4309
4311 """Set the molecule type.
4312
4313 @param mol_id: The molecule identification string.
4314 @type mol_id: str
4315 @param type: The molecule type.
4316 @type type: str
4317 @keyword force: A flag which if True will cause the molecule type to be overwritten.
4318 @type force: bool
4319 """
4320
4321
4322 if type not in ALLOWED_MOL_TYPES:
4323 raise RelaxError("The molecule type '%s' must be one of %s." % (type, ALLOWED_MOL_TYPES))
4324
4325
4326 select_obj = Selection(mol_id)
4327 if select_obj.has_residues():
4328 raise RelaxResSelectDisallowError
4329 if select_obj.has_spins():
4330 raise RelaxSpinSelectDisallowError
4331
4332
4333 for mol in molecule_loop(mol_id):
4334 if hasattr(mol, 'type') and mol.type and not force:
4335 warn(RelaxWarning("The molecule '%s' already has its type set. Set the force flag to change." % mol_id))
4336 else:
4337 mol.type = type
4338