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 J coupling data."""
24
25
26 import sys
27 from warnings import warn
28
29
30 from lib.check_types import is_float
31 from lib.errors import RelaxError, RelaxNoJError, RelaxNoSequenceError
32 from lib.io import extract_data, open_write_file, strip, write_data
33 from lib.warnings import RelaxWarning
34 from pipe_control import pipes
35 from pipe_control.interatomic import consistent_interatomic_data, create_interatom, interatomic_loop, return_interatom
36 from pipe_control.mol_res_spin import exists_mol_res_spin_data, return_spin
37 from pipe_control.pipes import check_pipe
38
39
77
78
79 -def copy(pipe_from=None, pipe_to=None):
80 """Copy the J coupling data from one data pipe to another.
81
82 @keyword pipe_from: The data pipe to copy the J coupling data from. This defaults to the current data pipe.
83 @type pipe_from: str
84 @keyword pipe_to: The data pipe to copy the J coupling data to. This defaults to the current data pipe.
85 @type pipe_to: str
86 """
87
88
89 if pipe_from == None and pipe_to == None:
90 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None.")
91 elif pipe_from == None:
92 pipe_from = pipes.cdp_name()
93 elif pipe_to == None:
94 pipe_to = pipes.cdp_name()
95
96
97 check_pipe_setup(pipe=pipe_from, sequence=True, j=True)
98 check_pipe_setup(pipe=pipe_to, sequence=True)
99
100
101 dp_from = pipes.get_pipe(pipe_from)
102 dp_to = pipes.get_pipe(pipe_to)
103
104
105 consistent_interatomic_data(pipe1=pipe_to, pipe2=pipe_from)
106
107
108 for i in range(len(dp_from.interatomic)):
109
110 interatom_from = dp_from.interatomic[i]
111 interatom_to = dp_to.interatomic[i]
112
113
114 if not hasattr(interatom_from, 'j_coupling') or not hasattr(interatom_from, 'j_coupling_err'):
115 continue
116
117
118 if hasattr(interatom_from, 'j_coupling'):
119 interatom_to.j_coupling = interatom_from.j_coupling
120 if hasattr(interatom_from, 'j_coupling_err'):
121 interatom_to.j_coupling_err = interatom_from.j_coupling_err
122
123
139
140
149
150
151 -def read(file=None, dir=None, file_data=None, spin_id1_col=None, spin_id2_col=None, data_col=None, error_col=None, sign_col=None, sep=None):
152 """Read the J coupling data from file.
153
154 @keyword file: The name of the file to open.
155 @type file: str
156 @keyword dir: The directory containing the file (defaults to the current directory if None).
157 @type dir: str or None
158 @keyword file_data: An alternative to opening a file, if the data already exists in the correct format. The format is a list of lists where the first index corresponds to the row and the second the column.
159 @type file_data: list of lists
160 @keyword spin_id1_col: The column containing the spin ID strings of the first spin.
161 @type spin_id1_col: int
162 @keyword spin_id2_col: The column containing the spin ID strings of the second spin.
163 @type spin_id2_col: int
164 @keyword data_col: The column containing the J coupling data in Hz.
165 @type data_col: int or None
166 @keyword error_col: The column containing the J coupling errors.
167 @type error_col: int or None
168 @keyword sign_col: The optional column containing the sign of the J coupling.
169 @type sign_col: int or None
170 @keyword sep: The column separator which, if None, defaults to whitespace.
171 @type sep: str or None
172 """
173
174
175 check_pipe_setup(sequence=True)
176
177
178 if data_col == None and error_col == None:
179 raise RelaxError("One of either the data or error column must be supplied.")
180
181
182 file_data = extract_data(file, dir, sep=sep)
183 file_data = strip(file_data, comments=True)
184
185
186 data = []
187 for line in file_data:
188
189 if spin_id1_col > len(line):
190 warn(RelaxWarning("The data %s is invalid, no first spin ID column can be found." % line))
191 continue
192 if spin_id2_col > len(line):
193 warn(RelaxWarning("The data %s is invalid, no second spin ID column can be found." % line))
194 continue
195 if data_col and data_col > len(line):
196 warn(RelaxWarning("The data %s is invalid, no data column can be found." % line))
197 continue
198 if error_col and error_col > len(line):
199 warn(RelaxWarning("The data %s is invalid, no error column can be found." % line))
200 continue
201 if sign_col and sign_col > len(line):
202 warn(RelaxWarning("The data %s is invalid, no sign column can be found." % line))
203 continue
204
205
206 spin_id1 = line[spin_id1_col-1]
207 spin_id2 = line[spin_id2_col-1]
208 value = None
209 if data_col:
210 value = line[data_col-1]
211 error = None
212 if error_col:
213 error = line[error_col-1]
214 sign = None
215 if sign_col:
216 sign = line[sign_col-1]
217
218
219 if spin_id1[0] in ["\"", "\'"]:
220 spin_id1 = eval(spin_id1)
221 if spin_id2[0] in ["\"", "\'"]:
222 spin_id2 = eval(spin_id2)
223
224
225 if value == 'None':
226 value = None
227 if value != None:
228 try:
229 value = float(value)
230 except ValueError:
231 warn(RelaxWarning("The J coupling value of the line %s is invalid." % line))
232 continue
233
234
235 if sign == 'None':
236 sign = None
237 if sign != None:
238 try:
239 sign = float(sign)
240 except ValueError:
241 warn(RelaxWarning("The J coupling sign of the line %s is invalid." % line))
242 continue
243 if sign not in [1.0, -1.0]:
244 warn(RelaxWarning("The J coupling sign of the line %s is invalid." % line))
245 continue
246
247
248 if error == 'None':
249 error = None
250 if error != None:
251 try:
252 error = float(error)
253 except ValueError:
254 warn(RelaxWarning("The error value of the line %s is invalid." % line))
255 continue
256
257
258 spin1 = return_spin(spin_id1)
259 spin2 = return_spin(spin_id2)
260
261
262 if not spin1:
263 warn(RelaxWarning("The spin ID '%s' cannot be found in the current data pipe, skipping the data %s." % (spin_id1, line)))
264 continue
265 if not spin2:
266 warn(RelaxWarning("The spin ID '%s' cannot be found in the current data pipe, skipping the data %s." % (spin_id2, line)))
267 continue
268
269
270 if error == 0.0:
271 raise RelaxError("An invalid error value of zero has been encountered.")
272
273
274 interatom = return_interatom(spin_id1, spin_id2)
275
276
277 if interatom == None:
278 interatom = create_interatom(spin_id1=spin_id1, spin_id2=spin_id2)
279
280
281 if data_col:
282
283 if sign != None:
284 value = value * sign
285
286
287 interatom.j_coupling = value
288
289
290 if error_col:
291 interatom.j_coupling_err = error
292
293
294 data.append([spin_id1, spin_id2])
295 if is_float(value):
296 data[-1].append("%20.15f" % value)
297 else:
298 data[-1].append("%20s" % value)
299 if is_float(error):
300 data[-1].append("%20.15f" % error)
301 else:
302 data[-1].append("%20s" % error)
303
304
305 if not len(data):
306 raise RelaxError("No J coupling data could be extracted.")
307
308
309 print("The following J coupling have been loaded into the relax data store:\n")
310 write_data(out=sys.stdout, headings=["Spin_ID1", "Spin_ID2", "Value", "Error"], data=data)
311
312
313 -def write(file=None, dir=None, force=False):
314 """Write the J coupling data to file.
315
316 @keyword file: The file name or object to write to.
317 @type file: str or file object
318 @keyword dir: The name of the directory to place the file into (defaults to the current directory).
319 @type dir: str
320 @keyword force: A flag which if True will cause any pre-existing file to be overwritten.
321 @type force: bool
322 """
323
324
325 check_pipe_setup(sequence=True, j=True)
326
327
328 file = open_write_file(file, dir, force)
329
330
331 data = []
332 for interatom in interatomic_loop():
333
334 if not interatom.select:
335 continue
336
337
338 if not hasattr(interatom, 'j_coupling'):
339 continue
340
341
342 data.append([])
343 data[-1].append(interatom.spin_id1)
344 data[-1].append(interatom.spin_id2)
345
346
347 data[-1].append(repr(interatom.j_coupling))
348
349
350 if hasattr(interatom, 'j_coupling_err'):
351 data[-1].append(repr(interatom.j_coupling_err))
352 else:
353 data[-1].append(repr(None))
354
355
356 write_data(out=file, headings=["Spin_ID1", "Spin_ID2", "J coupling", "J coupling"], data=data)
357