1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for selecting and deselecting spins."""
24
25
26 from warnings import warn
27
28
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
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
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
83 return state
84
85
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
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
114 return state
115
116
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
151 pipes.test()
152
153
154 if not exists_mol_res_spin_data():
155 raise RelaxNoSequenceError
156
157
158 if change_all:
159
160 for interatom in interatomic_loop(skip_desel=False):
161 interatom.select = True
162
163
164 for interatom in interatomic_loop(selection1=spin_id1, selection2=spin_id2, skip_desel=False):
165
166 if change_all:
167 interatom.select = False
168
169
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
224 pipes.test()
225
226
227 if not exists_mol_res_spin_data():
228 raise RelaxNoSequenceError
229
230
231 if change_all:
232 for spin in spin_loop():
233 spin.select = True
234
235
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
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
243 if spin == None:
244 warn(RelaxNoSpinWarning(id))
245 continue
246
247
248 if change_all:
249 spin.select = False
250
251
252 else:
253 spin.select = boolean_deselect(current=spin.select, boolean=boolean)
254
255
256 if not spin.select:
257 ids.append(id)
258
259
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
287 pipes.test()
288
289
290 if not exists_mol_res_spin_data():
291 raise RelaxNoSequenceError
292
293
294 if change_all:
295 for spin in spin_loop():
296 spin.select = True
297
298
299 for spin in spin_loop(spin_id):
300
301 if change_all:
302 spin.select = False
303
304
305 else:
306 spin.select = boolean_deselect(current=spin.select, boolean=boolean)
307
308
310 """Query if the molecule is selected.
311
312 @keyword selection: The molecule ID string.
313 @type selection: str
314 """
315
316
317 select = False
318 for spin in spin_loop(selection):
319 if spin.select:
320 select = True
321 break
322
323
324 return select
325
326
328 """Query if the residue is selected.
329
330 @keyword selection: The residue ID string.
331 @type selection: str
332 """
333
334
335 select = False
336 for spin in spin_loop(selection):
337 if spin.select:
338 select = True
339 break
340
341
342 return select
343
344
346 """Query if the spin is selected.
347
348 @keyword selection: The molecule ID string.
349 @type selection: str
350 """
351
352
353 spin = return_spin(selection)
354
355
356 return spin.select
357
358
381
382
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
413 pipes.test()
414
415
416 if not hasattr(cdp, 'domain') or domain_id not in cdp.domain:
417 raise RelaxNoDomainError(domain_id)
418
419
420 domain = Selection(cdp.domain[domain_id])
421
422
423 for spin, mol_name, res_num, res_name in spin_loop(full_info=True):
424
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
429 elif change_all:
430 spin.select = False
431
432
433 for interatom in interatomic_loop():
434
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
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
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
463 pipes.test()
464
465
466 if not exists_mol_res_spin_data():
467 raise RelaxNoSequenceError
468
469
470 if change_all:
471
472 for interatom in interatomic_loop(skip_desel=False):
473 interatom.select = False
474
475
476 for interatom in interatomic_loop(selection1=spin_id1, selection2=spin_id2, skip_desel=False):
477
478 if change_all:
479 interatom.select = True
480
481
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
536 pipes.test()
537
538
539 if not exists_mol_res_spin_data():
540 raise RelaxNoSequenceError
541
542
543 if change_all:
544
545 for spin in spin_loop():
546 spin.select = False
547
548
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
552 spin = return_spin(id)
553
554
555 if spin == None:
556 warn(RelaxNoSpinWarning(id))
557 continue
558
559
560 if change_all:
561 spin.select = True
562
563
564 else:
565 spin.select = boolean_select(current=spin.select, boolean=boolean)
566
567
568 if spin.select:
569 ids.append(id)
570
571
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
599 pipes.test()
600
601
602 if not exists_mol_res_spin_data():
603 raise RelaxNoSequenceError
604
605
606 if change_all:
607
608 for spin in spin_loop():
609 spin.select = False
610
611
612 for spin in spin_loop(spin_id):
613
614 if change_all:
615 spin.select = True
616
617
618 else:
619 spin.select = boolean_select(current=spin.select, boolean=boolean)
620