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