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 parameter and constant values."""
24
25
26 from numpy import ndarray
27 import sys
28
29
30 from generic_fns import minimise, pipes
31 from generic_fns.mol_res_spin import exists_mol_res_spin_data, generate_spin_id_unique, return_spin, spin_loop
32 from generic_fns.result_files import add_result_file
33 from relax_errors import RelaxError, RelaxNoSequenceError, RelaxNoSpinError, RelaxParamSetError, RelaxValueError
34 from relax_io import get_file_path, open_write_file, read_spin_data, write_spin_data
35 import specific_fns
36 from status import Status; status = Status()
37
38
39 -def copy(pipe_from=None, pipe_to=None, param=None):
40 """Copy spin specific data values from pipe_from to pipe_to.
41
42 @param pipe_from: The data pipe to copy the value from. This defaults to the current data
43 pipe.
44 @type pipe_from: str
45 @param pipe_to: The data pipe to copy the value to. This defaults to the current data pipe.
46 @type pipe_to: str
47 @param param: The name of the parameter to copy the values of.
48 @type param: str
49 """
50
51
52 if pipe_from == None:
53 pipe_from = pipes.cdp_name()
54 if pipe_to == None:
55 pipe_to = pipes.cdp_name()
56
57
58 pipes.test(pipe_to)
59
60
61 if not exists_mol_res_spin_data(pipe_from):
62 raise RelaxNoSequenceError(pipe_from)
63
64
65 if not exists_mol_res_spin_data(pipe_to):
66 raise RelaxNoSequenceError(pipe_to)
67
68
69 return_value = specific_fns.setup.get_specific_fn('return_value', pipes.get_type(pipe_from))
70
71
72 for spin in spin_loop(pipe_to):
73
74 value, error = return_value(spin, param)
75
76
77 if value != None or error != None:
78 raise RelaxValueError(param, pipe_to)
79
80
81 for spin, spin_id in spin_loop(pipe_from, return_id=True):
82
83 value, error = return_value(spin, param)
84
85
86 spin_to = return_spin(spin_id, pipe_to)
87
88
89 set(spin_id=spin_to, value=value, error=error, param=param)
90
91
92 minimise.reset_min_stats(pipe_to)
93
94
95 -def display(param=None, scaling=1.0):
96 """Display spin specific data values.
97
98 @keyword param: The name of the parameter to display.
99 @type param: str
100 @keyword scaling: The value to scale the parameter by.
101 @type scaling: float
102 """
103
104
105 pipes.test()
106
107
108 if not exists_mol_res_spin_data():
109 raise RelaxNoSequenceError
110
111
112 write_data(param=param, file=sys.stdout, scaling=scaling)
113
114
149
150
152 """Function for sorting and partitioning the parameters and their values.
153
154 The two major partitions are the tensor parameters and the spin specific parameters.
155
156 @param val: The parameter values.
157 @type val: None, number, or list of numbers
158 @param param: The parameter names.
159 @type param: None, str, or list of str
160 @return: A tuple, of length 4, of lists. The first and second elements are the lists of
161 spin specific parameters and values respectively. The third and forth elements
162 are the lists of all other parameters and their values.
163 @rtype: tuple of 4 lists
164 """
165
166
167 is_spin_param = specific_fns.setup.get_specific_fn('is_spin_param', pipes.get_type())
168
169
170 spin_params = []
171 spin_values = []
172 other_params = []
173 other_values = []
174
175
176 if isinstance(param, str):
177
178 if is_spin_param(param):
179 params = spin_params
180 values = spin_values
181
182
183 else:
184 params = other_params
185 values = other_values
186
187
188 if isinstance(val, list) or isinstance(val, ndarray):
189
190 for i in range(len(val)):
191 params.append(param)
192
193
194 values = val
195
196
197 else:
198
199 params.append(param)
200
201
202 values.append(val)
203
204
205 elif isinstance(param, list):
206
207 for i in range(len(param)):
208
209 if is_spin_param(param[i]):
210 params = spin_params
211 values = spin_values
212
213
214 else:
215 params = other_params
216 values = other_values
217
218
219 params.append(param[i])
220
221
222 if isinstance(val, list) or isinstance(val, ndarray):
223 values.append(val[i])
224 else:
225 values.append(val)
226
227
228
229 return spin_params, spin_values, other_params, other_values
230
231
232 -def read(param=None, scaling=1.0, 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, data_col=None, error_col=None, sep=None, spin_id=None):
233 """Read spin specific data values from a file.
234
235 @keyword param: The name of the parameter to read.
236 @type param: str
237 @keyword scaling: A scaling factor by which all read values are multiplied by.
238 @type scaling: float
239 @keyword file: The name of the file to open.
240 @type file: str
241 @keyword dir: The directory containing the file (defaults to the current directory if None).
242 @type dir: str or None
243 @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.
244 @type file_data: list of lists
245 @keyword spin_id_col: The column containing the spin ID strings. If supplied, the mol_name_col, res_name_col, res_num_col, spin_name_col, and spin_num_col arguments must be none.
246 @type spin_id_col: int or None
247 @keyword mol_name_col: The column containing the molecule name information. If supplied, spin_id_col must be None.
248 @type mol_name_col: int or None
249 @keyword res_name_col: The column containing the residue name information. If supplied, spin_id_col must be None.
250 @type res_name_col: int or None
251 @keyword res_num_col: The column containing the residue number information. If supplied, spin_id_col must be None.
252 @type res_num_col: int or None
253 @keyword spin_name_col: The column containing the spin name information. If supplied, spin_id_col must be None.
254 @type spin_name_col: int or None
255 @keyword spin_num_col: The column containing the spin number information. If supplied, spin_id_col must be None.
256 @type spin_num_col: int or None
257 @keyword data_col: The column containing the RDC data in Hz.
258 @type data_col: int or None
259 @keyword error_col: The column containing the RDC errors.
260 @type error_col: int or None
261 @keyword sep: The column separator which, if None, defaults to whitespace.
262 @type sep: str or None
263 @keyword spin_id: The spin ID string.
264 @type spin_id: None or str
265 """
266
267
268 pipes.test()
269
270
271 if not exists_mol_res_spin_data():
272 raise RelaxNoSequenceError
273
274
275 if minimise.return_data_name(param):
276
277 min_stat = True
278
279
280 return_value = minimise.return_value
281
282
283 set_fn = minimise.set
284
285
286 else:
287
288 min_stat = False
289
290
291 return_value = specific_fns.setup.get_specific_fn('return_value', pipes.get_type())
292
293
294 set_fn = set
295
296
297 for spin in spin_loop():
298
299 if not spin.select:
300 continue
301
302
303 value, error = return_value(spin, param)
304
305
306 if value != None or error != None:
307 raise RelaxValueError(param)
308
309
310 mol_names = []
311 res_nums = []
312 res_names = []
313 spin_nums = []
314 spin_names = []
315 values = []
316 errors = []
317 for data 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, data_col=data_col, error_col=error_col, sep=sep, spin_id=spin_id):
318
319 if data_col and error_col:
320 mol_name, res_num, res_name, spin_num, spin_name, value, error = data
321 elif data_col:
322 mol_name, res_num, res_name, spin_num, spin_name, value = data
323 error = None
324 else:
325 mol_name, res_num, res_name, spin_num, spin_name, error = data
326 value = None
327
328
329 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)
330 set_fn(val=value, error=error, param=param, spin_id=id)
331
332
333 mol_names.append(mol_name)
334 res_nums.append(res_num)
335 res_names.append(res_name)
336 spin_nums.append(spin_num)
337 spin_names.append(spin_name)
338 values.append(value)
339 errors.append(error)
340
341
342 write_spin_data(file=sys.stdout, mol_names=mol_names, res_nums=res_nums, res_names=res_names, spin_nums=spin_nums, spin_names=spin_names, data=values, data_name=param, error=errors, error_name='%s_error'%param)
343
344
345 if not min_stat:
346 minimise.reset_min_stats()
347
348
349 -def set(val=None, param=None, error=None, pipe=None, spin_id=None, force=True, reset=True):
350 """Set global or spin specific data values.
351
352 @keyword val: The parameter values.
353 @type val: None or list
354 @keyword param: The parameter names.
355 @type param: None, str, or list of str
356 @keyword error: The parameter errors.
357 @type error: None, number, or list of numbers
358 @keyword pipe: The data pipe the values should be placed in.
359 @type pipe: None or str
360 @keyword spin_id: The spin identification string.
361 @type spin_id: str
362 @keyword force: A flag forcing the overwriting of current values.
363 @type force: bool
364 @keyword reset: A flag which if True will cause all minimisation statistics to be reset.
365 @type reset: bool
366 """
367
368
369 if pipe:
370 orig_pipe = pipes.cdp_name()
371 pipes.switch(pipe)
372
373
374 pipes.test()
375
376
377 default_value = specific_fns.setup.get_specific_fn('default_value', pipes.get_type())
378 get_param_names = specific_fns.setup.get_specific_fn('get_param_names', pipes.get_type())
379 return_data_name = specific_fns.setup.get_specific_fn('return_data_name', pipes.get_type())
380 set_param_values = specific_fns.setup.get_specific_fn('set_param_values', pipes.get_type())
381
382
383 if isinstance(val, ndarray):
384 val = val.tolist()
385
386
387 if (isinstance(val, float) or isinstance(val, int)) and param == None:
388 raise RelaxError("The combination of a single value '%s' without specifying the parameter name is invalid." % val)
389 if isinstance(val, list) and isinstance(param, str):
390 raise RelaxError("Invalid combination: When multiple values '%s' are specified, either no parameters or a list of parameters must by supplied rather than the single parameter '%s'." % (val, param))
391
392
393 if isinstance(val, list) and isinstance(param, list) and len(val) != len(param):
394 raise RelaxError("Both the value array and parameter array must be of equal length.")
395
396
397 if param == None:
398 param = get_param_names()
399
400
401 if not isinstance(param, list):
402 param = [param]
403
404
405 if val != None and not isinstance(val, list):
406 val = [val] * len(param)
407
408
409 if val == None:
410
411 val = []
412 for i in range(len(param)):
413 val.append(default_value(return_data_name(param[i])))
414
415
416 if val[-1] == None:
417 raise RelaxParamSetError(param[i])
418
419
420 set_param_values(param=param, value=val, spin_id=spin_id, force=force)
421
422
423 if reset:
424 minimise.reset_min_stats()
425
426
427 if pipe:
428 pipes.switch(orig_pipe)
429
430
431 -def write(param=None, file=None, dir=None, scaling=1.0, return_value=None, return_data_desc=None, comment=None, bc=False, force=False):
432 """Write data to a file.
433
434 @keyword param: The name of the parameter to write to file.
435 @type param: str
436 @keyword file: The file to write the data to.
437 @type file: str
438 @keyword dir: The name of the directory to place the file into (defaults to the current directory).
439 @type dir: str
440 @keyword scaling: The value to scale the parameter by.
441 @type scaling: float
442 @keyword return_value: An optional function which if supplied will override the default value returning function.
443 @type return_value: None or func
444 @keyword return_data_desc: An optional function which if supplied will override the default parameter description returning function.
445 @type return_data_desc: None or func
446 @keyword comment: Text which will be added to the start of the file as comments. All lines will be prefixed by '# '.
447 @type comment: str
448 @keyword bc: A flag which if True will cause the back calculated values to be written.
449 @type bc: bool
450 @keyword force: A flag which if True will cause any pre-existing file to be overwritten.
451 @type force: bool
452 """
453
454
455 pipes.test()
456
457
458 if not exists_mol_res_spin_data():
459 raise RelaxNoSequenceError
460
461
462 file_path = get_file_path(file, dir)
463 file = open_write_file(file, dir, force)
464
465
466 write_data(param=param, file=file, scaling=scaling, return_value=return_value, return_data_desc=return_data_desc, comment=comment, bc=bc)
467
468
469 file.close()
470
471
472 add_result_file(type='text', label='Text', file=file_path)
473
474
475 -def write_data(param=None, file=None, scaling=1.0, bc=False, return_value=None, return_data_desc=None, comment=None):
476 """The function which actually writes the data.
477
478 @keyword param: The parameter to write.
479 @type param: str
480 @keyword file: The file to write the data to.
481 @type file: str
482 @keyword scaling: The value to scale the parameter by.
483 @type scaling: float
484 @keyword bc: A flag which if True will cause the back calculated values to be written.
485 @type bc: bool
486 @keyword return_value: An optional function which if supplied will override the default value returning function.
487 @type return_value: None or func
488 @keyword return_data_desc: An optional function which if supplied will override the default parameter description returning function.
489 @type return_data_desc: None or func
490 @keyword comment: Text which will be added to the start of the file as comments. All lines will be prefixed by '# '.
491 @type comment: str
492 """
493
494
495 if not return_value:
496 return_value = specific_fns.setup.get_specific_fn('return_value', pipes.get_type())
497 if not return_data_desc:
498 return_data_desc = specific_fns.setup.get_specific_fn('return_data_desc', pipes.get_type())
499
500
501 format = "%-30s%-30s"
502
503
504 mol_names = []
505 res_nums = []
506 res_names = []
507 spin_nums = []
508 spin_names = []
509 values = []
510 errors = []
511
512
513 desc = return_data_desc(param)
514 if desc:
515 file.write("# Parameter description: %s.\n" % desc)
516 file.write("#\n")
517
518
519 if comment:
520
521 lines = comment.splitlines()
522
523
524 for line in lines:
525 file.write("# %s\n" % line)
526 file.write("#\n")
527
528
529 for spin, mol_name, res_num, res_name in spin_loop(full_info=True):
530
531 value, error = return_value(spin, param, bc=bc)
532
533
534 mol_names.append(mol_name)
535 res_nums.append(res_num)
536 res_names.append(res_name)
537 spin_nums.append(spin.num)
538 spin_names.append(spin.name)
539
540
541 if value != None:
542 value *= scaling
543 if error != None:
544 error *= scaling
545 values.append(value)
546 errors.append(error)
547
548
549 write_spin_data(file, mol_names=mol_names, res_nums=res_nums, res_names=res_names, spin_nums=spin_nums, spin_names=spin_names, data=values, data_name='value', error=errors, error_name='error')
550