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