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 the manipulation of the interatomic data structures in the relax data store."""
24
25
26 from copy import deepcopy
27 from re import search
28 import sys
29
30
31 from generic_fns import pipes
32 from generic_fns.mol_res_spin import Selection, return_spin
33 from relax_errors import RelaxError, RelaxInteratomError, RelaxNoInteratomError
34 from relax_io import write_data
35 from relax_warnings import RelaxNoSpinWarning
36
37
38 -def copy(pipe_from=None, pipe_to=None, verbose=True):
39 """Copy the interatomic data from one data pipe to another.
40
41 @keyword pipe_from: The data pipe to copy the interatomic data from. This defaults to the current data pipe.
42 @type pipe_from: str
43 @keyword pipe_to: The data pipe to copy the interatomic data to. This defaults to the current data pipe.
44 @type pipe_to: str
45 @keyword verbose: A flag which if True will cause info about each spin pair to be printed out.
46 @type verbose: bool
47 """
48
49
50 if pipe_from == None and pipe_to == None:
51 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None.")
52 elif pipe_from == None:
53 pipe_from = pipes.cdp_name()
54 elif pipe_to == None:
55 pipe_to = pipes.cdp_name()
56
57
58 pipes.test(pipe_from)
59 pipes.test(pipe_to)
60
61
62 if not exists_data(pipe_from):
63 return
64
65
66 if exists_data(pipe_to):
67 raise RelaxInteratomError
68
69
70 ids = []
71 for interatom in interatomic_loop(pipe=pipe_from):
72
73 new_interatom = create_interatom(spin_id1=interatom.spin_id1, spin_id2=interatom.spin_id2, pipe=pipe_to)
74
75
76 for name in dir(interatom):
77
78 if search('^_', name):
79 continue
80
81
82 if name in ['spin_id1', 'spin_id2']:
83 continue
84
85
86 if name in list(interatom.__class__.__dict__.keys()):
87 continue
88
89
90 obj = deepcopy(getattr(interatom, name))
91 setattr(new_interatom, name, obj)
92
93
94 ids.append([repr(interatom.spin_id1), repr(interatom.spin_id2)])
95
96
97 if verbose:
98 write_data(out=sys.stdout, headings=["Spin_ID_1", "Spin_ID_2"], data=ids)
99
100
102 """Create and return the interatomic data container for the two spins.
103
104 @keyword spin_id1: The spin ID string of the first atom.
105 @type spin_id1: str
106 @keyword spin_id2: The spin ID string of the first atom.
107 @type spin_id2: str
108 @keyword pipe: The data pipe to create the interatomic data container for. This defaults to the current data pipe if not supplied.
109 @type pipe: str or None
110 @return: The newly created interatomic data container.
111 @rtype: data.interatomic.InteratomContainer instance
112 """
113
114
115 if pipe == None:
116 pipe = pipes.cdp_name()
117
118
119 dp = pipes.get_pipe(pipe)
120
121
122 spin = return_spin(spin_id1, pipe)
123 if spin == None:
124 raise RelaxNoSpinWarning(spin_id1)
125 spin = return_spin(spin_id2, pipe)
126 if spin == None:
127 raise RelaxNoSpinWarning(spin_id2)
128
129
130 for i in range(len(dp.interatomic)):
131 if id_match(spin_id=spin_id1, interatom=dp.interatomic[i], pipe=pipe) and id_match(spin_id=spin_id2, interatom=dp.interatomic[i], pipe=pipe):
132 raise RelaxError("The spin pair %s and %s have already been added." % (spin_id1, spin_id2))
133
134
135 return dp.interatomic.add_item(spin_id1=spin_id1, spin_id2=spin_id2)
136
137
139 """Determine if any interatomic data exists.
140
141 @keyword pipe: The data pipe in which the interatomic data will be checked for.
142 @type pipe: str
143 @return: The answer to the question about the existence of data.
144 @rtype: bool
145 """
146
147
148 if pipe == None:
149 pipe = pipes.cdp_name()
150
151
152 pipes.test(pipe)
153
154
155 dp = pipes.get_pipe(pipe)
156
157
158 if dp.interatomic.is_empty():
159 return False
160
161
162 return True
163
164
165 -def id_match(spin_id=None, interatom=None, pipe=None):
166 """Test if the spin ID matches one of the two spins of the given container.
167
168 @keyword spin_id: The spin ID string of the first atom.
169 @type spin_id: str
170 @keyword interatom: The interatomic data container.
171 @type interatom: InteratomContainer instance
172 @keyword pipe: The data pipe containing the interatomic data container. Defaults to the current data pipe.
173 @type pipe: str or None
174 @return: True if the spin ID matches one of the two spins, False otherwise.
175 @rtype: bool
176 """
177
178
179 spin1 = return_spin(interatom.spin_id1, pipe=pipe)
180 spin2 = return_spin(interatom.spin_id2, pipe=pipe)
181
182
183 if spin1 == None or spin2 == None:
184 return False
185
186
187 if spin_id in spin1._spin_ids or spin_id in spin2._spin_ids:
188 return True
189
190
191 return False
192
193
194 -def interatomic_loop(selection1=None, selection2=None, pipe=None, selected=True):
195 """Generator function for looping over all the interatomic data containers.
196
197 @keyword selection1: The optional spin ID selection of the first atom.
198 @type selection1: str
199 @keyword selection2: The optional spin ID selection of the second atom.
200 @type selection2: str
201 @keyword pipe: The data pipe containing the spin. Defaults to the current data pipe.
202 @type pipe: str
203 @keyword selected: A flag which if True will only return selected interatomic data containers.
204 @type selected: bool
205 """
206
207
208 if pipe == None:
209 pipe = pipes.cdp_name()
210
211
212 dp = pipes.get_pipe(pipe)
213
214
215 select_obj = None
216 select_obj1 = None
217 select_obj2 = None
218 if selection1 and selection2:
219 select_obj1 = Selection(selection1)
220 select_obj2 = Selection(selection2)
221 elif selection1:
222 select_obj = Selection(selection1)
223 elif selection2:
224 select_obj = Selection(selection2)
225
226
227 for i in range(len(dp.interatomic)):
228
229 if selected and not dp.interatomic[i].select:
230 continue
231
232
233 interatom = dp.interatomic[i]
234 mol_index1, res_index1, spin_index1 = cdp.mol._spin_id_lookup[interatom.spin_id1]
235 mol_index2, res_index2, spin_index2 = cdp.mol._spin_id_lookup[interatom.spin_id2]
236 mol1 = cdp.mol[mol_index1]
237 res1 = cdp.mol[mol_index1].res[res_index1]
238 spin1 = cdp.mol[mol_index1].res[res_index1].spin[spin_index1]
239 mol2 = cdp.mol[mol_index2]
240 res2 = cdp.mol[mol_index2].res[res_index2]
241 spin2 = cdp.mol[mol_index2].res[res_index2].spin[spin_index2]
242
243
244 if select_obj:
245 if (mol1, res1, spin1) not in select_obj and (mol2, res2, spin2) not in select_obj:
246 continue
247 if select_obj1:
248 if not ((mol1, res1, spin1) in select_obj1 or (mol2, res2, spin2) in select_obj1) or not ((mol1, res1, spin1) in select_obj2 or (mol2, res2, spin2) in select_obj2):
249 continue
250
251
252 yield interatom
253
254
256 """Return the list of interatomic data containers for the two spins.
257
258 @keyword spin_id1: The spin ID string of the first atom.
259 @type spin_id1: str
260 @keyword spin_id2: The spin ID string of the second atom.
261 @type spin_id2: str
262 @keyword pipe: The data pipe holding the container. Defaults to the current data pipe.
263 @type pipe: str or None
264 @return: The matching interatomic data container, if it exists.
265 @rtype: data.interatomic.InteratomContainer instance or None
266 """
267
268
269 if spin_id1 == None:
270 raise RelaxError("The first spin ID must be supplied.")
271 if spin_id2 == None:
272 raise RelaxError("The second spin ID must be supplied.")
273
274
275 if pipe == None:
276 pipe = pipes.cdp_name()
277
278
279 dp = pipes.get_pipe(pipe)
280
281
282 for i in range(len(dp.interatomic)):
283 if id_match(spin_id=spin_id1, interatom=dp.interatomic[i], pipe=pipe) and id_match(spin_id=spin_id2, interatom=dp.interatomic[i], pipe=pipe):
284 return dp.interatomic[i]
285
286
287 return None
288
289
291 """Return the list of interatomic data containers for the given spin.
292
293 @keyword spin_id: The spin ID string.
294 @type spin_id: str
295 @keyword pipe: The data pipe holding the container. This defaults to the current data pipe.
296 @type pipe: str or None
297 @return: The list of matching interatomic data containers, if any exist.
298 @rtype: list of data.interatomic.InteratomContainer instances
299 """
300
301
302 if spin_id == None:
303 raise RelaxError("The spin ID must be supplied.")
304
305
306 if pipe == None:
307 pipe = pipes.cdp_name()
308
309
310 dp = pipes.get_pipe(pipe)
311
312
313 interatoms = []
314
315
316 for i in range(len(dp.interatomic)):
317 if id_match(spin_id=spin_id, interatom=dp.interatomic[i], pipe=pipe) or id_match(spin_id=spin_id, interatom=dp.interatomic[i], pipe=pipe):
318 interatoms.append(dp.interatomic[i])
319
320
321 return interatoms
322