Package generic_fns :: Module mol_res_spin
[hide private]
[frames] | no frames]

Source Code for Module generic_fns.mol_res_spin

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