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