1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Module for the manipulation of the molecule-residue-spin data structures in the relax data store.
25
26 The functionality of this module is diverse:
27 - Documentation for the spin identification string.
28 - Functions for parsing or generating spin identification strings.
29 - The mol-res-spin selection object (derived from the Selection class).
30 - Generator functions for looping over molecules, residues, or spins.
31 - Functions for returning MoleculeContainer, ResidueContainer, and SpinContainer objects or
32 information about these.
33 - Functions for copying, creating, deleting, displaying, naming, and numbering
34 MoleculeContainer, ResidueContainer, and SpinContainer objects in the relax data store.
35 - Functions for counting spins or testing their existence.
36 """
37
38
39 from numpy import array, float64
40 from re import split
41 from string import count, replace, strip, upper
42 import sys
43 from textwrap import fill
44 from warnings import warn
45
46
47 from data.mol_res_spin import MoleculeContainer, ResidueContainer, SpinContainer
48 from generic_fns import pipes
49 from generic_fns import relax_re
50 from relax_errors import RelaxError, RelaxNoSpinError, RelaxMultiMolIDError, RelaxMultiResIDError, RelaxMultiSpinIDError, RelaxResSelectDisallowError, RelaxSpinSelectDisallowError
51 from relax_warnings import RelaxWarning
52 from status import Status; status = Status()
53
54
55 ALLOWED_MOL_TYPES = ['protein',
56 'DNA',
57 'RNA',
58 'organic molecule',
59 'inorganic molecule'
60 ]
61 """The list of allowable molecule types."""
62
63 id_string_doc = ["Spin ID string documentation", """
64 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 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.
65
66 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.
67
68 Regular expression can be used to select spins. For example the string '@H*' will select the protons 'H', 'H2', 'H98'.
69 """]
70
71
72
74 """An object containing mol-res-spin selections.
75
76 A Selection object represents either a set of selected molecules, residues and spins, or the
77 union or intersection of two other Selection objects.
78 """
79
81 """Initialise a Selection object.
82
83 @param select_string: A mol-res-spin selection string.
84 @type select_string: string
85 """
86
87
88 if isinstance(select_string, unicode):
89 select_string = str(select_string)
90
91 self._union = None
92 self._intersect = None
93
94 self.molecules = []
95 self.residues = []
96 self.spins = []
97
98 if not select_string:
99 return
100
101
102 and_index = select_string.rfind('&')
103 or_index = select_string.rfind('|')
104
105 if and_index > or_index:
106 sel0 = Selection(select_string[:and_index].strip())
107 sel1 = Selection(select_string[and_index+1:].strip())
108 self.intersection(sel0, sel1)
109
110 elif or_index > and_index:
111 sel0 = Selection(select_string[:or_index].strip())
112 sel1 = Selection(select_string[or_index+1:].strip())
113 self.union(sel0, sel1)
114
115
116 else:
117 mol_token, res_token, spin_token = tokenise(select_string)
118 self.molecules = parse_token(mol_token)
119 self.residues = parse_token(res_token)
120 self.spins = parse_token(spin_token)
121
122
124 """Replacement function for determining if an object matches the selection.
125
126 @param obj: The data object. This can be a MoleculeContainer, ResidueContainer, or
127 SpinContainer instance or a type of these instances. If a tuple, only one
128 type of object can be in the tuple.
129 @type obj: instance or type of instances.
130 @return: The answer of whether the object matches the selection.
131 @rtype: bool
132 """
133
134
135 if self._union:
136 return (obj in self._union[0]) or (obj in self._union[1])
137
138
139 elif self._intersect:
140 return (obj in self._intersect[0]) and (obj in self._intersect[1])
141
142
143 if isinstance(obj, str):
144 return self.__contains_spin_id(obj)
145
146
147 else:
148 return self.__contains_mol_res_spin_containers(obj)
149
150
152 """Are the MoleculeContainer, ResidueContainer, and/or SpinContainer in the selection.
153
154 @param obj: The data object. This can be a MoleculeContainer, ResidueContainer, or
155 SpinContainer instance or a type of these instances. If a tuple, only one
156 type of object can be in the tuple.
157 @type obj: instance or type of instances.
158 @return: The answer of whether the objects are found within the selection object.
159 @rtype: bool
160 """
161
162
163 mol = None
164 res = None
165 spin = None
166
167
168 if not isinstance(obj, tuple):
169 obj = (obj,)
170
171
172 if len(obj) > 3:
173 return False
174
175
176 for i in range(len(obj)):
177
178 if isinstance(obj[i], MoleculeContainer):
179
180 if mol != None:
181 raise RelaxError("Comparing two molecular containers simultaneously with the selection object is not supported.")
182
183
184 mol = obj[i]
185
186
187 elif isinstance(obj[i], ResidueContainer):
188
189 if res != None:
190 raise RelaxError("Comparing two residue containers simultaneously with the selection object is not supported.")
191
192
193 res = obj[i]
194
195
196 elif isinstance(obj[i], SpinContainer):
197
198 if spin != None:
199 raise RelaxError("Comparing two spin containers simultaneously with the selection object is not supported.")
200
201
202 spin = obj[i]
203
204
205 else:
206 return False
207
208
209 select_mol = False
210 select_res = False
211 select_spin = False
212
213
214 if mol:
215
216 if not self.molecules:
217 select_mol = True
218
219
220 elif relax_re.search(self.molecules, mol.name):
221 select_mol = True
222 else:
223
224 select_mol = True
225
226
227 if not select_mol:
228 return False
229
230
231 if res:
232
233 if not self.residues:
234 select_res = True
235
236
237 elif res.num in self.residues or relax_re.search(self.residues, res.name):
238 select_res = True
239 else:
240
241 select_res = True
242
243
244 if not select_res:
245 return False
246
247
248 if spin:
249
250 if not self.spins:
251 select_spin = True
252
253
254 elif spin.num in self.spins or relax_re.search(self.spins, spin.name):
255 select_spin = True
256 else:
257
258 select_spin = True
259
260
261 return select_mol and select_res and select_spin
262
263
265 """Is the molecule, residue, and/or spin of the spin_id string located in the selection.
266
267 Only the simple selections allowed by the tokenise function are currently supported.
268
269
270 @param spin_id: The spin identification string.
271 @type spin_id: str
272 @return: The answer of whether the molecule, residue, and/or spin corresponding to
273 the spin_id string found within the selection object.
274 @rtype: bool
275 """
276
277
278 try:
279 mol_token, res_token, spin_token = tokenise(spin_id)
280 molecules = parse_token(mol_token)
281 residues = parse_token(res_token)
282 spins = parse_token(spin_token)
283 except RelaxError:
284 warn(RelaxWarning("The spin identification string " + repr(spin_id) + " is too complex for the selection object."))
285
286
288 """Determine if the molecule name, in string form, is contained in this selection object.
289
290 @keyword mol: The name of the molecule.
291 @type mol: str or None
292 @return: The answer of whether the molecule is contained withing the selection
293 object.
294 @rtype: bool
295 """
296
297
298 if self._union:
299 return self._union[0].contains_mol(mol) or self._union[1].contains_mol(mol)
300
301
302 elif self._intersect:
303 return self._intersect[0].contains_mol(mol) and self._intersect[1].contains_mol(mol)
304
305
306 if relax_re.search(self.molecules, mol):
307 return True
308
309
310 if not self.molecules:
311 return True
312
313
314 return False
315
316
317 - def contains_res(self, res_num=None, res_name=None, mol=None):
318 """Determine if the residue name, in string form, is contained in this selection object.
319
320 @keyword res_num: The residue number.
321 @type res_num: int or None
322 @keyword res_name: The residue name.
323 @type res_name: str or None
324 @keyword mol: The molecule name.
325 @type mol: str or None
326 @return: The answer of whether the molecule is contained withing the selection
327 object.
328 @rtype: bool
329 """
330
331
332 if self._union:
333 return self._union[0].contains_res(res_num, res_name, mol) or self._union[1].contains_res(res_num, res_name, mol)
334
335
336 elif self._intersect:
337 return self._intersect[0].contains_res(res_num, res_name, mol) and self._intersect[1].contains_res(res_num, res_name, mol)
338
339
340 select_mol = self.contains_mol(mol)
341
342
343 select_res = False
344
345
346 if res_num in self.residues or relax_re.search(self.residues, res_name):
347 select_res = True
348
349
350 if not self.residues:
351 select_res = True
352
353
354 return select_res and select_mol
355
356
357 - def contains_spin(self, spin_num=None, spin_name=None, res_num=None, res_name=None, mol=None):
358 """Determine if the spin is contained in this selection object.
359
360 @keyword spin_num: The spin number.
361 @type spin_num: int or None
362 @keyword spin_name: The spin name.
363 @type spin_name: str or None
364 @keyword res_num: The residue number.
365 @type res_num: int or None
366 @keyword res_name: The residue name.
367 @type res_name: str or None
368 @keyword mol: The molecule name.
369 @type mol: str or None
370 @return: The answer of whether the spin is contained withing the selection
371 object.
372 @rtype: bool
373 """
374
375
376 if self._union:
377 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)
378
379
380 elif self._intersect:
381 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)
382
383
384 select_mol = self.contains_mol(mol)
385
386
387 select_res = self.contains_res(res_num, res_name, mol)
388
389
390 select_spin = False
391
392
393 if spin_num in self.spins or relax_re.search(self.spins, spin_name):
394 select_spin = True
395
396
397 if not self.spins:
398 select_spin = True
399
400
401 return select_spin and select_res and select_mol
402
403
405 """Determine if the selection object contains molecules.
406
407 @return: The answer of whether the selection contains molecules.
408 @rtype: bool
409 """
410
411
412 if self._union:
413 return self._union[0].has_molecules() or self._union[1].has_molecules()
414
415
416 elif self._intersect:
417 return self._intersect[0].has_molecules() and self._intersect[1].has_molecules()
418
419
420 if self.molecules:
421 return True
422
423
425 """Determine if the selection object contains residues.
426
427 @return: The answer of whether the selection contains residues.
428 @rtype: bool
429 """
430
431
432 if self._union:
433 return self._union[0].has_residues() or self._union[1].has_residues()
434
435
436 elif self._intersect:
437 return self._intersect[0].has_residues() and self._intersect[1].has_residues()
438
439
440 if self.residues:
441 return True
442
443
445 """Determine if the selection object contains spins.
446
447 @return: The answer of whether the selection contains spins.
448 @rtype: bool
449 """
450
451
452 if self._union:
453 return self._union[0].has_spins() or self._union[1].has_spins()
454
455
456 elif self._intersect:
457 return self._intersect[0].has_spins() and self._intersect[1].has_spins()
458
459
460 if self.spins:
461 return True
462
463
465 """Make this Selection object the intersection of two other Selection objects.
466
467 @param select_obj0: First Selection object in intersection.
468 @type select_obj0: Selection instance.
469 @param select_obj1: First Selection object in intersection.
470 @type select_obj1: Selection instance.
471 """
472
473
474 if self._union or self._intersect or self.molecules or self.residues or self.spins:
475 raise RelaxError("Cannot define multiple Boolean relationships between Selection objects")
476
477
478 self._intersect = (select_obj0, select_obj1)
479
480
481 - def union(self, select_obj0, select_obj1):
482 """Make this Selection object the union of two other Selection objects.
483
484 @param select_obj0: First Selection object in intersection.
485 @type select_obj0: Selection instance.
486 @param select_obj1: First Selection object in intersection.
487 @type select_obj1: Selection instance.
488 """
489
490
491 if self._union or self._intersect or self.molecules or self.residues or self.spins:
492 raise RelaxError("Cannot define multiple Boolean relationships between Selection objects")
493
494
495 self._union = (select_obj0, select_obj1)
496
497
498
500 """Determine if any spins have been named.
501
502 @keyword spin_id: The spin ID string.
503 @type spin_id: None or str
504 @return: True if a spin has been named or False if no spins have been named.
505 @rtype: bool
506 """
507
508
509 for spin in spin_loop(spin_id):
510
511 if spin.name != None:
512 return True
513
514
515 return False
516
517
519 """Generate the molecule and residue spin containers from the entity saveframe records.
520
521 @param star: The NMR-STAR dictionary object.
522 @type star: NMR_STAR instance
523 """
524
525
526 for data in star.entity.loop():
527
528 mol_name = data['mol_name']
529 if mol_name:
530
531 mol_name = replace(mol_name, '(', '')
532 mol_name = replace(mol_name, ')', '')
533
534
535 mol_name = replace(mol_name, '[', '')
536 mol_name = replace(mol_name, ']', '')
537
538
539 mol_name = replace(mol_name, ',', ' ')
540
541
542 for i in range(len(data['res_nums'])):
543 create_residue(data['res_nums'][i], data['res_names'][i], mol_name=mol_name)
544
545
547 """Generate the entity saveframe records for the NMR-STAR dictionary object.
548
549 @param star: The NMR-STAR dictionary object.
550 @type star: NMR_STAR instance
551 @keyword version: The BMRB NMR-STAR dictionary format to output to.
552 @type version: str
553 """
554
555
556 for mol in molecule_loop():
557
558 if not mol.name:
559 raise RelaxError("All molecules must be named.")
560
561
562 if not hasattr(mol, 'type') or not mol.type:
563 raise RelaxError("The molecule type for the '%s' molecule must be specified, please use the appropriate molecule user function to set this." % mol.name)
564
565
566 if not hasattr(cdp, 'exp_info') or not hasattr(cdp.exp_info, 'thiol_state'):
567 raise RelaxError("The thiol state of the molecule '%s' must be specified, please use the appropriate BMRB user function to set this." % mol.name)
568
569
570 res_names = get_residue_names("#" + mol.name)
571 res_nums = get_residue_nums("#" + mol.name)
572
573
574 polymer_seq_code = one_letter_code(res_names)
575
576
577 if mol.type in ['organic molecule', 'other']:
578 mol_type = 'non-polymer'
579 else:
580 mol_type = 'polymer'
581
582
583 polymer_type = mol.type
584 if polymer_type == 'protein':
585 polymer_type = 'polypeptide(L)'
586 if polymer_type == 'DNA':
587 polymer_type = 'polydeoxyribonucleotide'
588 if polymer_type == 'RNA':
589 polymer_type = 'polyribonucleotide'
590 if polymer_type == 'inorganic molecule':
591 polymer_type = 'other'
592
593
594 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)
595
596
597 -def copy_molecule(pipe_from=None, mol_from=None, pipe_to=None, mol_to=None):
598 """Copy the contents of a molecule container to a new molecule.
599
600 For copying to be successful, the mol_from identification string must match an existent molecule.
601
602 @param pipe_from: The data pipe to copy the molecule data from. This defaults to the current
603 data pipe.
604 @type pipe_from: str
605 @param mol_from: The molecule identification string for the structure to copy the data from.
606 @type mol_from: str
607 @param pipe_to: The data pipe to copy the molecule data to. This defaults to the current
608 data pipe.
609 @type pipe_to: str
610 @param mol_to: The molecule identification string for the structure to copy the data to.
611 @type mol_to: str
612 """
613
614
615 status.spin_lock.acquire(sys._getframe().f_code.co_name)
616 try:
617
618 if pipe_from == None:
619 pipe_from = pipes.cdp_name()
620 if pipe_to == None:
621 pipe_to = pipes.cdp_name()
622
623
624 pipes.test(pipe_to)
625
626
627 mol_from_token, res_from_token, spin_from_token = tokenise(mol_from)
628 mol_to_token, res_to_token, spin_to_token = tokenise(mol_to)
629
630
631 if spin_from_token != None or spin_to_token != None:
632 raise RelaxSpinSelectDisallowError
633
634
635 if res_from_token != None or res_to_token != None:
636 raise RelaxResSelectDisallowError
637
638
639 mol_name_to = return_single_molecule_info(mol_to_token)
640
641
642 mol_to_cont = return_molecule(mol_to, pipe_to)
643 if mol_to_cont and not mol_to_cont.is_empty():
644 raise RelaxError("The molecule " + repr(mol_to) + " already exists in the " + repr(pipe_to) + " data pipe.")
645
646
647 mol_from_cont = return_molecule(mol_from, pipe_from)
648
649
650 if mol_from_cont == None:
651 raise RelaxError("The molecule " + repr(mol_from) + " does not exist in the " + repr(pipe_from) + " data pipe.")
652
653
654 pipe = pipes.get_pipe(pipe_to)
655
656
657 if pipe.mol[0].name == None and len(pipe.mol) == 1:
658 pipe.mol[0] = mol_from_cont.__clone__()
659 else:
660 pipe.mol.append(mol_from_cont.__clone__())
661
662
663 if mol_name_to != None:
664 pipe.mol[-1].name = mol_name_to
665
666
667 finally:
668 status.spin_lock.release(sys._getframe().f_code.co_name)
669
670
671 -def copy_residue(pipe_from=None, res_from=None, pipe_to=None, res_to=None):
672 """Copy the contents of the residue structure from one residue to a new residue.
673
674 For copying to be successful, the res_from identification string must match an existent residue.
675 The new residue number must be unique.
676
677 @param pipe_from: The data pipe to copy the residue from. This defaults to the current data
678 pipe.
679 @type pipe_from: str
680 @param res_from: The residue identification string for the structure to copy the data from.
681 @type res_from: str
682 @param pipe_to: The data pipe to copy the residue to. This defaults to the current data
683 pipe.
684 @type pipe_to: str
685 @param res_to: The residue identification string for the structure to copy the data to.
686 @type res_to: str
687 """
688
689
690 status.spin_lock.acquire(sys._getframe().f_code.co_name)
691 try:
692
693 if pipe_from == None:
694 pipe_from = pipes.cdp_name()
695 if pipe_to == None:
696 pipe_to = pipes.cdp_name()
697
698
699 pipes.test(pipe_to)
700
701
702 pipe = pipes.get_pipe(pipe_to)
703
704
705 mol_from_token, res_from_token, spin_from_token = tokenise(res_from)
706 mol_to_token, res_to_token, spin_to_token = tokenise(res_to)
707
708
709 if spin_from_token != None or spin_to_token != None:
710 raise RelaxSpinSelectDisallowError
711
712
713 res_num_to, res_name_to = return_single_residue_info(res_to_token)
714
715
716 res_to_cont = return_residue(res_to, pipe_to)
717 if res_to_cont and not res_to_cont.is_empty():
718 raise RelaxError("The residue " + repr(res_to) + " already exists in the " + repr(pipe_to) + " data pipe.")
719
720
721 res_from_cont = return_residue(res_from, pipe_from)
722
723
724 if res_from_cont == None:
725 raise RelaxError("The residue " + repr(res_from) + " does not exist in the " + repr(pipe_from) + " data pipe.")
726
727
728 mol_to_container = return_molecule(res_to, pipe_to)
729 if mol_to_container == None:
730 mol_to_container = pipe.mol[0]
731
732
733 if mol_to_container.res[0].num == None and mol_to_container.res[0].name == None and len(mol_to_container.res) == 1:
734 mol_to_container.res[0] = res_from_cont.__clone__()
735 else:
736 mol_to_container.res.append(res_from_cont.__clone__())
737
738
739 if res_num_to != None:
740 mol_to_container.res[-1].num = res_num_to
741 if res_name_to != None:
742 mol_to_container.res[-1].name = res_name_to
743
744
745 finally:
746 status.spin_lock.release(sys._getframe().f_code.co_name)
747
748
749 -def copy_spin(pipe_from=None, spin_from=None, pipe_to=None, spin_to=None):
750 """Copy the contents of the spin structure from one spin to a new spin.
751
752 For copying to be successful, the spin_from identification string must match an existent spin.
753 The new spin number must be unique.
754
755 @param pipe_from: The data pipe to copy the spin from. This defaults to the current data
756 pipe.
757 @type pipe_from: str
758 @param spin_from: The spin identification string for the structure to copy the data from.
759 @type spin_from: str
760 @param pipe_to: The data pipe to copy the spin to. This defaults to the current data
761 pipe.
762 @type pipe_to: str
763 @param spin_to: The spin identification string for the structure to copy the data to.
764 @type spin_to: str
765 """
766
767
768 status.spin_lock.acquire(sys._getframe().f_code.co_name)
769 try:
770
771 if pipe_from == None:
772 pipe_from = pipes.cdp_name()
773 if pipe_to == None:
774 pipe_to = pipes.cdp_name()
775
776
777 pipes.test(pipe_to)
778
779
780 pipe = pipes.get_pipe(pipe_to)
781
782
783 mol_to_token, res_to_token, spin_to_token = tokenise(spin_to)
784
785
786 if spin_to_token:
787 spin_to_cont = return_spin(spin_to, pipe_to)
788 if spin_to_cont and not spin_to_cont.is_empty():
789 raise RelaxError("The spin " + repr(spin_to) + " already exists in the " + repr(pipe_from) + " data pipe.")
790
791
792 if not return_residue(spin_from, pipe_from):
793 raise RelaxError("The residue in " + repr(spin_from) + " does not exist in the " + repr(pipe_from) + " data pipe.")
794
795
796 spin_from_cont = return_spin(spin_from, pipe_from)
797 if spin_from_cont == None:
798 raise RelaxError("The spin " + repr(spin_from) + " does not exist in the " + repr(pipe_from) + " data pipe.")
799
800
801 res_to_cont = return_residue(spin_to, pipe_to)
802 if res_to_cont == None and spin_to:
803
804 raise RelaxError("The residue in " + repr(spin_to) + " does not exist in the " + repr(pipe_from) + " data pipe.")
805 if res_to_cont == None:
806 res_to_cont = pipe.mol[0].res[0]
807
808
809 if len(res_to_cont.spin) == 1 and res_to_cont.spin[0].is_empty():
810 res_to_cont.spin[0] = spin_from_cont.__clone__()
811 else:
812 res_to_cont.spin.append(spin_from_cont.__clone__())
813
814
815 spin_num_to, spin_name_to = return_single_spin_info(spin_to_token)
816
817
818 if spin_num_to != None:
819 res_to_cont.spin[-1].num = spin_num_to
820 if spin_name_to != None:
821 res_to_cont.spin[-1].name = spin_name_to
822
823
824 finally:
825 status.spin_lock.release(sys._getframe().f_code.co_name)
826
827
829 """Count the number of molecules for which there is data.
830
831 @keyword selection: The selection string.
832 @type selection: str
833 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
834 @type pipe: str
835 @return: The number of non-empty molecules.
836 @rtype: int
837 """
838
839
840 if pipe == None:
841 pipe = pipes.cdp_name()
842
843
844 pipes.test(pipe)
845
846
847 if not exists_mol_res_spin_data(pipe=pipe):
848 return 0
849
850
851 mol_num = 0
852
853
854 for mol in molecule_loop(selection, pipe=pipe):
855 mol_num = mol_num + 1
856
857
858 return mol_num
859
860
862 """Count the number of residues for which there is data.
863
864 @keyword selection: The selection string.
865 @type selection: str
866 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
867 @type pipe: str
868 @return: The number of non-empty residues.
869 @rtype: int
870 """
871
872
873 if pipe == None:
874 pipe = pipes.cdp_name()
875
876
877 pipes.test(pipe)
878
879
880 if not exists_mol_res_spin_data(pipe=pipe):
881 return 0
882
883
884 res_num = 0
885
886
887 for res in residue_loop(selection, pipe=pipe):
888 res_num = res_num + 1
889
890
891 return res_num
892
893
894 -def count_spins(selection=None, pipe=None, skip_desel=True):
895 """Function for counting the number of spins for which there is data.
896
897 @keyword selection: The selection string.
898 @type selection: str
899 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
900 @type pipe: str
901 @keyword skip_desel: A flag which if true will cause deselected spins to be skipped in the
902 count.
903 @type skip_desel: bool
904 @return: The number of non-empty spins.
905 @rtype: int
906 """
907
908
909 if pipe == None:
910 pipe = pipes.cdp_name()
911
912
913 pipes.test(pipe)
914
915
916 if not exists_mol_res_spin_data(pipe=pipe):
917 return 0
918
919
920 spin_num = 0
921
922
923 for spin in spin_loop(selection, pipe=pipe):
924
925 if skip_desel and not spin.select:
926 continue
927
928 spin_num = spin_num + 1
929
930
931 return spin_num
932
933
935 """Add a molecule into the relax data store.
936
937 @keyword mol_name: The name of the molecule.
938 @type mol_name: str
939 @keyword mol_type: The type of molecule.
940 @type mol_type: str
941 @return: The newly created molecule.
942 @rtype: MoleculeContainer instance
943 """
944
945
946 pipes.test()
947
948
949 status.spin_lock.acquire(sys._getframe().f_code.co_name)
950 try:
951
952 if mol_type and mol_type not in ALLOWED_MOL_TYPES:
953 raise RelaxError("The molecule type '%s' must be one of %s" % (mol_type, ALLOWED_MOL_TYPES))
954
955
956 for i in xrange(len(cdp.mol)):
957 if cdp.mol[i].name == mol_name:
958 raise RelaxError("The molecule '" + repr(mol_name) + "' already exists in the relax data store.")
959
960
961 cdp.mol.add_item(mol_name=mol_name, mol_type=mol_type)
962
963
964 mol = cdp.mol[-1]
965
966
967 finally:
968 status.spin_lock.release(sys._getframe().f_code.co_name)
969
970
971 return mol
972
973
975 """Add a residue into the relax data store (and molecule if necessary).
976
977 @keyword res_num: The number of the new residue.
978 @type res_num: int
979 @keyword res_name: The name of the new residue.
980 @type res_name: str
981 @keyword mol_name: The name of the molecule to add the residue to.
982 @type mol_name: str
983 @return: The newly created residue.
984 @rtype: ResidueContainer instance
985 """
986
987
988 pipes.test()
989
990
991 status.spin_lock.acquire(sys._getframe().f_code.co_name)
992 try:
993
994 mol_cont = return_molecule(generate_spin_id(mol_name=mol_name))
995 if mol_cont == None:
996 mol_cont = create_molecule(mol_name=mol_name)
997
998
999 mol_cont.res.add_item(res_num=res_num, res_name=res_name)
1000
1001
1002 res = mol_cont.res[-1]
1003
1004
1005 finally:
1006 status.spin_lock.release(sys._getframe().f_code.co_name)
1007
1008
1009 return res
1010
1011
1012 -def create_pseudo_spin(spin_name=None, spin_num=None, res_id=None, members=None, averaging=None):
1013 """Add a pseudo-atom spin container into the relax data store.
1014
1015 @param spin_name: The name of the new pseudo-spin.
1016 @type spin_name: str
1017 @param spin_num: The identification number of the new spin.
1018 @type spin_num: int
1019 @param res_id: The molecule and residue identification string.
1020 @type res_id: str
1021 """
1022
1023
1024 pipes.test()
1025
1026
1027 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1028 try:
1029
1030 mol_token, res_token, spin_token = tokenise(res_id)
1031
1032
1033 if spin_token != None:
1034 raise RelaxSpinSelectDisallowError
1035
1036
1037 if res_id:
1038 res_to_cont = return_residue(res_id)
1039 if res_to_cont == None:
1040 raise RelaxError("The residue in " + repr(res_id) + " does not exist in the current data pipe.")
1041 else:
1042 res_to_cont = cdp.mol[0].res[0]
1043
1044
1045 if averaging not in ['linear']:
1046 raise RelaxError("The '%s' averaging technique is unknown." % averaging)
1047
1048
1049 positions = []
1050 for atom in members:
1051
1052 spin = return_spin(atom)
1053
1054
1055 if spin == None:
1056 raise RelaxNoSpinError(atom)
1057
1058
1059 if not hasattr(spin, 'pos') or spin.pos == None:
1060 raise RelaxError("Positional information is not available for the atom '%s'." % atom)
1061
1062
1063 pos = spin.pos
1064
1065
1066 multi_model = True
1067 if type(pos[0]) in [float, float64]:
1068 multi_model = False
1069 pos = [pos]
1070
1071
1072 positions.append([])
1073 for i in range(len(pos)):
1074 positions[-1].append(pos[i].tolist())
1075
1076
1077 for atom in members:
1078
1079 spin = return_spin(atom)
1080
1081
1082 if res_id:
1083 spin.pseudo_name = res_id + '@' + spin_name
1084 else:
1085 spin.pseudo_name = '@' + spin_name
1086 spin.pseudo_num = spin_num
1087
1088
1089 res_to_cont.spin.add_item(spin_num=spin_num, spin_name=spin_name)
1090 spin = res_to_cont.spin[-1]
1091
1092
1093 spin.averaging = averaging
1094 spin.members = members
1095 if averaging == 'linear':
1096
1097 ave = linear_ave(positions)
1098
1099
1100 if multi_model:
1101 spin.pos = ave
1102 else:
1103 spin.pos = ave[0]
1104
1105
1106 finally:
1107 status.spin_lock.release(sys._getframe().f_code.co_name)
1108
1109
1110 -def create_spin(spin_num=None, spin_name=None, res_num=None, res_name=None, mol_name=None):
1111 """Add a spin into the relax data store (and molecule and residue if necessary).
1112
1113 @keyword spin_num: The number of the new spin.
1114 @type spin_num: int
1115 @keyword spin_name: The name of the new spin.
1116 @type spin_name: str
1117 @keyword res_num: The number of the residue to add the spin to.
1118 @type res_num: int
1119 @keyword res_name: The name of the residue to add the spin to.
1120 @type res_name: str
1121 @keyword mol_name: The name of the molecule to add the spin to.
1122 @type mol_name: str
1123 @return: The newly created spin.
1124 @rtype: SpinContainer instance
1125 """
1126
1127
1128 pipes.test()
1129
1130
1131 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1132 try:
1133
1134 if not return_molecule(generate_spin_id(mol_name=mol_name)):
1135 create_molecule(mol_name=mol_name)
1136 res_cont = return_residue(generate_spin_id(mol_name=mol_name, res_num=res_num, res_name=res_name))
1137 if res_cont == None:
1138 res_cont = create_residue(mol_name=mol_name, res_num=res_num, res_name=res_name)
1139
1140
1141 if len(res_cont.spin) == 1 and res_cont.spin[0].is_empty():
1142 spin_cont = res_cont.spin[0]
1143 spin_cont.name = spin_name
1144 spin_cont.num = spin_num
1145
1146
1147 else:
1148 res_cont.spin.add_item(spin_num=spin_num, spin_name=spin_name)
1149 spin_cont = res_cont.spin[-1]
1150
1151
1152 finally:
1153 status.spin_lock.release(sys._getframe().f_code.co_name)
1154
1155
1156 return spin_cont
1157
1158
1160 """Convert the global index into the molecule, residue, and spin indices.
1161
1162 @param global_index: The global spin index, spanning the molecule and residue containers.
1163 @type global_index: int
1164 @param pipe: The data pipe containing the spin. Defaults to the current data
1165 pipe.
1166 @type pipe: str
1167 @return: The corresponding molecule, residue, and spin indices.
1168 @rtype: tuple of int
1169 """
1170
1171
1172 if pipe == None:
1173 pipe = pipes.cdp_name()
1174
1175
1176 pipes.test(pipe)
1177
1178
1179 spin_num = 0
1180 for mol_index, res_index, spin_index in spin_index_loop(pipe=pipe):
1181
1182 if spin_num == global_index:
1183 return mol_index, res_index, spin_index
1184
1185
1186 spin_num = spin_num + 1
1187
1188
1190 """Function for deleting molecules from the current data pipe.
1191
1192 @param mol_id: The molecule identifier string.
1193 @type mol_id: str
1194 """
1195
1196
1197 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1198 try:
1199
1200 mol_token, res_token, spin_token = tokenise(mol_id)
1201
1202
1203 if spin_token != None:
1204 raise RelaxSpinSelectDisallowError
1205
1206
1207 if res_token != None:
1208 raise RelaxResSelectDisallowError
1209
1210
1211 molecules = parse_token(mol_token)
1212
1213
1214 indices = []
1215
1216
1217 for i in xrange(len(cdp.mol)):
1218
1219 if cdp.mol[i].name in molecules:
1220 indices.append(i)
1221
1222
1223 indices.reverse()
1224
1225
1226 for index in indices:
1227 cdp.mol.pop(index)
1228
1229
1230 if len(cdp.mol) == 0:
1231 cdp.mol.add_item()
1232
1233
1234 finally:
1235 status.spin_lock.release(sys._getframe().f_code.co_name)
1236
1237
1239 """Function for deleting residues from the current data pipe.
1240
1241 @param res_id: The molecule and residue identifier string.
1242 @type res_id: str
1243 """
1244
1245
1246 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1247 try:
1248
1249 mol_token, res_token, spin_token = tokenise(res_id)
1250
1251
1252 if spin_token != None:
1253 raise RelaxSpinSelectDisallowError
1254
1255
1256 residues = parse_token(res_token)
1257
1258
1259 for mol in molecule_loop(res_id):
1260
1261 indices = []
1262
1263
1264 for i in xrange(len(mol.res)):
1265
1266 if mol.res[i].num in residues or mol.res[i].name in residues:
1267 indices.append(i)
1268
1269
1270 indices.reverse()
1271
1272
1273 for index in indices:
1274 mol.res.pop(index)
1275
1276
1277 if len(mol.res) == 0:
1278 mol.res.add_item()
1279
1280
1281 finally:
1282 status.spin_lock.release(sys._getframe().f_code.co_name)
1283
1284
1286 """Function for deleting spins from the current data pipe.
1287
1288 @param spin_id: The molecule, residue, and spin identifier string.
1289 @type spin_id: str
1290 """
1291
1292
1293 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1294 try:
1295
1296
1297 mol_token, res_token, spin_token = tokenise(spin_id)
1298
1299
1300 spins = parse_token(spin_token)
1301
1302
1303 for res in residue_loop(spin_id):
1304
1305 indices = []
1306
1307
1308 for i in xrange(len(res.spin)):
1309
1310 if res.spin[i].num in spins or res.spin[i].name in spins:
1311 indices.append(i)
1312
1313
1314 indices.reverse()
1315
1316
1317 for index in indices:
1318 res.spin.pop(index)
1319
1320
1321 if len(res.spin) == 0:
1322 res.spin.add_item()
1323
1324
1325 finally:
1326 status.spin_lock.release(sys._getframe().f_code.co_name)
1327
1328
1330 """Function for displaying the information associated with the molecule.
1331
1332 @param mol_id: The molecule identifier string.
1333 @type mol_id: str
1334 """
1335
1336
1337 mol_token, res_token, spin_token = tokenise(mol_id)
1338
1339
1340 if res_token != None:
1341 raise RelaxResSelectDisallowError
1342 if spin_token != None:
1343 raise RelaxSpinSelectDisallowError
1344
1345
1346 if mol_token:
1347 mol_sel = '#' + mol_token
1348 else:
1349 mol_sel = None
1350
1351
1352 print(("\n\n%-15s %-15s" % ("Molecule", "Number of residues")))
1353
1354
1355 for mol in molecule_loop(mol_sel):
1356
1357 print(("%-15s %-15s" % (mol.name, repr(len(mol.res)))))
1358
1359
1361 """Function for displaying the information associated with the residue.
1362
1363 @param res_id: The molecule and residue identifier string.
1364 @type res_id: str
1365 """
1366
1367
1368 mol_token, res_token, spin_token = tokenise(res_id)
1369
1370
1371 if spin_token != None:
1372 raise RelaxSpinSelectDisallowError
1373
1374
1375 print(("\n\n%-15s %-15s %-15s %-15s" % ("Molecule", "Res number", "Res name", "Number of spins")))
1376
1377
1378 for res, mol_name in residue_loop(res_id, full_info=True):
1379 print(("%-15s %-15s %-15s %-15s" % (mol_name, repr(res.num), res.name, repr(len(res.spin)))))
1380
1381
1383 """Function for displaying the information associated with the spin.
1384
1385 @param spin_id: The molecule and residue identifier string.
1386 @type spin_id: str
1387 """
1388
1389
1390 print(("\n\n%-15s %-15s %-15s %-15s %-15s" % ("Molecule", "Res number", "Res name", "Spin number", "Spin name")))
1391
1392
1393 for spin, mol_name, res_num, res_name in spin_loop(spin_id, full_info=True):
1394
1395 print(("%-15s %-15s %-15s %-15s %-15s" % (mol_name, repr(res_num), res_name, repr(spin.num), spin.name)))
1396
1397
1399 """Function for determining if any molecule-residue-spin data exists.
1400
1401 @keyword pipe: The data pipe in which the molecule-residue-spin data will be checked for.
1402 @type pipe: str
1403 @return: The answer to the question about the existence of data.
1404 @rtype: bool
1405 """
1406
1407
1408 if pipe == None:
1409 pipe = pipes.cdp_name()
1410
1411
1412 pipes.test(pipe)
1413
1414
1415 dp = pipes.get_pipe(pipe)
1416
1417
1418 if dp.mol.is_empty():
1419 return False
1420
1421
1422 return True
1423
1424
1425 -def find_index(selection=None, pipe=None, global_index=True):
1426 """Find and return the spin index or indices for the selection string.
1427
1428 @keyword selection: The spin selection identifier.
1429 @type selection: str
1430 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
1431 @type pipe: str
1432 @keyword global_index: A flag which if True will cause the global index to be returned. If
1433 False, then the molecule, residue, and spin indices will be returned.
1434 @type global_index: bool
1435 @return: The global spin index or the molecule, residue, and spin indices.
1436 @rtype: int or tuple of 3 int
1437 """
1438
1439
1440 if pipe == None:
1441 pipe = pipes.cdp_name()
1442
1443
1444 pipes.test(pipe)
1445
1446
1447 dp = pipes.get_pipe(pipe)
1448
1449
1450 select_obj = Selection(selection)
1451
1452
1453 global_i = -1
1454 mol_index = -1
1455
1456
1457 for mol in dp.mol:
1458
1459 mol_index = mol_index + 1
1460
1461
1462 res_index = -1
1463
1464
1465 for res in mol.res:
1466
1467 res_index = res_index + 1
1468
1469
1470 spin_index = -1
1471
1472
1473 for spin in res.spin:
1474
1475 spin_index = spin_index + 1
1476 global_i = global_i + 1
1477
1478
1479 if (mol, res, spin) in select_obj:
1480
1481 if global_index:
1482 return global_i
1483 else:
1484 return mol_index, res_index, spin_index
1485
1486
1488 """Determine the first residue number.
1489
1490 @return: The number of the first residue.
1491 @rtype: int
1492 """
1493
1494
1495 mol = return_molecule(selection)
1496
1497
1498 return mol.res[0].num
1499
1500
1501 -def generate_spin_id(mol_name=None, res_num=None, res_name=None, spin_num=None, spin_name=None):
1502 """Generate the spin selection string.
1503
1504 @param mol_name: The molecule name.
1505 @type mol_name: str or None
1506 @param res_num: The residue number.
1507 @type res_num: int or None
1508 @param res_name: The residue name.
1509 @type res_name: str or None
1510 @param spin_num: The spin number.
1511 @type spin_num: int or None
1512 @param spin_name: The spin name.
1513 @type spin_name: str or None
1514 @return: The spin identification string.
1515 @rtype: str
1516 """
1517
1518
1519 id = ""
1520
1521
1522 if mol_name != None:
1523 id = id + "#" + mol_name
1524
1525
1526 if res_num != None:
1527 id = id + ":" + str(res_num)
1528 if res_num != None and res_name != None:
1529 id = id + "&:" + res_name
1530 elif res_name != None:
1531 id = id + ":" + res_name
1532
1533
1534 if spin_num != None:
1535 id = id + "@" + str(spin_num)
1536 if spin_num != None and spin_name != None:
1537 id = id + "&@" + spin_name
1538 elif spin_name != None:
1539 id = id + "@" + spin_name
1540
1541
1542 return id
1543
1544
1545 -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):
1546 """Generate the spin selection string from the given data array.
1547
1548 @param data: An array containing the molecule, residue, and/or spin data.
1549 @type data: list of str
1550 @param mol_name_col: The column containing the molecule name information.
1551 @type mol_name_col: int or None
1552 @param res_name_col: The column containing the residue name information.
1553 @type res_name_col: int or None
1554 @param res_num_col: The column containing the residue number information.
1555 @type res_num_col: int or None
1556 @param spin_name_col: The column containing the spin name information.
1557 @type spin_name_col: int or None
1558 @param spin_num_col: The column containing the spin number information.
1559 @type spin_num_col: int or None
1560 @return: The spin identification string.
1561 @rtype: str
1562 """
1563
1564
1565 id = ""
1566
1567
1568 if mol_name_col and data[mol_name_col-1] not in [None, 'None']:
1569 id = id + "#" + data[mol_name_col-1]
1570
1571
1572 if res_num_col and data[res_num_col-1] not in [None, 'None']:
1573 id = id + ":" + str(data[res_num_col-1])
1574 if (res_num_col and data[res_num_col-1] not in [None, 'None']) and (res_name_col and data[res_name_col-1]):
1575 id = id + "&:" + data[res_name_col-1]
1576 elif res_name_col and data[res_name_col-1] not in [None, 'None']:
1577 id = id + ":" + data[res_name_col-1]
1578
1579
1580 if spin_num_col and data[spin_num_col-1] not in [None, 'None']:
1581 id = id + "@" + str(data[spin_num_col-1])
1582 if (spin_num_col and data[spin_num_col-1] not in [None, 'None']) and (spin_name_col and data[spin_name_col-1]):
1583 id = id + "&@" + data[spin_name_col-1]
1584 elif spin_name_col and data[spin_name_col-1] not in [None, 'None']:
1585 id = id + "@" + data[spin_name_col-1]
1586
1587
1588 return id
1589
1590
1592 """Return a list of the molecule ID strings.
1593
1594 @param selection: The molecule selection identifier.
1595 @type selection: str
1596 @return: The molecule ID strings.
1597 @rtype: list of str
1598 """
1599
1600
1601 mol_ids = []
1602 for mol, mol_id in molecule_loop(selection, return_id=True):
1603 mol_ids.append(mol_id)
1604
1605
1606 return mol_ids
1607
1608
1610 """Return a list of the molecule names.
1611
1612 @param selection: The molecule selection identifier.
1613 @type selection: str
1614 @return: The molecule names.
1615 @rtype: list of str
1616 """
1617
1618
1619 mol_names = []
1620 for mol in molecule_loop(selection):
1621 mol_names.append(mol.name)
1622
1623
1624 return mol_names
1625
1626
1628 """Return a list of the residue ID strings.
1629
1630 @param selection: The molecule and residue selection identifier.
1631 @type selection: str
1632 @return: The residue ID strings.
1633 @rtype: list of str
1634 """
1635
1636
1637 res_ids = []
1638 for res, res_id in residue_loop(selection, return_id=True):
1639 res_ids.append(res_id)
1640
1641
1642 return res_ids
1643
1644
1646 """Return a list of the residue names.
1647
1648 @param selection: The molecule and residue selection identifier.
1649 @type selection: str
1650 @return: The residue names.
1651 @rtype: list of str
1652 """
1653
1654
1655 res_names = []
1656 for res in residue_loop(selection):
1657 res_names.append(res.name)
1658
1659
1660 return res_names
1661
1662
1664 """Return a list of the residue numbers.
1665
1666 @param selection: The molecule and residue selection identifier.
1667 @type selection: str
1668 @return: The residue numbers.
1669 @rtype: list of str
1670 """
1671
1672
1673 res_nums = []
1674 for res in residue_loop(selection):
1675 res_nums.append(res.num)
1676
1677
1678 return res_nums
1679
1680
1682 """Return a list of the spin ID strings.
1683
1684 @param selection: The molecule and spin selection identifier.
1685 @type selection: str
1686 @return: The spin ID strings.
1687 @rtype: list of str
1688 """
1689
1690
1691 spin_ids = []
1692 for spin, spin_id in spin_loop(selection, return_id=True):
1693 spin_ids.append(spin_id)
1694
1695
1696 return spin_ids
1697
1698
1700 """Determine the last residue number.
1701
1702 @param selection: The molecule selection identifier.
1703 @type selection: str
1704 @return: The number of the last residue.
1705 @rtype: int
1706 """
1707
1708
1709 mol = return_molecule(selection)
1710
1711
1712 return mol.res[-1].num
1713
1714
1716 """Generator function for looping over all the molecules of the given selection.
1717
1718 @param selection: The molecule selection identifier.
1719 @type selection: str
1720 @param pipe: The data pipe containing the molecule. Defaults to the current data pipe.
1721 @type pipe: str
1722 @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.
1723 @type return_id: bool
1724 @return: The molecule specific data container.
1725 @rtype: instance of the MoleculeContainer class.
1726 """
1727
1728
1729 if pipe == None:
1730 pipe = pipes.cdp_name()
1731
1732
1733 pipes.test(pipe)
1734
1735
1736 dp = pipes.get_pipe(pipe)
1737
1738
1739 if not exists_mol_res_spin_data(pipe=pipe):
1740 return
1741
1742
1743 select_obj = Selection(selection)
1744
1745
1746 for mol in dp.mol:
1747
1748 if mol not in select_obj:
1749 continue
1750
1751
1752 if return_id:
1753 mol_id = generate_spin_id(mol.name)
1754
1755
1756 if return_id:
1757 yield mol, mol_id
1758 else:
1759 yield mol
1760
1761
1763 """Perform linear averaging of the atomic positions.
1764
1765 @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.
1766 @type positions: list of lists of numpy float arrays
1767 @return: The averaged positions as a list of vectors.
1768 @rtype: list of numpy float arrays
1769 """
1770
1771
1772 ave = []
1773 for model_index in range(len(positions[0])):
1774
1775 ave.append(array([0.0, 0.0, 0.0]))
1776
1777
1778 for coord_index in range(3):
1779
1780 for atom_index in range(len(positions)):
1781 ave[model_index][coord_index] = ave[model_index][coord_index] + positions[atom_index][model_index][coord_index]
1782
1783
1784 ave[model_index][coord_index] = ave[model_index][coord_index] / len(positions)
1785
1786
1787 return ave
1788
1789
1791 """Name the molecules.
1792
1793 @param mol_id: The molecule identification string.
1794 @type mol_id: str
1795 @param name: The new molecule name.
1796 @type name: str
1797 @keyword force: A flag which if True will cause the named molecule to be renamed.
1798 @type force: bool
1799 """
1800
1801
1802 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1803 try:
1804
1805
1806 mol = return_molecule(mol_id)
1807
1808
1809 select_obj = Selection(mol_id)
1810 if select_obj.has_residues():
1811 raise RelaxResSelectDisallowError
1812 if select_obj.has_spins():
1813 raise RelaxSpinSelectDisallowError
1814
1815
1816 if mol:
1817 if mol.name and not force:
1818 warn(RelaxWarning("The molecule '%s' is already named. Set the force flag to rename." % mol_id))
1819 else:
1820 mol.name = name
1821
1822
1823 finally:
1824 status.spin_lock.release(sys._getframe().f_code.co_name)
1825
1826
1828 """Name the residues.
1829
1830 @param res_id: The residue identification string.
1831 @type res_id: str
1832 @param name: The new residue name.
1833 @type name: str
1834 @keyword force: A flag which if True will cause the named residue to be renamed.
1835 @type force: bool
1836 """
1837
1838
1839 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1840 try:
1841
1842 select_obj = Selection(res_id)
1843 if select_obj.has_spins():
1844 raise RelaxSpinSelectDisallowError
1845
1846
1847 for res, mol_name in residue_loop(res_id, full_info=True):
1848 if res.name and not force:
1849 warn(RelaxWarning("The residue '%s' is already named. Set the force flag to rename." % generate_spin_id(mol_name, res.num, res.name)))
1850 else:
1851 res.name = name
1852
1853
1854 finally:
1855 status.spin_lock.release(sys._getframe().f_code.co_name)
1856
1857
1858 -def name_spin(spin_id=None, name=None, force=False):
1859 """Name the spins.
1860
1861 @keyword spin_id: The spin identification string.
1862 @type spin_id: str
1863 @keyword name: The new spin name.
1864 @type name: str
1865 @keyword force: A flag which if True will cause the named spin to be renamed.
1866 @type force: bool
1867 """
1868
1869
1870 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1871 try:
1872
1873 for spin, id in spin_loop(spin_id, return_id=True):
1874 if spin.name and not force:
1875 warn(RelaxWarning("The spin '%s' is already named. Set the force flag to rename." % id))
1876 else:
1877 spin.name = name
1878
1879
1880 finally:
1881 status.spin_lock.release(sys._getframe().f_code.co_name)
1882
1883
1885 """Number the residues.
1886
1887 @param res_id: The residue identification string.
1888 @type res_id: str
1889 @param number: The new residue number.
1890 @type number: int
1891 @keyword force: A flag which if True will cause the numbered residue to be renumbered.
1892 @type force: bool
1893 """
1894
1895
1896 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1897 try:
1898
1899 i = 0
1900 for res in residue_loop(res_id):
1901 i = i + 1
1902
1903
1904 if i > 1:
1905 raise RelaxError("The numbering of multiple residues is disallowed, each residue requires a unique number.")
1906
1907
1908 select_obj = Selection(res_id)
1909 if select_obj.has_spins():
1910 raise RelaxSpinSelectDisallowError
1911
1912
1913 for res, mol_name in residue_loop(res_id, full_info=True):
1914 if res.num and not force:
1915 warn(RelaxWarning("The residue '%s' is already numbered. Set the force flag to renumber." % generate_spin_id(mol_name, res.num, res.name)))
1916 else:
1917 res.num = number
1918
1919
1920 finally:
1921 status.spin_lock.release(sys._getframe().f_code.co_name)
1922
1923
1924 -def number_spin(spin_id=None, number=None, force=False):
1925 """Number the spins.
1926
1927 @param spin_id: The spin identification string.
1928 @type spin_id: str
1929 @param number: The new spin number.
1930 @type number: int
1931 @keyword force: A flag which if True will cause the numbered spin to be renumbered.
1932 @type force: bool
1933 """
1934
1935
1936 status.spin_lock.acquire(sys._getframe().f_code.co_name)
1937 try:
1938
1939 i = 0
1940 for spin in spin_loop(spin_id):
1941 i = i + 1
1942
1943
1944 if number != None and i > 1:
1945 raise RelaxError("The numbering of multiple spins is disallowed, as each spin requires a unique number.")
1946
1947
1948 for spin, id in spin_loop(spin_id, return_id=True):
1949 if spin.num and not force:
1950 warn(RelaxWarning("The spin '%s' is already numbered. Set the force flag to renumber." % id))
1951 else:
1952 spin.num = number
1953
1954
1955 finally:
1956 status.spin_lock.release(sys._getframe().f_code.co_name)
1957
1958
1960 """Convert the list of residue names into a string of one letter residue codes.
1961
1962 Standard amino acids are converted to the one letter code. Unknown residues are labelled as 'X'.
1963
1964
1965 @param res_names: A list of residue names.
1966 @type res_names: list or str
1967 @return: The one letter codes for the residues.
1968 @rtype: str
1969 """
1970
1971
1972 aa_table = [
1973 ['Alanine', 'ALA', 'A'],
1974 ['Arginine', 'ARG', 'R'],
1975 ['Asparagine', 'ASN', 'N'],
1976 ['Aspartic acid', 'ASP', 'D'],
1977 ['Cysteine', 'CYS', 'C'],
1978 ['Glutamic acid', 'GLU', 'E'],
1979 ['Glutamine', 'GLN', 'Q'],
1980 ['Glycine', 'GLY', 'G'],
1981 ['Histidine', 'HIS', 'H'],
1982 ['Isoleucine', 'ILE', 'I'],
1983 ['Leucine', 'LEU', 'L'],
1984 ['Lysine', 'LYS', 'K'],
1985 ['Methionine', 'MET', 'M'],
1986 ['Phenylalanine', 'PHE', 'F'],
1987 ['Proline', 'PRO', 'P'],
1988 ['Serine', 'SER', 'S'],
1989 ['Threonine', 'THR', 'T'],
1990 ['Tryptophan', 'TRP', 'W'],
1991 ['Tyrosine', 'TYR', 'Y'],
1992 ['Valine', 'VAL', 'V']
1993 ]
1994
1995
1996 seq = ''
1997 for res in res_names:
1998
1999 match = False
2000 for i in range(len(aa_table)):
2001 if upper(res) == aa_table[i][1]:
2002 seq = seq + aa_table[i][2]
2003 match = True
2004 break
2005
2006
2007 if not match:
2008 seq = seq + 'X'
2009
2010
2011 return seq
2012
2013
2015 """Parse the token string and return a list of identifying numbers and names.
2016
2017 Firstly the token is split by the ',' character into its individual elements and all whitespace
2018 stripped from the elements. Numbers are converted to integers, names are left as strings, and
2019 ranges are converted into the full list of integers.
2020
2021 @param token: The identification string, the elements of which are separated by commas.
2022 Each element can be either a single number, a range of numbers (two numbers
2023 separated by '-'), or a name.
2024 @type token: str
2025 @keyword verbosity: A flag which if True will cause a number of print outs to be activated.
2026 @type verbosity: bool
2027 @return: A list of identifying numbers and names.
2028 @rtype: list of int and str
2029 """
2030
2031
2032 if token == None:
2033 return []
2034
2035
2036 if not isinstance(token, list):
2037 tokens = [token]
2038 else:
2039 tokens = token
2040
2041
2042 id_list = []
2043 for token in tokens:
2044
2045 elements = split(',', token)
2046
2047
2048 for element in elements:
2049
2050 element = strip(element)
2051
2052
2053 indices= []
2054 for i in xrange(1, len(element)):
2055 if element[i] == '-':
2056 indices.append(i)
2057
2058
2059 valid_range = True
2060 if indices:
2061
2062 if len(indices) > 2:
2063 if verbosity:
2064 print(("The range element " + repr(element) + " is invalid. Assuming the '-' character does not specify a range."))
2065 valid_range = False
2066
2067
2068 try:
2069 start = int(element[:indices[0]])
2070 end = int(element[indices[0]+1:])
2071 except ValueError:
2072 if verbosity:
2073 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."))
2074 valid_range = False
2075
2076
2077 if valid_range and start >= end:
2078 if verbosity:
2079 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."))
2080 valid_range = False
2081
2082
2083 if valid_range:
2084 for i in range(start, end+1):
2085 id_list.append(i)
2086
2087
2088 else:
2089 id_list.append(element)
2090
2091
2092 else:
2093
2094 try:
2095 element = int(element)
2096 except ValueError:
2097 pass
2098
2099
2100 id_list.append(element)
2101
2102
2103 id_list.sort()
2104
2105
2106 return id_list
2107
2108
2109 -def residue_loop(selection=None, pipe=None, full_info=False, return_id=False):
2110 """Generator function for looping over all the residues of the given selection.
2111
2112 @param selection: The residue selection identifier.
2113 @type selection: str
2114 @param pipe: The data pipe containing the residue. Defaults to the current data pipe.
2115 @type pipe: str
2116 @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.
2117 @type full_info: boolean
2118 @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.
2119 @type return_id: bool
2120 @return: The residue specific data container and, if full_info=True, the molecule name.
2121 @rtype: instance of the ResidueContainer class. If full_info=True, the type is the tuple (ResidueContainer, str).
2122 """
2123
2124
2125 if pipe == None:
2126 pipe = pipes.cdp_name()
2127
2128
2129 pipes.test(pipe)
2130
2131
2132 dp = pipes.get_pipe(pipe)
2133
2134
2135 if not exists_mol_res_spin_data(pipe=pipe):
2136 return
2137
2138
2139 select_obj = Selection(selection)
2140
2141
2142 for mol in dp.mol:
2143
2144 for res in mol.res:
2145
2146 if (mol, res) not in select_obj:
2147 continue
2148
2149
2150 if return_id:
2151 res_id = generate_spin_id(mol.name, res.num, res.name)
2152
2153
2154 if full_info and return_id:
2155 yield res, mol.name, res_id
2156 elif full_info:
2157 yield res, mol.name
2158 elif return_id:
2159 yield res, res_id
2160 else:
2161 yield res
2162
2163
2165 """Function for returning the molecule data container of the given selection.
2166
2167 @param selection: The molecule selection identifier.
2168 @type selection: str
2169 @param pipe: The data pipe containing the molecule. Defaults to the current data pipe.
2170 @type pipe: str
2171 @return: The molecule specific data container.
2172 @rtype: instance of the MoleculeContainer class.
2173 """
2174
2175
2176 if pipe == None:
2177 pipe = pipes.cdp_name()
2178
2179
2180 pipes.test(pipe)
2181
2182
2183 dp = pipes.get_pipe(pipe)
2184
2185
2186 select_obj = Selection(selection)
2187
2188
2189 mol_num = 0
2190 mol_container = None
2191 for mol in dp.mol:
2192
2193 if mol not in select_obj:
2194 continue
2195
2196
2197 if selection == None and mol.name != None:
2198 continue
2199
2200
2201 mol_container = mol
2202
2203
2204 mol_num = mol_num + 1
2205
2206
2207 if mol_num > 1:
2208 raise RelaxMultiMolIDError(selection)
2209
2210
2211 return mol_container
2212
2213
2215 """Function for returning the residue data container of the given selection.
2216
2217 @param selection: The residue selection identifier.
2218 @type selection: str
2219 @param pipe: The data pipe containing the residue. Defaults to the current data pipe.
2220 @type pipe: str
2221 @return: The residue specific data container.
2222 @rtype: instance of the ResidueContainer class.
2223 """
2224
2225
2226 if pipe == None:
2227 pipe = pipes.cdp_name()
2228
2229
2230 pipes.test(pipe)
2231
2232
2233 dp = pipes.get_pipe(pipe)
2234
2235
2236 select_obj = Selection(selection)
2237
2238
2239 res = None
2240 res_num = 0
2241 res_container = None
2242 for mol in dp.mol:
2243
2244 if mol not in select_obj:
2245 continue
2246
2247
2248 for res in mol.res:
2249
2250 if res not in select_obj:
2251 continue
2252
2253
2254 res_container = res
2255
2256
2257 res_num = res_num + 1
2258
2259
2260 if res_num > 1:
2261 raise RelaxMultiResIDError(selection)
2262
2263
2264 return res_container
2265
2266
2267 -def return_spin(selection=None, pipe=None, full_info=False):
2268 """Function for returning the spin data container of the given selection.
2269
2270 If more than one selection is given, then the boolean AND operation will be used to pull out the spin.
2271
2272 @param selection: The spin selection identifier.
2273 @type selection: str
2274 @param pipe: The data pipe containing the spin. Defaults to the current data pipe.
2275 @type pipe: str
2276 @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.
2277 @type full_info: boolean
2278 @return: The spin system specific data container and, if full_info=True, the molecule name, residue number, and residue name.
2279 @rtype: instance of the SpinContainer class. If full_info=True, the type is the tuple (SpinContainer, str, int, str).
2280 """
2281
2282
2283 if isinstance(selection, unicode):
2284 selection = str(selection)
2285
2286
2287 if pipe == None:
2288 pipe = pipes.cdp_name()
2289
2290
2291 dp = pipes.get_pipe(pipe)
2292
2293
2294 select_obj = Selection(selection)
2295
2296
2297 spin = None
2298 spin_num = 0
2299 spin_container = None
2300 for mol in dp.mol:
2301
2302 if mol not in select_obj:
2303 continue
2304
2305
2306 for res in mol.res:
2307
2308 if res not in select_obj:
2309 continue
2310
2311
2312 for spin in res.spin:
2313
2314 if spin not in select_obj:
2315 continue
2316
2317
2318 mol_container = mol
2319 res_container = res
2320 spin_container = spin
2321
2322
2323 spin_num = spin_num + 1
2324
2325
2326 if spin_num > 1:
2327 raise RelaxMultiSpinIDError(selection)
2328
2329
2330 if full_info:
2331 return mol_container.name, res_container.num, res_container.name, spin_container
2332 else:
2333 return spin_container
2334
2335
2337 """Function for returning the spin data container corresponding to the global index.
2338
2339 @param global_index: The global spin index, spanning the molecule and residue containers.
2340 @type global_index: int
2341 @param pipe: The data pipe containing the spin. Defaults to the current data
2342 pipe.
2343 @type pipe: str
2344 @keyword return_spin_id: A flag which if True will cause both the spin container and spin
2345 identification string to be returned.
2346 @type return_spin_id: bool
2347 @return: The spin specific data container (additionally the spin
2348 identification string if return_spin_id is set).
2349 @rtype: instance of the SpinContainer class (or tuple of SpinContainer and
2350 str)
2351 """
2352
2353
2354 if pipe == None:
2355 pipe = pipes.cdp_name()
2356
2357
2358 pipes.test(pipe)
2359
2360
2361 spin_num = 0
2362 for spin, mol_name, res_num, res_name in spin_loop(full_info=True, pipe=pipe):
2363
2364 if spin_num == global_index:
2365
2366 if return_spin_id:
2367
2368 spin_id = generate_spin_id(mol_name, res_num, res_name, spin.num, spin.name)
2369
2370
2371 return spin, spin_id
2372
2373
2374 else:
2375 return spin
2376
2377
2378 spin_num = spin_num + 1
2379
2380
2382 """Return the single molecule name corresponding to the molecule token.
2383
2384 @param molecule_token: The molecule identification string.
2385 @type molecule_token: str
2386 @return: The molecule name.
2387 @rtype: str
2388 """
2389
2390
2391 molecule_info = parse_token(molecule_token)
2392
2393
2394 mol_name = None
2395 for info in molecule_info:
2396
2397 if mol_name == None:
2398 mol_name = info
2399 else:
2400 raise RelaxError("The molecule identifier " + repr(molecule_token) + " does not correspond to a single molecule.")
2401
2402
2403 return mol_name
2404
2405
2407 """Return the single residue number and name corresponding to the residue token.
2408
2409 @param residue_token: The residue identification string.
2410 @type residue_token: str
2411 @return: A tuple containing the residue number and the residue name.
2412 @rtype: (int, str)
2413 """
2414
2415
2416 residue_info = parse_token(residue_token)
2417
2418
2419 res_num = None
2420 res_name = None
2421 for info in residue_info:
2422
2423 if isinstance(info, str):
2424 if res_name == None:
2425 res_name = info
2426 else:
2427 raise RelaxError("The residue identifier " + repr(residue_token) + " does not correspond to a single residue.")
2428
2429
2430 if isinstance(info, int):
2431 if res_num == None:
2432 res_num = info
2433 else:
2434 raise RelaxError("The residue identifier " + repr(residue_token) + " does not correspond to a single residue.")
2435
2436
2437 return res_num, res_name
2438
2439
2441 """Return the single spin number and name corresponding to the spin token.
2442
2443 @param spin_token: The spin identification string.
2444 @type spin_token: str
2445 @return: A tuple containing the spin number and the spin name.
2446 @rtype: (int, str)
2447 """
2448
2449
2450 spin_info = parse_token(spin_token)
2451
2452
2453 spin_num = None
2454 spin_name = None
2455 for info in spin_info:
2456
2457 if isinstance(info, str):
2458 if spin_name == None:
2459 spin_name = info
2460 else:
2461 raise RelaxError("The spin identifier " + repr(spin_token) + " does not correspond to a single spin.")
2462
2463
2464 if isinstance(info, int):
2465 if spin_num == None:
2466 spin_num = info
2467 else:
2468 raise RelaxError("The spin identifier " + repr(spin_token) + " does not correspond to a single spin.")
2469
2470
2471 return spin_num, spin_name
2472
2473
2475 """Test if the sequence data in both pipes are the same.
2476
2477 @param pipe1: The first data pipe.
2478 @type pipe1: str
2479 @param pipe2: The second data pipe.
2480 @type pipe2: str
2481 @return: True if the sequence data matches, False otherwise.
2482 @rtype: bool
2483 """
2484
2485
2486 pipes.test(pipe1)
2487 pipes.test(pipe2)
2488
2489
2490 pipe1 = pipes.get_pipe(pipe1)
2491 pipe2 = pipes.get_pipe(pipe2)
2492
2493
2494 if len(pipe1.mol) != len(pipe2.mol):
2495 return False
2496
2497
2498 for i in xrange(len(pipe1.mol)):
2499
2500 if len(pipe1.mol[i].res) != len(pipe2.mol[i].res):
2501 return False
2502
2503
2504 for j in xrange(len(pipe1.mol[i].res)):
2505
2506 if len(pipe1.mol[i].res[j].spin) != len(pipe2.mol[i].res[j].spin):
2507 return False
2508
2509
2510 for k in xrange(len(pipe1.mol[i].res[j].spin)):
2511
2512 if pipe1.mol[i].res[j].spin[k].num != pipe2.mol[i].res[j].spin[k].num:
2513 return False
2514
2515
2516 if pipe1.mol[i].res[j].spin[k].name != pipe2.mol[i].res[j].spin[k].name:
2517 return False
2518
2519
2520 return True
2521
2522
2524 """Set the element type of the spins.
2525
2526 @keyword spin_id: The spin identification string.
2527 @type spin_id: str
2528 @keyword element: The IUPAC element name.
2529 @type element: str
2530 @keyword force: A flag which if True will cause the element to be changed.
2531 @type force: bool
2532 """
2533
2534
2535 valid_names = ['H',
2536 'C',
2537 'N',
2538 'O',
2539 'F',
2540 'Na',
2541 'P',
2542 'Cd'
2543 ]
2544
2545
2546 if element not in valid_names:
2547 raise(RelaxError("The element name '%s' is not valid and should be one of the IUPAC names %s." % (element, valid_names)))
2548
2549
2550
2551 for spin, id in spin_loop(spin_id, return_id=True):
2552 if hasattr(spin, 'element') and spin.element and not force:
2553 warn(RelaxWarning("The element type of the spin '%s' is already set. Set the force flag to True to rename." % id))
2554 else:
2555 spin.element = element
2556
2557
2559 """Convert the single spin ID string into a list of the mol, res, and spin names and numbers.
2560
2561 @param id: The spin ID string.
2562 @type id: str
2563 @return: The molecule name, the residue number and name, and the spin number and name.
2564 @rtype: str, int, str, int, str
2565 """
2566
2567
2568 mol_token, res_token, spin_token = tokenise(id)
2569 mol_info = parse_token(mol_token)
2570 res_info = parse_token(res_token)
2571 spin_info = parse_token(spin_token)
2572
2573
2574 mol_name = None
2575 if len(mol_info) > 1:
2576 raise RelaxError("The single spin ID '%s' should only belong to one molecule, not %s." % (id, mol_info))
2577 if len(mol_info) == 1:
2578 mol_name = mol_info[0]
2579
2580
2581 res_names = []
2582 res_nums = []
2583 for i in range(len(res_info)):
2584 try:
2585 res_nums.append(int(res_info[i]))
2586 except ValueError:
2587 res_names.append(res_info[i])
2588
2589
2590 res_num = None
2591 if len(res_nums) > 1:
2592 raise RelaxError("The single spin ID '%s' should only belong to one residue number, not %s." % (id, res_info))
2593 elif len(res_nums) == 1:
2594 res_num = res_nums[0]
2595
2596
2597 res_name = None
2598 if len(res_names) > 1:
2599 raise RelaxError("The single spin ID '%s' should only belong to one residue name, not %s." % (id, res_info))
2600 elif len(res_names) == 1:
2601 res_name = res_names[0]
2602
2603
2604 spin_names = []
2605 spin_nums = []
2606 for i in range(len(spin_info)):
2607 try:
2608 spin_nums.append(int(spin_info[i]))
2609 except ValueError:
2610 spin_names.append(spin_info[i])
2611
2612
2613 spin_num = None
2614 if len(spin_nums) > 1:
2615 raise RelaxError("The single spin ID '%s' should only belong to one spin number, not %s." % (id, spin_info))
2616 elif len(spin_nums) == 1:
2617 spin_num = spin_nums[0]
2618
2619
2620 spin_name = None
2621 if len(spin_names) > 1:
2622 raise RelaxError("The single spin ID '%s' should only belong to one spin name, not %s." % (id, spin_info))
2623 elif len(spin_names) == 1:
2624 spin_name = spin_names[0]
2625
2626
2627 return mol_name, res_num, res_name, spin_num, spin_name
2628
2629
2630 -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):
2631 """Function for determining if the spin is located within the list of spins.
2632
2633 @param spin_list: The list of spins. The first dimension corresponds to different spins,
2634 the second corresponds to the spin information columns.
2635 @type spin_list: list of lists of str
2636 @keyword mol_name_col: The column containing the molecule name information.
2637 @type mol_name_col: int or None
2638 @keyword res_num_col: The column containing the residue number information.
2639 @type res_num_col: int or None
2640 @keyword res_name_col: The column containing the residue name information.
2641 @type res_name_col: int or None
2642 @keyword spin_num_col: The column containing the spin number information.
2643 @type spin_num_col: int or None
2644 @keyword spin_name_col: The column containing the spin name information.
2645 @type spin_name_col: int or None
2646 @keyword mol_name: The molecule name.
2647 @type mol_name: str or None
2648 @keyword res_num: The residue number.
2649 @type res_num: int or None
2650 @keyword res_name: The residue name.
2651 @type res_name: str or None
2652 @keyword spin_num: The spin number.
2653 @type spin_num: int or None
2654 @keyword spin_name: The spin name.
2655 @type spin_name: str or None
2656 @return: The answer of whether the spin is within the list.
2657 @rtype: bool
2658 """
2659
2660
2661 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))
2662
2663
2664 for spin in spin_list:
2665
2666 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)
2667
2668
2669 if spin_id in select_obj:
2670 return True
2671
2672
2673 return False
2674
2675
2677 """Generator function for looping over all selected spins, returning the mol-res-spin indices.
2678
2679 @param selection: The spin system selection identifier.
2680 @type selection: str
2681 @param pipe: The data pipe containing the spin. Defaults to the current data pipe.
2682 @type pipe: str
2683 @return: The molecule, residue, and spin index.
2684 @rtype: tuple of 3 int
2685 """
2686
2687
2688 if pipe == None:
2689 pipe = pipes.cdp_name()
2690
2691
2692 pipes.test(pipe)
2693
2694
2695 dp = pipes.get_pipe(pipe)
2696
2697
2698 if not exists_mol_res_spin_data(pipe=pipe):
2699 return
2700
2701
2702 select_obj = Selection(selection)
2703
2704
2705 for mol_index in xrange(len(dp.mol)):
2706
2707 mol = dp.mol[mol_index]
2708
2709
2710 for res_index in xrange(len(dp.mol[mol_index].res)):
2711
2712 res = dp.mol[mol_index].res[res_index]
2713
2714
2715 for spin_index in xrange(len(dp.mol[mol_index].res[res_index].spin)):
2716
2717 spin = dp.mol[mol_index].res[res_index].spin[spin_index]
2718
2719
2720 if (mol, res, spin) not in select_obj:
2721 continue
2722
2723
2724 yield mol_index, res_index, spin_index
2725
2726
2727 -def spin_loop(selection=None, pipe=None, full_info=False, return_id=False):
2728 """Generator function for looping over all the spin systems of the given selection.
2729
2730 @keyword selection: The spin system selection identifier.
2731 @type selection: str
2732 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
2733 @type pipe: str
2734 @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.
2735 @type full_info: bool
2736 @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.
2737 @type return_id: bool
2738 @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.
2739 @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)
2740 """
2741
2742
2743 if pipe == None:
2744 pipe = pipes.cdp_name()
2745
2746
2747 pipes.test(pipe)
2748
2749
2750 dp = pipes.get_pipe(pipe)
2751
2752
2753 if not exists_mol_res_spin_data(pipe=pipe):
2754 return
2755
2756
2757 select_obj = Selection(selection)
2758
2759
2760 for mol in dp.mol:
2761
2762 for res in mol.res:
2763
2764 for spin in res.spin:
2765
2766 if (mol, res, spin) not in select_obj:
2767 continue
2768
2769
2770 if return_id:
2771 spin_id = generate_spin_id(mol.name, res.num, res.name, spin.num, spin.name)
2772
2773
2774 if full_info and return_id:
2775 yield spin, mol.name, res.num, res.name, spin_id
2776 elif full_info:
2777 yield spin, mol.name, res.num, res.name
2778 elif return_id:
2779 yield spin, spin_id
2780 else:
2781 yield spin
2782
2783
2785 """Split the input selection string returning the mol_token, res_token, and spin_token strings.
2786
2787 The mol_token is identified as the text from the '#' to either the ':' or '@' characters or the
2788 end of the string.
2789
2790 The res_token is identified as the text from the ':' to either the '@' character or the end of
2791 the string.
2792
2793 The spin_token is identified as the text from the '@' to the end of the string.
2794
2795 @param selection: The selection identifier.
2796 @type selection: str
2797 @return: The mol_token, res_token, and spin_token.
2798 @rtype: 3-tuple of str or None
2799 """
2800
2801
2802 if selection == None:
2803 return None, None, None
2804
2805
2806
2807 mol_info = ''
2808 res_info = ''
2809 spin_info = ''
2810 pos = 'mol'
2811 for i in range(len(selection)):
2812
2813 if selection[i] == '|':
2814 raise RelaxError("The boolean operator '|' is not supported for individual spin selections.")
2815
2816
2817 if selection[i] == ':':
2818 if pos == 'spin':
2819 raise RelaxError("Invalid selection string '%s'." % selection)
2820 pos = 'res'
2821
2822
2823 if selection[i] == '@':
2824 pos = 'spin'
2825
2826
2827 if pos == 'mol':
2828 mol_info = mol_info + selection[i]
2829 if pos == 'res':
2830 res_info = res_info + selection[i]
2831 if pos == 'spin':
2832 spin_info = spin_info + selection[i]
2833
2834
2835
2836
2837
2838
2839 if mol_info:
2840
2841 if '&' in mol_info:
2842 raise RelaxError("The boolean operator '&' is not supported for the molecule component of individual spin IDs.")
2843
2844
2845
2846
2847
2848
2849 if ':' in mol_info or '@' in mol_info or mol_info[0] != '#' or count(mol_info, '#') != 1:
2850 raise RelaxError("Invalid molecule selection '%s'." % mol_info)
2851
2852
2853 mol_token = mol_info[1:]
2854
2855
2856 else:
2857 mol_token = None
2858
2859
2860
2861
2862
2863
2864 if res_info:
2865
2866 if count(res_info, '&') > 1:
2867 raise RelaxError("Only one '&' boolean operator is supported for the residue component of individual spin IDs.")
2868
2869
2870 res_token = split('&', res_info)
2871
2872
2873 for i in range(len(res_token)):
2874
2875
2876
2877
2878
2879 if '#' in res_token[i] or '@' in res_token[i] or res_token[i][0] != ':' or count(res_token[i], ':') != 1:
2880 raise RelaxError("Invalid residue selection '%s'." % res_info)
2881
2882
2883 res_token[i] = res_token[i][1:]
2884
2885
2886 if len(res_token) == 1:
2887 res_token = res_token[0]
2888
2889
2890 else:
2891 res_token = None
2892
2893
2894
2895
2896
2897
2898 if spin_info:
2899
2900 if count(spin_info, '&') > 1:
2901 raise RelaxError("Only one '&' boolean operator is supported for the spin component of individual spin IDs.")
2902
2903
2904 spin_token = split('&', spin_info)
2905
2906
2907 for i in range(len(spin_token)):
2908
2909
2910
2911
2912
2913 if '#' in spin_token[i] or ':' in spin_token[i] or spin_token[i][0] != '@' or count(spin_token[i], '@') != 1:
2914 raise RelaxError("Invalid spin selection '%s'." % spin_info)
2915
2916
2917 spin_token[i] = spin_token[i][1:]
2918
2919
2920 if len(spin_token) == 1:
2921 spin_token = spin_token[0]
2922
2923
2924 else:
2925 spin_token = None
2926
2927
2928
2929
2930
2931
2932 if mol_token == None and res_token == None and spin_token == None:
2933 raise RelaxError("The selection string '%s' is invalid." % selection)
2934
2935
2936 return mol_token, res_token, spin_token
2937
2938
2940 """Set the molecule type.
2941
2942 @param mol_id: The molecule identification string.
2943 @type mol_id: str
2944 @param type: The molecule type.
2945 @type type: str
2946 @keyword force: A flag which if True will cause the molecule type to be overwritten.
2947 @type force: bool
2948 """
2949
2950
2951 if type not in ALLOWED_MOL_TYPES:
2952 raise RelaxError("The molecule type '%s' must be one of %s." % (type, ALLOWED_MOL_TYPES))
2953
2954
2955 select_obj = Selection(mol_id)
2956 if select_obj.has_residues():
2957 raise RelaxResSelectDisallowError
2958 if select_obj.has_spins():
2959 raise RelaxSpinSelectDisallowError
2960
2961
2962 for mol in molecule_loop(mol_id):
2963 if hasattr(mol, 'type') and mol.type and not force:
2964 warn(RelaxWarning("The molecule '%s' already has its type set. Set the force flag to change." % mol_id))
2965 else:
2966 mol.type = type
2967