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