Package pipe_control :: Module selection
[hide private]
[frames] | no frames]

Source Code for Module pipe_control.selection

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2014 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 selecting and deselecting spins.""" 
 24   
 25  # Python module imports 
 26  import sys 
 27  from warnings import warn 
 28   
 29  # relax module imports. 
 30  from lib.errors import RelaxError, RelaxNoDomainError, RelaxNoSequenceError 
 31  from lib.selection import Selection, spin_id_to_data_list 
 32  from lib.sequence import read_spin_data, write_spin_data 
 33  from lib.warnings import RelaxNoSpinWarning 
 34  from pipe_control.interatomic import interatomic_loop 
 35  from pipe_control.mol_res_spin import check_mol_res_spin_data, exists_mol_res_spin_data, generate_spin_id_unique, return_spin, spin_loop 
 36  from pipe_control.pipes import check_pipe 
 37  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
 38  from user_functions.objects import Desc_container 
 39   
 40   
 41  boolean_doc = Desc_container("Boolean operators") 
 42  boolean_doc.add_paragraph("The boolean operator can be used to change how spin systems or interatomic data containers are selected.  The allowed values are: 'OR', 'NOR', 'AND', 'NAND', 'XOR', 'XNOR'.  The following table details how the selections will occur for the different boolean operators.") 
 43  table = uf_tables.add_table(label="table: bool operators", caption="Boolean operators and their effects on selections") 
 44  table.add_headings(["Spin system or interatomic data container", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) 
 45  table.add_row(["Original selection", "0", "1", "1", "1", "1", "0", "1", "0", "1"]) 
 46  table.add_row(["New selection", "0", "1", "1", "1", "1", "1", "0", "0", "0"]) 
 47  table.add_row(["OR", "0", "1", "1", "1", "1", "1", "1", "0", "1"]) 
 48  table.add_row(["NOR", "1", "0", "0", "0", "0", "0", "0", "1", "0"]) 
 49  table.add_row(["AND", "0", "1", "1", "1", "1", "0", "0", "0", "0"]) 
 50  table.add_row(["NAND", "1", "0", "0", "0", "0", "1", "1", "1", "1"]) 
 51  table.add_row(["XOR", "0", "0", "0", "0", "0", "1", "1", "0", "1"]) 
 52  table.add_row(["XNOR", "1", "1", "1", "1", "1", "0", "0", "1", "0"]) 
 53  boolean_doc.add_table(table.label) 
 54   
 55   
56 -def boolean_deselect(current=None, boolean=None):
57 """Return the new boolean deselection result using the current selection. 58 59 @keyword current: The current selection state. 60 @type current: bool 61 @keyword boolean: The boolean operator used to select with. It can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. 62 @type boolean: str 63 @return: The new selection state. 64 @rtype: bool 65 """ 66 67 # Boolean selections. 68 if boolean == 'OR': 69 state = current or False 70 elif boolean == 'NOR': 71 state = not (current or False) 72 elif boolean == 'AND': 73 state = current and False 74 elif boolean == 'NAND': 75 state = not (current and False) 76 elif boolean == 'XOR': 77 state = not (current and False) and (current or False) 78 elif boolean == 'XNOR': 79 state = (current and False) or not (current or False) 80 else: 81 raise RelaxError("Unknown boolean operator " + repr(boolean)) 82 83 # Return the new selection state. 84 return state
85 86
87 -def boolean_select(current=None, boolean=None):
88 """Return the new boolean selection result using the current selection. 89 90 @keyword current: The current selection state. 91 @type current: bool 92 @keyword boolean: The boolean operator used to select with. It can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. 93 @type boolean: str 94 @return: The new selection state. 95 @rtype: bool 96 """ 97 98 # Boolean selections. 99 if boolean == 'OR': 100 state = current or True 101 elif boolean == 'NOR': 102 state = not (current or True) 103 elif boolean == 'AND': 104 state = current and True 105 elif boolean == 'NAND': 106 state = not (current and True) 107 elif boolean == 'XOR': 108 state = not (current and True) and (current or True) 109 elif boolean == 'XNOR': 110 state = (current and True) or not (current or True) 111 else: 112 raise RelaxError("Unknown boolean operator " + repr(boolean)) 113 114 # Return the new selection state. 115 return state
116 117
118 -def desel_all():
119 """Deselect all spins. 120 121 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 122 """ 123 124 # Test if the current data pipe exists. 125 check_pipe() 126 127 # Test if sequence data is loaded. 128 if not exists_mol_res_spin_data(): 129 raise RelaxNoSequenceError 130 131 # Loop over the spins and deselect them. 132 for spin in spin_loop(): 133 spin.select = False
134 135
136 -def desel_interatom(spin_id1=None, spin_id2=None, boolean='AND', change_all=False):
137 """Deselect specific interatomic data containers. 138 139 @keyword spin_id1: The spin ID string of the first spin of the pair. 140 @type spin_id1: str or None 141 @keyword spin_id2: The spin ID string of the second spin of the pair. 142 @type spin_id2: str or None 143 @param boolean: The boolean operator used to deselect the spin systems with. It can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. This will be ignored if the change_all flag is set. 144 @type boolean: str 145 @keyword change_all: A flag which if True will cause all spins not specified in the file to be selected. Only the boolean operator 'AND' is compatible with this flag set to True (all others will be ignored). 146 @type change_all: bool 147 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 148 @raises RelaxError: If the boolean operator is unknown. 149 """ 150 151 # Test if the current data pipe exists. 152 check_pipe() 153 154 # Test if sequence data is loaded. 155 if not exists_mol_res_spin_data(): 156 raise RelaxNoSequenceError 157 158 # First select all interatom containers if the change_all flag is set. 159 if change_all: 160 # Interatomic data loop. 161 for interatom in interatomic_loop(skip_desel=False): 162 interatom.select = True 163 164 # Interatomic data loop. 165 for interatom in interatomic_loop(selection1=spin_id1, selection2=spin_id2, skip_desel=False): 166 # Deselect just the specified residues. 167 if change_all: 168 interatom.select = False 169 170 # Boolean selections. 171 else: 172 interatom.select = boolean_deselect(current=interatom.select, boolean=boolean)
173 174
175 -def desel_read(file=None, dir=None, file_data=None, spin_id_col=None, mol_name_col=None, res_num_col=None, res_name_col=None, spin_num_col=None, spin_name_col=None, sep=None, spin_id=None, boolean='AND', change_all=False):
176 """Deselect the spins contained in the given file. 177 178 @keyword file: The name of the file to open. 179 @type file: str 180 @keyword dir: The directory containing the file (defaults to the current 181 directory if None). 182 @type dir: str or None 183 @keyword file_data: An alternative opening a file, if the data already exists in the 184 correct format. The format is a list of lists where the first 185 index corresponds to the row and the second the column. 186 @type file_data: list of lists 187 @keyword spin_id_col: The column containing the spin ID strings. If supplied, the 188 mol_name_col, res_name_col, res_num_col, spin_name_col, and 189 spin_num_col arguments must be none. 190 @type spin_id_col: int or None 191 @keyword mol_name_col: The column containing the molecule name information. If 192 supplied, spin_id_col must be None. 193 @type mol_name_col: int or None 194 @keyword res_name_col: The column containing the residue name information. If 195 supplied, spin_id_col must be None. 196 @type res_name_col: int or None 197 @keyword res_num_col: The column containing the residue number information. If 198 supplied, spin_id_col must be None. 199 @type res_num_col: int or None 200 @keyword spin_name_col: The column containing the spin name information. If supplied, 201 spin_id_col must be None. 202 @type spin_name_col: int or None 203 @keyword spin_num_col: The column containing the spin number information. If supplied, 204 spin_id_col must be None. 205 @type spin_num_col: int or None 206 @keyword sep: The column separator which, if None, defaults to whitespace. 207 @type sep: str or None 208 @keyword spin_id: The spin ID string used to restrict data loading to a subset of 209 all spins. 210 @type spin_id: None or str 211 @param boolean: The boolean operator used to deselect the spin systems with. It 212 can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. 213 This will be ignored if the change_all flag is set. 214 @type boolean: str 215 @keyword change_all: A flag which if True will cause all spins not specified in the 216 file to be selected. Only the boolean operator 'AND' is 217 compatible with this flag set to True (all others will be 218 ignored). 219 @type change_all: bool 220 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 221 @raises RelaxError: If the boolean operator is unknown. 222 """ 223 224 # Test if the current data pipe exists. 225 check_pipe() 226 227 # Test if sequence data is loaded. 228 if not exists_mol_res_spin_data(): 229 raise RelaxNoSequenceError 230 231 # First select all spins if the change_all flag is set. 232 if change_all: 233 for spin in spin_loop(): 234 spin.select = True 235 236 # Then deselect the spins in the file. 237 ids = [] 238 for mol_name, res_num, res_name, spin_num, spin_name in read_spin_data(file=file, dir=dir, file_data=file_data, spin_id_col=spin_id_col, 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, sep=sep, spin_id=spin_id): 239 # Get the corresponding spin container. 240 id = generate_spin_id_unique(mol_name=mol_name, res_num=res_num, res_name=res_name, spin_num=spin_num, spin_name=spin_name) 241 spin = return_spin(id) 242 243 # No spin. 244 if spin == None: 245 warn(RelaxNoSpinWarning(id)) 246 continue 247 248 # Deselect the spin. 249 if change_all: 250 spin.select = False 251 252 # Boolean selections. 253 else: 254 spin.select = boolean_deselect(current=spin.select, boolean=boolean) 255 256 # Store the spin ID for printouts. 257 if not spin.select: 258 ids.append(id) 259 260 # Printout. 261 if not len(ids): 262 print("No spins deselected.") 263 else: 264 print("The following spins were deselected:") 265 for id in ids: 266 print(id)
267 268
269 -def desel_spin(spin_id=None, boolean='AND', change_all=False):
270 """Deselect specific spins. 271 272 @keyword spin_id: The spin identification string. 273 @type spin_id: str or None 274 @param boolean: The boolean operator used to deselect the spin systems with. It 275 can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. 276 This will be ignored if the change_all flag is set. 277 @type boolean: str 278 @keyword change_all: A flag which if True will cause all spins not specified in the 279 file to be selected. Only the boolean operator 'AND' is 280 compatible with this flag set to True (all others will be 281 ignored). 282 @type change_all: bool 283 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 284 @raises RelaxError: If the boolean operator is unknown. 285 """ 286 287 # Test if the current data pipe exists. 288 check_pipe() 289 290 # Test if sequence data is loaded. 291 if not exists_mol_res_spin_data(): 292 raise RelaxNoSequenceError 293 294 # First select all spins if the change_all flag is set. 295 if change_all: 296 for spin in spin_loop(): 297 spin.select = True 298 299 # Loop over the specified spins. 300 for spin in spin_loop(spin_id): 301 # Deselect just the specified residues. 302 if change_all: 303 spin.select = False 304 305 # Boolean selections. 306 else: 307 spin.select = boolean_deselect(current=spin.select, boolean=boolean)
308 309
310 -def display(sep=None, mol_name_flag=True, res_num_flag=True, res_name_flag=True, spin_num_flag=True, spin_name_flag=True):
311 """Display the current spin selections. 312 313 @keyword sep: The column seperator which, if None, defaults to whitespace. 314 @type sep: str or None 315 @keyword mol_name_flag: A flag which if True will cause the molecule name column to be written. 316 @type mol_name_flag: bool 317 @keyword res_num_flag: A flag which if True will cause the residue number column to be written. 318 @type res_num_flag: bool 319 @keyword res_name_flag: A flag which if True will cause the residue name column to be written. 320 @type res_name_flag: bool 321 @keyword spin_name_flag: A flag which if True will cause the spin name column to be written. 322 @type spin_name_flag: bool 323 @keyword spin_num_flag: A flag which if True will cause the spin number column to be written. 324 @type spin_num_flag: bool 325 """ 326 327 # Test if the sequence data is loaded. 328 check_mol_res_spin_data() 329 330 # Init the data. 331 mol_names = [] 332 res_nums = [] 333 res_names = [] 334 spin_nums = [] 335 spin_names = [] 336 selections = [] 337 338 # Spin loop. 339 for spin, mol_name, res_num, res_name in spin_loop(full_info=True, skip_desel=False): 340 mol_names.append(mol_name) 341 res_nums.append(res_num) 342 res_names.append(res_name) 343 spin_nums.append(spin.num) 344 spin_names.append(spin.name) 345 selections.append(spin.select) 346 347 # Remove unwanted data. 348 if not mol_name_flag: 349 mol_names = None 350 if not res_num_flag: 351 res_nums = None 352 if not res_name_flag: 353 res_names = None 354 if not spin_num_flag: 355 spin_nums = None 356 if not spin_name_flag: 357 spin_names = None 358 359 # Write the data. 360 write_spin_data(file=sys.stdout, sep=sep, mol_names=mol_names, res_nums=res_nums, res_names=res_names, spin_nums=spin_nums, spin_names=spin_names, data=selections, data_name="selection")
361 362
363 -def is_mol_selected(selection=None):
364 """Query if the molecule is selected. 365 366 @keyword selection: The molecule ID string. 367 @type selection: str 368 """ 369 370 # Find if any spins are selected. 371 select = False 372 for spin in spin_loop(selection): 373 if spin.select: 374 select = True 375 break 376 377 # Return the state. 378 return select
379 380
381 -def is_res_selected(selection=None):
382 """Query if the residue is selected. 383 384 @keyword selection: The residue ID string. 385 @type selection: str 386 """ 387 388 # Find if any spins are selected. 389 select = False 390 for spin in spin_loop(selection): 391 if spin.select: 392 select = True 393 break 394 395 # Return the state. 396 return select
397 398
399 -def is_spin_selected(selection=None):
400 """Query if the spin is selected. 401 402 @keyword selection: The molecule ID string. 403 @type selection: str 404 """ 405 406 # Get the spin. 407 spin = return_spin(selection) 408 409 # Return the selected state. 410 return spin.select
411 412
413 -def reverse(spin_id=None):
414 """Reversal of spin selections. 415 416 @keyword spin_id: The spin identification string. 417 @type spin_id: str or None 418 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 419 """ 420 421 # Test if the current data pipe exists. 422 check_pipe() 423 424 # Test if sequence data is loaded. 425 if not exists_mol_res_spin_data(): 426 raise RelaxNoSequenceError 427 428 # Loop over the spin systems and reverse the selection flag. 429 for spin in spin_loop(spin_id): 430 # Reverse the selection. 431 if spin.select: 432 spin.select = False 433 else: 434 spin.select = True
435 436
437 -def sel_all():
438 """Select all residues. 439 440 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 441 """ 442 443 # Test if the current data pipe exists. 444 check_pipe() 445 446 # Test if sequence data is loaded. 447 if not exists_mol_res_spin_data(): 448 raise RelaxNoSequenceError 449 450 # Loop over the spins and select them. 451 for spin in spin_loop(): 452 spin.select = True
453 454
455 -def sel_domain(domain_id=None, boolean='OR', change_all=False):
456 """Select all spins and interatomic data containers of the given domain. 457 458 @keyword domain_id: The domain ID string. 459 @type domain_id: str or None 460 @param boolean: The boolean operator used to select the spin systems with. It can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. This will be ignored if the change_all flag is set. 461 @type boolean: str 462 @keyword change_all: A flag which if True will cause all spins and interatomic data containers outside of the domain to be deselected. 463 @type change_all: bool 464 """ 465 466 # Test if the current data pipe exists. 467 check_pipe() 468 469 # Test if the domain is defined. 470 if not hasattr(cdp, 'domain') or domain_id not in cdp.domain: 471 raise RelaxNoDomainError(domain_id) 472 473 # The domain selection object. 474 domain = Selection(cdp.domain[domain_id]) 475 476 # Loop over the spins and select as required. 477 for spin, mol_name, res_num, res_name in spin_loop(full_info=True): 478 # Inside the domain. 479 if domain.contains_spin(spin_name=spin.name, spin_num=spin.num, res_name=res_name, res_num=res_num, mol=mol_name): 480 spin.select = boolean_select(current=spin.select, boolean=boolean) 481 482 # Deselect spins outside of the domain. 483 elif change_all: 484 spin.select = False 485 486 # Interatomic data loop. 487 for interatom in interatomic_loop(): 488 # Decode the spin ids. 489 mol_name1, res_num1, res_name1, spin_num1, spin_name1 = spin_id_to_data_list(interatom.spin_id1) 490 mol_name2, res_num2, res_name2, spin_num2, spin_name2 = spin_id_to_data_list(interatom.spin_id2) 491 492 # Inside the domain. 493 if domain.contains_spin(spin_name=spin_name1, spin_num=spin_num1, res_name=res_name1, res_num=res_num1, mol=mol_name1) or domain.contains_spin(spin_name=spin_name2, spin_num=spin_num2, res_name=res_name2, res_num=res_num2, mol=mol_name2): 494 interatom.select = boolean_select(current=interatom.select, boolean=boolean) 495 496 # Deselect containers outside of the domain. 497 elif change_all: 498 interatom.select = False
499 500
501 -def sel_interatom(spin_id1=None, spin_id2=None, boolean='OR', change_all=False):
502 """Select specific interatomic data containers. 503 504 @keyword spin_id1: The spin ID string of the first spin of the pair. 505 @type spin_id1: str or None 506 @keyword spin_id2: The spin ID string of the second spin of the pair. 507 @type spin_id2: str or None 508 @param boolean: The boolean operator used to select the spin systems with. It can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. This will be ignored if the change_all flag is set. 509 @type boolean: str 510 @keyword change_all: A flag which if True will cause all spins not specified in the file to be deselected. Only the boolean operator 'OR' is compatible with this flag set to True (all others will be ignored). 511 @type change_all: bool 512 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 513 @raises RelaxError: If the boolean operator is unknown. 514 """ 515 516 # Test if the current data pipe exists. 517 check_pipe() 518 519 # Test if sequence data is loaded. 520 if not exists_mol_res_spin_data(): 521 raise RelaxNoSequenceError 522 523 # First deselect all interatom containers if the change_all flag is set. 524 if change_all: 525 # Interatomic data loop. 526 for interatom in interatomic_loop(skip_desel=False): 527 interatom.select = False 528 529 # Interatomic data loop. 530 for interatom in interatomic_loop(selection1=spin_id1, selection2=spin_id2, skip_desel=False): 531 # Select just the specified containers. 532 if change_all: 533 interatom.select = True 534 535 # Boolean selections. 536 else: 537 interatom.select = boolean_select(current=interatom.select, boolean=boolean)
538 539
540 -def sel_read(file=None, dir=None, file_data=None, spin_id_col=None, mol_name_col=None, res_num_col=None, res_name_col=None, spin_num_col=None, spin_name_col=None, sep=None, spin_id=None, boolean='OR', change_all=False):
541 """Select the spins contained in the given file. 542 543 @keyword file: The name of the file to open. 544 @type file: str 545 @keyword dir: The directory containing the file (defaults to the current 546 directory if None). 547 @type dir: str or None 548 @keyword file_data: An alternative opening a file, if the data already exists in the 549 correct format. The format is a list of lists where the first 550 index corresponds to the row and the second the column. 551 @type file_data: list of lists 552 @keyword spin_id_col: The column containing the spin ID strings. If supplied, the 553 mol_name_col, res_name_col, res_num_col, spin_name_col, and 554 spin_num_col arguments must be none. 555 @type spin_id_col: int or None 556 @keyword mol_name_col: The column containing the molecule name information. If 557 supplied, spin_id_col must be None. 558 @type mol_name_col: int or None 559 @keyword res_name_col: The column containing the residue name information. If 560 supplied, spin_id_col must be None. 561 @type res_name_col: int or None 562 @keyword res_num_col: The column containing the residue number information. If 563 supplied, spin_id_col must be None. 564 @type res_num_col: int or None 565 @keyword spin_name_col: The column containing the spin name information. If supplied, 566 spin_id_col must be None. 567 @type spin_name_col: int or None 568 @keyword spin_num_col: The column containing the spin number information. If supplied, 569 spin_id_col must be None. 570 @type spin_num_col: int or None 571 @keyword sep: The column separator which, if None, defaults to whitespace. 572 @type sep: str or None 573 @keyword spin_id: The spin ID string used to restrict data loading to a subset of 574 all spins. 575 @type spin_id: None or str 576 @param boolean: The boolean operator used to select the spin systems with. It 577 can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. 578 This will be ignored if the change_all flag is set. 579 @type boolean: str 580 @keyword change_all: A flag which if True will cause all spins not specified in the 581 file to be deselected. Only the boolean operator 'OR' is 582 compatible with this flag set to True (all others will be 583 ignored). 584 @type change_all: bool 585 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 586 @raises RelaxError: If the boolean operator is unknown. 587 """ 588 589 # Test if the current data pipe exists. 590 check_pipe() 591 592 # Test if sequence data is loaded. 593 if not exists_mol_res_spin_data(): 594 raise RelaxNoSequenceError 595 596 # First deselect all spins if the change_all flag is set. 597 if change_all: 598 # Loop over all spins. 599 for spin in spin_loop(): 600 spin.select = False 601 602 # Then deselect the spins in the file. 603 ids = [] 604 for id in read_spin_data(file=file, dir=dir, file_data=file_data, spin_id_col=spin_id_col, 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, sep=sep, spin_id=spin_id): 605 # Get the corresponding spin container. 606 spin = return_spin(id) 607 608 # No spin. 609 if spin == None: 610 warn(RelaxNoSpinWarning(id)) 611 continue 612 613 # Select the spin. 614 if change_all: 615 spin.select = True 616 617 # Boolean selections. 618 else: 619 spin.select = boolean_select(current=spin.select, boolean=boolean) 620 621 # Store the spin ID for printouts. 622 if spin.select: 623 ids.append(id) 624 625 # Printout. 626 if not len(ids): 627 print("No spins selected.") 628 else: 629 print("The following spins were selected:") 630 for id in ids: 631 print(id)
632 633
634 -def sel_spin(spin_id=None, boolean='OR', change_all=False):
635 """Select specific spins. 636 637 @keyword spin_id: The spin identification string. 638 @type spin_id: str or None 639 @param boolean: The boolean operator used to select the spin systems with. It 640 can be one of 'OR', 'NOR', 'AND', 'NAND', 'XOR', or 'XNOR'. 641 This will be ignored if the change_all flag is set. 642 @type boolean: str 643 @keyword change_all: A flag which if True will cause all spins not specified in the 644 file to be deselected. Only the boolean operator 'OR' is 645 compatible with this flag set to True (all others will be 646 ignored). 647 @type change_all: bool 648 @raises RelaxNoSequenceError: If no molecule/residue/spins sequence data exists. 649 @raises RelaxError: If the boolean operator is unknown. 650 """ 651 652 # Test if the current data pipe exists. 653 check_pipe() 654 655 # Test if sequence data is loaded. 656 if not exists_mol_res_spin_data(): 657 raise RelaxNoSequenceError 658 659 # First deselect all spins if the change_all flag is set. 660 if change_all: 661 # Loop over all spins. 662 for spin in spin_loop(): 663 spin.select = False 664 665 # Loop over the specified spins. 666 for spin in spin_loop(spin_id): 667 # Select just the specified residues. 668 if change_all: 669 spin.select = True 670 671 # Boolean selections. 672 else: 673 spin.select = boolean_select(current=spin.select, boolean=boolean)
674