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