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 handling the molecule, residue, and spin sequence."""
24
25
26 from copy import deepcopy
27 from re import search
28 import sys
29
30
31 from lib.errors import RelaxError, RelaxDiffMolNumError, RelaxDiffResNumError, RelaxDiffSeqError, RelaxDiffSpinNumError, RelaxNoSequenceError, RelaxSequenceError
32 from lib.sequence import read_spin_data, write_spin_data
33 from pipe_control import pipes
34 from pipe_control.interatomic import return_interatom_list
35 from pipe_control.mol_res_spin import count_molecules, count_residues, count_spins, create_molecule, create_residue, create_spin, exists_mol_res_spin_data, generate_spin_id, return_molecule, return_residue, return_spin, set_spin_element, set_spin_isotope, spin_loop
36
37
38
40 """Attach a single proton to all heteronuclei."""
41
42
43 mol_names = []
44 res_nums = []
45 res_names = []
46 for spin, mol_name, res_num, res_name, spin_id in spin_loop(full_info=True, return_id=True):
47
48 if hasattr(spin, 'element') and spin.element == 'H':
49 continue
50
51
52 interatoms = return_interatom_list(spin_id)
53 proton_found = False
54 if len(interatoms):
55 for i in range(len(interatoms)):
56
57 spin_attached = return_spin(interatoms[i].spin_id1)
58 if id(spin_attached) == id(spin):
59 spin_attached = return_spin(interatoms[i].spin_id2)
60
61
62 if hasattr(spin_attached, 'element') and spin_attached.element == 'H' or spin.name == 'H':
63 proton_found = True
64 break
65
66
67 if proton_found:
68 continue
69
70
71 mol_names.append(mol_name)
72 res_nums.append(res_num)
73 res_names.append(res_name)
74
75
76 for i in range(len(mol_names)):
77
78 create_spin(spin_name='H', res_name=res_names[i], res_num=res_nums[i], mol_name=mol_names[i])
79
80
81 set_spin_element(spin_id='@H', element='H')
82 set_spin_isotope(spin_id='@H', isotope='1H')
83
84
85 -def copy(pipe_from=None, pipe_to=None, preserve_select=False, empty=True, verbose=True):
86 """Copy the molecule, residue, and spin sequence data from one data pipe to another.
87
88 @keyword pipe_from: The data pipe to copy the sequence data from. This defaults to the current data pipe.
89 @type pipe_from: str
90 @keyword pipe_to: The data pipe to copy the sequence data to. This defaults to the current data pipe.
91 @type pipe_to: str
92 @keyword preserve_select: A flag which if True will cause spin selections to be preserved.
93 @type preserve_select: bool
94 @keyword empty: A flag which if True will create a molecule, residue, and spin sequence in the target pipe lacking all of the spin data of the source pipe. If False, then the spin data will also be copied.
95 @keyword verbose: A flag which if True will cause info about each spin to be printed out as the sequence is generated.
96 @type verbose: bool
97 """
98
99
100 if pipe_from == None and pipe_to == None:
101 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None.")
102 elif pipe_from == None:
103 pipe_from = pipes.cdp_name()
104 elif pipe_to == None:
105 pipe_to = pipes.cdp_name()
106
107
108 pipes.test(pipe_from)
109 pipes.test(pipe_to)
110
111
112 if not exists_mol_res_spin_data(pipe_from):
113 raise RelaxNoSequenceError
114
115
116 if exists_mol_res_spin_data(pipe_to):
117 raise RelaxSequenceError
118
119
120 for spin, mol_name, res_num, res_name in spin_loop(pipe=pipe_from, full_info=True):
121
122 new_spin = create_spin(spin_num=spin.num, spin_name=spin.name, res_num=res_num, res_name=res_name, mol_name=mol_name, pipe=pipe_to)
123
124
125 if preserve_select:
126 new_spin.select = spin.select
127 else:
128 select = True
129
130
131 if not empty:
132
133 for name in dir(spin):
134
135 if search('^_', name):
136 continue
137
138
139
140
141
142
143 if name in list(spin.__class__.__dict__.keys()):
144 continue
145
146
147 obj = deepcopy(getattr(spin, name))
148 setattr(new_spin, name, obj)
149
150
151 if verbose:
152 display(mol_name_flag=True, res_num_flag=True, res_name_flag=True, spin_num_flag=True, spin_name_flag=True)
153
154
206
207
208 -def display(sep=None, mol_name_flag=False, res_num_flag=False, res_name_flag=False, spin_num_flag=False, spin_name_flag=False):
209 """Display the molecule, residue, and/or spin sequence data.
210
211 This calls the write() function to do most of the work.
212
213
214 @keyword sep: The column seperator which, if None, defaults to whitespace.
215 @type sep: str or None
216 @keyword mol_name_flag: A flag which if True will cause the molecule name column to be
217 written.
218 @type mol_name_flag: bool
219 @keyword res_num_flag: A flag which if True will cause the residue number column to be
220 written.
221 @type res_num_flag: bool
222 @keyword res_name_flag: A flag which if True will cause the residue name column to be
223 written.
224 @type res_name_flag: bool
225 @keyword spin_name_flag: A flag which if True will cause the spin name column to be written.
226 @type spin_name_flag: bool
227 @keyword spin_num_flag: A flag which if True will cause the spin number column to be
228 written.
229 @type spin_num_flag: bool
230 @param mol_name_flag: The column to contain the molecule name information.
231 """
232
233
234 if not count_spins():
235 raise RelaxNoSequenceError
236
237
238 write(file=sys.stdout, sep=sep, mol_name_flag=mol_name_flag, res_num_flag=res_num_flag, res_name_flag=res_name_flag, spin_num_flag=spin_num_flag, spin_name_flag=spin_name_flag)
239
240
241 -def generate(mol_name=None, res_num=None, res_name=None, spin_num=None, spin_name=None, pipe=None, select=True, verbose=True):
242 """Generate the sequence item-by-item by adding a single molecule/residue/spin container as necessary.
243
244 @keyword mol_name: The molecule name.
245 @type mol_name: str or None
246 @keyword res_num: The residue number.
247 @type res_num: int or None
248 @keyword res_name: The residue name.
249 @type res_name: str or None
250 @keyword spin_num: The spin number.
251 @type spin_num: int or None
252 @keyword spin_name: The spin name.
253 @type spin_name: str or None
254 @keyword pipe: The data pipe in which to generate the sequence. This defaults to the current data pipe.
255 @type pipe: str
256 @keyword select: The spin selection flag.
257 @type select: bool
258 @keyword verbose: A flag which if True will cause info about each spin to be printed out as the sequence is generated.
259 @type verbose: bool
260 """
261
262
263 if pipe == None:
264 pipe = pipes.cdp_name()
265
266
267 if not return_molecule(generate_spin_id(mol_name=mol_name), pipe=pipe):
268 create_molecule(mol_name=mol_name, pipe=pipe)
269
270
271 curr_res = return_residue(generate_spin_id(mol_name=mol_name, res_num=res_num, res_name=res_name), pipe=pipe)
272 if not curr_res or ((res_num != None and curr_res.num != res_num) or (res_name != None and curr_res.name != res_name)):
273 create_residue(mol_name=mol_name, res_num=res_num, res_name=res_name, pipe=pipe)
274
275
276 curr_spin = return_spin(generate_spin_id(mol_name=mol_name, res_num=res_num, res_name=res_name, spin_num=spin_num, spin_name=spin_name), pipe=pipe)
277 if not curr_spin or ((spin_num != None and curr_spin.num != spin_num) or (spin_name != None and curr_spin.name != spin_name)):
278
279 curr_spin = create_spin(mol_name=mol_name, res_num=res_num, res_name=res_name, spin_num=spin_num, spin_name=spin_name, pipe=pipe)
280
281
282 curr_spin.select = select
283
284
285 -def 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):
286 """Read the molecule, residue, and/or spin sequence data from file.
287
288 @param file: The name of the file to open.
289 @type file: str
290 @param dir: The directory containing the file (defaults to the current directory if
291 None).
292 @type dir: str or None
293 @keyword file_data: An alternative to opening a file, if the data already exists in the
294 correct format. The format is a list of lists where the first index
295 corresponds to the row and the second the column.
296 @type file_data: list of lists
297 @keyword spin_id_col: The column containing the spin ID strings. If supplied, the
298 mol_name_col, res_name_col, res_num_col, spin_name_col, and spin_num_col
299 arguments must be none.
300 @type spin_id_col: int or None
301 @keyword mol_name_col: The column containing the molecule name information. If supplied,
302 spin_id_col must be None.
303 @type mol_name_col: int or None
304 @keyword res_name_col: The column containing the residue name information. If supplied,
305 spin_id_col must be None.
306 @type res_name_col: int or None
307 @keyword res_num_col: The column containing the residue number information. If supplied,
308 spin_id_col must be None.
309 @type res_num_col: int or None
310 @keyword spin_name_col: The column containing the spin name information. If supplied,
311 spin_id_col must be None.
312 @type spin_name_col: int or None
313 @keyword spin_num_col: The column containing the spin number information. If supplied,
314 spin_id_col must be None.
315 @type spin_num_col: int or None
316 @keyword sep: The column separator which, if None, defaults to whitespace.
317 @type sep: str or None
318 @keyword spin_id: The spin ID string used to restrict data loading to a subset of all
319 spins.
320 @type spin_id: None or str
321 """
322
323
324 pipes.test()
325
326
327 if exists_mol_res_spin_data():
328 raise RelaxSequenceError
329
330
331 mol_names = []
332 res_nums = []
333 res_names = []
334 spin_nums = []
335 spin_names = []
336
337
338 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):
339
340 generate(mol_name=mol_name, res_num=res_num, res_name=res_name, spin_num=spin_num, spin_name=spin_name)
341
342
343 mol_names.append(mol_name)
344 res_nums.append(res_num)
345 res_names.append(res_name)
346 spin_nums.append(spin_num)
347 spin_names.append(spin_name)
348
349
350 if not len(spin_names):
351 raise RelaxError("No sequence data could be loaded.")
352
353
354 write_spin_data(sys.stdout, mol_names=mol_names, res_nums=res_nums, res_names=res_names, spin_nums=spin_nums, spin_names=spin_names)
355
356
358 """Return a list of all proton spin containers attached to the given spin.
359
360 @keyword spin_id: The spin ID string.
361 @type spin_id: str
362 @return: The list of proton spin containers attached to the given spin.
363 @rtype: list of SpinContainer instances
364 """
365
366
367 spin_list = []
368
369
370 interatoms = return_interatom_list(spin_id)
371
372
373 if not len(interatoms):
374 return spin_list
375
376
377 for i in range(len(interatoms)):
378
379 if interatoms[i].spin_id1 == spin_id:
380 attached = return_spin(interatoms[i].spin_id2)
381 else:
382 attached = return_spin(interatoms[i].spin_id1)
383
384
385 if (hasattr(attached, 'element') and attached.element == 'H') or attached.name == 'H':
386 spin_list.append(attached)
387
388
389 return spin_list
390
391
392 -def write(file, dir=None, sep=None, mol_name_flag=True, res_num_flag=True, res_name_flag=True, spin_num_flag=True, spin_name_flag=True, force=False):
393 """Write the molecule, residue, and/or sequence data.
394
395 This calls the lib.io.write_spin_data() function to do most of the work.
396
397
398 @param file: The name of the file to write the data to.
399 @type file: str
400 @keyword dir: The directory to contain the file (defaults to the current directory if None).
401 @type dir: str or None
402 @keyword sep: The column seperator which, if None, defaults to whitespace.
403 @type sep: str or None
404 @keyword mol_name_flag: A flag which if True will cause the molecule name column to be written.
405 @type mol_name_flag: bool
406 @keyword res_num_flag: A flag which if True will cause the residue number column to be written.
407 @type res_num_flag: bool
408 @keyword res_name_flag: A flag which if True will cause the residue name column to be written.
409 @type res_name_flag: bool
410 @keyword spin_name_flag: A flag which if True will cause the spin name column to be written.
411 @type spin_name_flag: bool
412 @keyword spin_num_flag: A flag which if True will cause the spin number column to be written.
413 @keyword force: A flag which if True will cause an existing file to be overwritten.
414 @type force: bin
415 """
416
417
418 if not count_spins():
419 raise RelaxNoSequenceError
420
421
422 mol_names = []
423 res_nums = []
424 res_names = []
425 spin_nums = []
426 spin_names = []
427
428
429 for spin, mol_name, res_num, res_name in spin_loop(full_info=True):
430 mol_names.append(mol_name)
431 res_nums.append(res_num)
432 res_names.append(res_name)
433 spin_nums.append(spin.num)
434 spin_names.append(spin.name)
435
436
437 if not mol_name_flag:
438 mol_names = None
439 if not res_num_flag:
440 res_nums = None
441 if not res_name_flag:
442 res_names = None
443 if not spin_num_flag:
444 spin_nums = None
445 if not spin_name_flag:
446 spin_names = None
447
448
449 write_spin_data(file=file, dir=dir, sep=sep, mol_names=mol_names, res_nums=res_nums, res_names=res_names, spin_nums=spin_nums, spin_names=spin_names, force=force)
450