1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module containing functions for the handling of alignment tensors."""
24
25
26 from copy import deepcopy
27 from math import pi, sqrt
28 from numpy import arccos, dot, float64, linalg, zeros
29 from numpy.linalg import norm
30 from re import search
31 import sys
32 from warnings import warn
33
34
35 from data_store.align_tensor import AlignTensorList
36 from lib.alignment.alignment_tensor import calc_chi_tensor, kappa
37 from lib.errors import RelaxError, RelaxNoTensorError, RelaxStrError, RelaxTensorError, RelaxUnknownParamCombError, RelaxUnknownParamError
38 from lib.io import write_data
39 from lib.warnings import RelaxWarning
40 import pipe_control
41 from pipe_control import pipes
42 from pipe_control.angles import wrap_angles
43
44
46 """Function for determining if alignment data exists in the current data pipe.
47
48 @param tensor: The alignment tensor identification string.
49 @type tensor: str
50 @param pipe: The data pipe to search for data in.
51 @type pipe: str
52 @return: The answer to the question.
53 @rtype: bool
54 """
55
56
57 if pipe == None:
58 pipe = pipes.cdp_name()
59
60
61 pipe = pipes.get_pipe(pipe)
62
63
64 if hasattr(pipe, 'align_tensors'):
65 for data in pipe.align_tensors:
66 if data.name == tensor:
67 return True
68 else:
69 return False
70
71
73 """Determine if all alignment tensors are fixed.
74
75 @return: True if all tensors are fixed, False otherwise.
76 @rtype: bool
77 """
78
79
80 for i in range(len(cdp.align_tensors)):
81
82 if not cdp.align_tensors[i].fixed:
83 return False
84
85
86 return True
87
88
89 -def copy(tensor_from=None, pipe_from=None, tensor_to=None, pipe_to=None):
90 """Function for copying alignment tensor data from one data pipe to another.
91
92 @param tensor_from: The identification string of the alignment tensor to copy the data from.
93 @type tensor_from: str
94 @param pipe_from: The data pipe to copy the alignment tensor data from. This defaults to the current data pipe.
95 @type pipe_from: str
96 @param tensor_to: The identification string of the alignment tensor to copy the data to. If set to None, then the ID string will be set to the value of tensor_from.
97 @type tensor_to: str or None
98 @param pipe_to: The data pipe to copy the alignment tensor data to. This defaults to the current data pipe.
99 @type pipe_to: str
100 """
101
102
103 if tensor_from == tensor_to and pipe_from == None and pipe_to == None:
104 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None when the tensor names are the same.")
105 elif pipe_from == None:
106 pipe_from = pipes.cdp_name()
107 elif pipe_to == None:
108 pipe_to = pipes.cdp_name()
109
110
111 if tensor_to == None:
112 tensor_to = tensor_from
113
114
115 pipes.test(pipe_from)
116 pipes.test(pipe_to)
117
118
119 dp_from = pipes.get_pipe(pipe_from)
120 dp_to = pipes.get_pipe(pipe_to)
121
122
123 if not align_data_exists(tensor_from, pipe_from):
124 raise RelaxNoTensorError('alignment')
125
126
127 if align_data_exists(tensor_to, pipe_to):
128 raise RelaxTensorError('alignment')
129
130
131 if not hasattr(dp_to, 'align_tensors'):
132 dp_to.align_tensors = AlignTensorList()
133
134
135 if tensor_to not in dp_to.align_tensors.names():
136 dp_to.align_tensors.add_item(tensor_to)
137
138
139 index_from = get_tensor_index(tensor=tensor_from, pipe=pipe_from)
140 index_to = get_tensor_index(tensor=tensor_to, pipe=pipe_to)
141
142
143 if index_to == None:
144 dp_to.align_tensors.append(deepcopy(dp_from.align_tensors[index_from]))
145 index_to = len(dp_to.align_tensors) - 1
146 else:
147 dp_to.align_tensors[index_to] = deepcopy(dp_from.align_tensors[index_from])
148
149
150 dp_to.align_tensors[index_to].set('name', tensor_to)
151
152
153 align_id = dp_from.align_tensors[index_from].align_id
154 if not hasattr(dp_to, 'align_ids'):
155 dp_to.align_ids = []
156 if align_id not in dp_to.align_ids:
157 dp_to.align_ids.append(align_id)
158
159
161 """Function for returning a list of names of data structures associated with the sequence."""
162
163 names = [ 'align_params' ]
164
165 return names
166
167
169 """Return the default values for the alignment tensor parameters.
170
171 @param param: The name of the parameter.
172 @type param: str
173 @return: The default value, which for all parameters is set to zero.
174 @rtype: float
175 """
176
177
178 return 0.0
179
180
181 __default_value_prompt_doc__ = """
182 Alignment tensor parameter default values
183 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184
185 ________________________________________________________________________
186 | | | |
187 | Data type | Object name | Value |
188 |________________________|____________________|________________________|
189 | | | |
190 | Axx | 'Axx' | 0.0 |
191 | | | |
192 | Ayy | 'Ayy' | 0.0 |
193 | | | |
194 | Azz | 'Azz' | 0.0 |
195 | | | |
196 | Axxyy | 'Axxyy' | 0.0 |
197 | | | |
198 | Axy | 'Axy' | 0.0 |
199 | | | |
200 | Axz | 'Axz' | 0.0 |
201 | | | |
202 | Ayz | 'Ayz' | 0.0 |
203 | | | |
204 | alpha | 'alpha' | 0.0 |
205 | | | |
206 | beta | 'beta' | 0.0 |
207 | | | |
208 | gamma | 'gamma' | 0.0 |
209 |________________________|____________________|________________________|
210
211 """
212
213
215 """Function for deleting alignment tensor data.
216
217 @param tensor: The alignment tensor identification string.
218 @type tensor: str or None
219 """
220
221
222 pipes.test()
223
224
225 if tensor and not align_data_exists(tensor):
226 raise RelaxNoTensorError('alignment')
227
228
229 if tensor:
230 tensors = [tensor]
231 else:
232 tensors = []
233 for i in range(len(cdp.align_tensors)):
234 tensors.append(cdp.align_tensors[i].name)
235
236
237 for tensor in tensors:
238
239 print("Removing the '%s' tensor." % tensor)
240
241
242 index = get_tensor_index(tensor=tensor)
243
244
245 cdp.align_tensors.pop(index)
246
247
248 if not len(cdp.align_tensors):
249 del(cdp.align_tensors)
250
251
253 """Function for displaying the alignment tensor.
254
255 @keyword tensor: The alignment tensor identification string.
256 @type tensor: str or None
257 """
258
259
260 pipes.test()
261
262
263 tensor_list = []
264 if not tensor:
265 for tensor_cont in cdp.align_tensors:
266 tensor_list.append(tensor_cont.name)
267 else:
268 tensor_list.append(tensor)
269
270
271 for tensor in tensor_list:
272
273 if not align_data_exists(tensor):
274 raise RelaxNoTensorError('alignment')
275
276
277 data = get_tensor_object(tensor)
278
279
280 head = "# Tensor: %s #" % tensor
281 print("\n\n\n" + '#' * len(head) + "\n" + head + "\n" + '#' * len(head))
282
283
284
285
286
287 title = "# Saupe order matrix."
288 print("\n\n" + title + '\n' + '#'*len(title) + '\n')
289
290
291 print("# 5D, rank-1 notation {Sxx, Syy, Sxy, Sxz, Syz}:")
292 print("[%25.12e, %25.12e, %25.12e, %25.12e, %25.12e]\n" % (data.Sxx, data.Syy, data.Sxy, data.Sxz, data.Syz))
293
294
295 print("# 5D, rank-1 notation {Szz, Sxx-yy, Sxy, Sxz, Syz} (the Pales default format).")
296 print("[%25.12e, %25.12e, %25.12e, %25.12e, %25.12e]\n" % (data.Szz, data.Sxxyy, data.Sxy, data.Sxz, data.Syz))
297
298
299 print("# 3D, rank-2 notation.")
300 print("%s" % (data.S))
301
302
303
304
305
306 title = "# Alignment tensor."
307 print("\n\n" + title + '\n' + '#'*len(title) + '\n')
308
309
310 print("# 5D, rank-1 notation {Axx, Ayy, Axy, Axz, Ayz}:")
311 print("[%25.12e, %25.12e, %25.12e, %25.12e, %25.12e]\n" % (data.Axx, data.Ayy, data.Axy, data.Axz, data.Ayz))
312
313
314 print("# 5D, rank-1 notation {Azz, Axx-yy, Axy, Axz, Ayz} (the Pales default format).")
315 print("[%25.12e, %25.12e, %25.12e, %25.12e, %25.12e]\n" % (data.Azz, data.Axxyy, data.Axy, data.Axz, data.Ayz))
316
317
318 print("# 3D, rank-2 notation.")
319 print("%s" % data.A)
320
321
322
323
324
325 title = "# Probability tensor."
326 print("\n\n" + title + '\n' + '#'*len(title) + '\n')
327
328
329 print("# 5D, rank-1 notation {Pxx, Pyy, Pxy, Pxz, Pyz}:")
330 print("[%25.12e, %25.12e, %25.12e, %25.12e, %25.12e]\n" % (data.Pxx, data.Pyy, data.Pxy, data.Pxz, data.Pyz))
331
332
333 print("# 5D, rank-1 notation {Pzz, Pxx-yy, Pxy, Pxz, Pyz}.")
334 print("[%25.12e, %25.12e, %25.12e, %25.12e, %25.12e]\n" % (data.Pzz, data.Pxxyy, data.Pxy, data.Pxz, data.Pyz))
335
336
337 print("# 3D, rank-2 notation.")
338 print("%s" % data.P)
339
340
341
342
343
344 title = "# Magnetic susceptibility tensor."
345 print("\n\n" + title + '\n' + '#'*len(title) + '\n')
346 chi_tensor = True
347
348
349 print("# The magnetic field strength (MHz):")
350 if hasattr(cdp, 'spectrometer_frq') and tensor in cdp.spectrometer_frq:
351 print("%s\n" % (cdp.spectrometer_frq[tensor] / 1e6))
352 else:
353 print("Not set.\n")
354 chi_tensor = False
355
356
357 print("# The temperature (K):")
358 if hasattr(cdp, 'temperature') and tensor in cdp.temperature:
359 print("%s\n" % cdp.temperature[tensor])
360 else:
361 print("Not set.\n")
362 chi_tensor = False
363
364
365 if not chi_tensor:
366 print("# The chi tensor:\nN/A.\n")
367
368
369 else:
370
371 chi_xx = calc_chi_tensor(data.Axx, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
372 chi_xy = calc_chi_tensor(data.Axy, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
373 chi_xz = calc_chi_tensor(data.Axz, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
374 chi_yy = calc_chi_tensor(data.Ayy, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
375 chi_yz = calc_chi_tensor(data.Ayz, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
376 chi_zz = calc_chi_tensor(data.Azz, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
377 chi_xxyy = calc_chi_tensor(data.Axxyy, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
378 chi = calc_chi_tensor(data.A, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
379
380
381 print("# 5D, rank-1 notation {chi_xx, chi_yy, chi_xy, chi_xz, chi_yz}:")
382 print("[%25.12e, %25.12e, %25.12e, %25.12e, %25.12e]\n" % (chi_xx, chi_yy, chi_xy, chi_xz, chi_yz))
383
384
385 print("# 5D, rank-1 notation {chi_zz, chi_xx-yy, chi_xy, chi_xz, chi_yz}.")
386 print("[%25.12e, %25.12e, %25.12e, %25.12e, %25.12e]\n" % (chi_zz, chi_xxyy, chi_xy, chi_xz, chi_yz))
387
388
389 print("# 3D, rank-2 notation.")
390 print("%s" % chi)
391
392
393
394
395
396 title = "# Eigensystem."
397 print("\n\n" + title + '\n' + '#'*len(title) + '\n')
398
399
400 print("# Saupe order matrix eigenvalues {Sxx, Syy, Szz}.")
401 print("[%25.12e, %25.12e, %25.12e]\n" % (data.S_diag[0, 0], data.S_diag[1, 1], data.S_diag[2, 2]))
402 print("# Alignment tensor eigenvalues {Axx, Ayy, Azz}.")
403 print("[%25.12e, %25.12e, %25.12e]\n" % (data.A_diag[0, 0], data.A_diag[1, 1], data.A_diag[2, 2]))
404 print("# Probability tensor eigenvalues {Pxx, Pyy, Pzz}.")
405 print("[%25.12e, %25.12e, %25.12e]\n" % (data.P_diag[0, 0], data.P_diag[1, 1], data.P_diag[2, 2]))
406 if chi_tensor:
407 chi_diag = calc_chi_tensor(data.A_diag, cdp.spectrometer_frq[tensor], cdp.temperature[tensor])
408 print("# Magnetic susceptibility eigenvalues {chi_xx, chi_yy, chi_zz}.")
409 print("[%25.12e, %25.12e, %25.12e]\n" % (chi_diag[0, 0], chi_diag[1, 1], chi_diag[2, 2]))
410
411
412 print("# Eigenvector x.")
413 print("[%25.12f, %25.12f, %25.12f]\n" % (data.unit_x[0], data.unit_x[1], data.unit_x[2]))
414 print("# Eigenvector y.")
415 print("[%25.12f, %25.12f, %25.12f]\n" % (data.unit_y[0], data.unit_y[1], data.unit_y[2]))
416 print("# Eigenvector z.")
417 print("[%25.12f, %25.12f, %25.12f]\n" % (data.unit_z[0], data.unit_z[1], data.unit_z[2]))
418
419
420 print("# Rotation matrix.")
421 print("%s\n" % data.rotation)
422
423
424 print("# Euler angles in zyz notation {alpha, beta, gamma}.")
425 print("[%25.12f, %25.12f, %25.12f]\n" % (data.euler[0], data.euler[1], data.euler[2]))
426
427
428
429
430
431 title = "# Geometric description."
432 print("\n\n" + title + '\n' + '#'*len(title) + '\n')
433
434
435 print("# Generalized degree of order (GDO).")
436 print("GDO = %-25.12e\n" % gdo(data.A))
437
438
439 print("# Alignment tensor axial component (Aa = 3/2 * Azz, where Aii are the eigenvalues).")
440 print("Aa = %-25.12e\n" % data.Aa)
441
442
443 print("# Rhombic component (Ar = Axx - Ayy, where Aii are the eigenvalues).")
444 print("Ar = %-25.12e\n" % data.Ar)
445 print("# Rhombicity (R = Ar / Aa).")
446 print("R = %-25.12f\n" % data.R)
447 print("# Asymmetry parameter (eta = (Axx - Ayy) / Azz, where Aii are the eigenvalues).")
448 print("eta = %-25.12f\n" % data.eta)
449
450
451 if chi_tensor:
452
453 print("# Magnetic susceptibility axial parameter (chi_ax = chi_zz - (chi_xx + chi_yy)/2, where chi_ii are the eigenvalues).")
454 print("chi_ax = %-25.12e\n" % (chi_diag[2, 2] - (chi_diag[0, 0] + chi_diag[1, 1])/2.0))
455
456
457 print("# Magnetic susceptibility rhombicity parameter (chi_rh = chi_xx - chi_yy, where chi_ii are the eigenvalues).")
458 print("chi_rh = %-25.12e\n" % (chi_diag[0, 0] - chi_diag[1, 1]))
459
460
461 print("\n\n\n")
462
463
464 -def fix(id=None, fixed=True):
465 """Fix the alignment tensor during optimisation.
466
467 @keyword id: The alignment tensor ID string. If set to None, then all alignment tensors will be fixed.
468 @type id: str or None
469 @keyword fixed: If True, the alignment tensor will be fixed during optimisation. If False, the alignment tensors will be optimised.
470 @type fixed: bool
471 """
472
473
474 pipes.test()
475
476
477 for i in range(len(cdp.align_tensors)):
478
479 if id and cdp.align_tensors[i].name == id:
480 cdp.align_tensors[i].set_fixed(fixed)
481
482
483 if id == None:
484 cdp.align_tensors[i].set_fixed(fixed)
485
486
488 """Wrap the Euler angles and remove the glide reflection and translational symmetries.
489
490 Wrap the angles such that::
491
492 0 <= alpha <= 2pi,
493 0 <= beta <= pi,
494 0 <= gamma <= 2pi.
495
496 For the simulated values, the angles are wrapped as::
497
498 alpha - pi <= alpha_sim <= alpha + pi
499 beta - pi/2 <= beta_sim <= beta + pi/2
500 gamma - pi <= gamma_sim <= gamma + pi
501
502
503 @param sim_index: The simulation index. If set to None then the actual values will be folded
504 rather than the simulation values.
505 @type sim_index: int or None
506 """
507
508
509
510
511
512
513 alpha = cdp.align_tensors.alpha
514 beta = cdp.align_tensors.beta
515 gamma = cdp.align_tensors.gamma
516
517
518 if sim_index != None:
519 alpha_sim = cdp.align_tensors.alpha_sim[sim_index]
520 beta_sim = cdp.align_tensors.beta_sim[sim_index]
521 gamma_sim = cdp.align_tensors.gamma_sim[sim_index]
522
523
524 if sim_index == None:
525 cdp.align_tensors.set(param='alpha', value=wrap_angles(alpha, 0.0, 2.0*pi))
526 cdp.align_tensors.set(param='beta', value= wrap_angles(beta, 0.0, 2.0*pi))
527 cdp.align_tensors.set(param='gamma', value=wrap_angles(gamma, 0.0, 2.0*pi))
528
529
530 else:
531 cdp.align_tensors.set(param='alpha', value=wrap_angles(alpha_sim, alpha - pi, alpha + pi), category='sim', sim_index=sim_index)
532 cdp.align_tensors.set(param='beta', value= wrap_angles(beta_sim, beta - pi, beta + pi), category='sim', sim_index=sim_index)
533 cdp.align_tensors.set(param='gamma', value=wrap_angles(gamma_sim, gamma - pi, gamma + pi), category='sim', sim_index=sim_index)
534
535
536
537
538
539
540 if sim_index == None:
541
542 if cdp.align_tensors.beta >= pi:
543 cdp.align_tensors.set(param='alpha', value=pi - cdp.align_tensors.alpha)
544 cdp.align_tensors.set(param='beta', value=cdp.align_tensors.beta - pi)
545
546
547 else:
548
549 if cdp.align_tensors.beta_sim[sim_index] >= cdp.align_tensors.beta + pi/2.0:
550 cdp.align_tensors.set(param='alpha', value=pi - cdp.align_tensors.alpha_sim[sim_index], category='sim', sim_index=sim_index)
551 cdp.align_tensors.set(param='beta', value=cdp.align_tensors.beta_sim[sim_index] - pi, category='sim', sim_index=sim_index)
552 elif cdp.align_tensors.beta_sim[sim_index] <= cdp.align_tensors.beta - pi/2.0:
553 cdp.align_tensors.set(param='alpha', value=pi - cdp.align_tensors.alpha_sim[sim_index], category='sim', sim_index=sim_index)
554 cdp.align_tensors.set(param='beta', value=cdp.align_tensors.beta_sim[sim_index] + pi, category='sim', sim_index=sim_index)
555
556
558 """Calculate the generalized degree of order (GDO) for the given alignment tensor.
559
560 @param A: The alignment tensor.
561 @type A: rank-2, 3D numpy array
562 @return: The GDO value.
563 @rtype: float
564 """
565
566
567 gdo = sqrt(3.0/2.0) * norm(A)
568
569
570 return gdo
571
572
574 """Return the list of all alignment IDs.
575
576 @return: The list of all alignment IDs.
577 @rtype: list of str
578 """
579
580
581 if cdp == None:
582 return []
583
584
585 if not hasattr(cdp, 'align_ids'):
586 return []
587
588
589 return cdp.align_ids
590
591
593 """Return the list of all tensor IDs.
594
595 @return: The list of all tensor IDs.
596 @rtype: list of str
597 """
598
599
600 ids = []
601
602
603 if cdp == None:
604 return ids
605
606
607 if not hasattr(cdp, 'align_tensors'):
608 return ids
609
610
611 for i in range(len(cdp.align_tensors)):
612 if cdp.align_tensors[i].name != None:
613 ids.append(cdp.align_tensors[i].name)
614
615
616 return ids
617
618
620 """Function for returning the index corresponding to the 'tensor' argument.
621
622 @keyword tensor: The alignment tensor identification string.
623 @type tensor: str or None
624 @keyword align_id: Alternative to the tensor argument, used to return the tensor index for the tensors corresponding to the alignment ID string. If more than one tensor exists, then this will fail.
625 @type align_id: str or None
626 @keyword pipe: The data pipe to search for data in.
627 @type pipe: str
628 @return: The index corresponding to the 'tensor' arg.
629 @rtype: int
630 """
631
632
633 if pipe == None:
634 pipe = pipes.cdp_name()
635
636
637 dp = pipes.get_pipe(pipe)
638
639
640 index = None
641 count = 0
642
643
644 for i in range(len(dp.align_tensors)):
645
646 if tensor and dp.align_tensors[i].name == tensor:
647 index = i
648 count += 1
649
650
651 if align_id and hasattr(dp.align_tensors[i], 'align_id') and dp.align_tensors[i].align_id == align_id:
652 index = i
653 count += 1
654
655
656 if count == 0:
657 warn(RelaxWarning("No alignment tensors match the tensor name '%s' or alignment ID '%s' in the data pipe '%s'." % (tensor, align_id, pipe)))
658 return None
659
660
661 if count > 1:
662 warn(RelaxWarning("More than one alignment tensors matches the tensor name '%s' or alignment ID '%s' in the data pipe '%s'." % (tensor, align_id, pipe)))
663 return None
664
665
666 return index
667
668
670 """Return the AlignTensorData instance corresponding to the tensor ID.
671
672 @param tensor: The alignment tensor identification string.
673 @type tensor: str
674 @param pipe: The data pipe to search for data in.
675 @type pipe: str
676 @return: The alignment tensor object corresponding to the 'tensor' arg.
677 @rtype: AlignTensorData instance
678 """
679
680
681 if pipe == None:
682 pipe = pipes.cdp_name()
683
684
685 data = None
686
687
688 for i in range(len(cdp.align_tensors)):
689 if cdp.align_tensors[i].name == tensor:
690 data = cdp.align_tensors[i]
691
692
693 return data
694
695
697 """Return the unique AlignTensorData instance corresponding to the alignment ID.
698
699 @param align_id: The alignment ID for the unique tensor.
700 @type align_id: str
701 @return: The alignment tensor object corresponding to the 'tensor' arg.
702 @rtype: AlignTensorData instance
703 """
704
705
706 if pipe == None:
707 pipe = pipes.cdp_name()
708
709
710 data = None
711
712
713 count = 0
714 for i in range(len(cdp.align_tensors)):
715 if hasattr(cdp.align_tensors[i], 'align_id') and cdp.align_tensors[i].align_id == align_id:
716 data = cdp.align_tensors[i]
717 count += 1
718
719
720 if count > 1:
721 raise RelaxError("Multiple alignment tensors match the alignment ID '%s'." % align_id)
722
723 return data
724
725
726 -def init(tensor=None, align_id=None, params=None, scale=1.0, angle_units='deg', param_types=0, domain=None, errors=False):
727 """Function for initialising the alignment tensor.
728
729 @keyword tensor: The alignment tensor identification string.
730 @type tensor: str
731 @keyword align_id: The alignment ID string that the tensor corresponds to.
732 @type align_id: str or None
733 @keyword params: The alignment tensor parameters.
734 @type params: float
735 @keyword scale: The alignment tensor eigenvalue scaling value.
736 @type scale: float
737 @keyword angle_units: The units for the angle parameters (either 'deg' or 'rad').
738 @type angle_units: str
739 @keyword param_types: The type of parameters supplied. The flag values correspond to, 0: {Axx, Ayy, Axy, Axz, Ayz}, and 1: {Azz, Axx-yy, Axy, Axz, Ayz}.
740 @type param_types: int
741 @keyword domain: The domain label.
742 @type domain: str or None
743 @keyword errors: A flag which determines if the alignment tensor data or its errors are being input.
744 @type errors: bool
745 """
746
747
748 pipes.test()
749
750
751 if align_id == None:
752 raise RelaxError("The alignment ID must be given.")
753
754
755 valid_types = ['deg', 'rad']
756 if not angle_units in valid_types:
757 raise RelaxError("The alignment tensor 'angle_units' argument " + repr(angle_units) + " should be either 'deg' or 'rad'.")
758
759
760 if errors and (not hasattr(cdp, 'align_ids') or not align_id in cdp.align_ids):
761 raise RelaxNoTensorError('alignment')
762
763
764 if domain and (not hasattr(cdp, 'domain') or domain not in cdp.domain.keys()):
765 raise RelaxError("The domain '%s' has not been defined. Please use the domain user function." % domain)
766
767
768 if not hasattr(cdp, 'align_ids'):
769 cdp.align_ids = []
770 if align_id not in cdp.align_ids:
771 cdp.align_ids.append(align_id)
772
773
774 tensor_obj = None
775 if not errors:
776
777 if not hasattr(cdp, 'align_tensors'):
778 cdp.align_tensors = AlignTensorList()
779
780
781 if tensor == None or tensor not in cdp.align_tensors.names():
782 tensor_obj = cdp.align_tensors.add_item(tensor)
783
784
785 if not tensor_obj:
786 if tensor:
787 tensor_obj = get_tensor_object(tensor)
788 else:
789 tensor_obj = get_tensor_object_from_align(align_id)
790
791
792 if param_types == 0:
793
794 Sxx, Syy, Sxy, Sxz, Syz = params
795
796
797 Sxx = Sxx * scale
798 Syy = Syy * scale
799 Sxy = Sxy * scale
800 Sxz = Sxz * scale
801 Syz = Syz * scale
802
803
804 set(tensor=tensor_obj, value=[Sxx, Syy, Sxy, Sxz, Syz], param=['Sxx', 'Syy', 'Sxy', 'Sxz', 'Syz'], errors=errors)
805
806
807 elif param_types == 1:
808
809 Szz, Sxxyy, Sxy, Sxz, Syz = params
810
811
812 Szz = Szz * scale
813 Sxxyy = Sxxyy * scale
814 Sxy = Sxy * scale
815 Sxz = Sxz * scale
816 Syz = Syz * scale
817
818
819 set(tensor=tensor_obj, value=[Szz, Sxxyy, Sxy, Sxz, Syz], param=['Szz', 'Sxxyy', 'Sxy', 'Sxz', 'Syz'], errors=errors)
820
821
822 elif param_types == 2:
823
824 Axx, Ayy, Axy, Axz, Ayz = params
825
826
827 Axx = Axx * scale
828 Ayy = Ayy * scale
829 Axy = Axy * scale
830 Axz = Axz * scale
831 Ayz = Ayz * scale
832
833
834 set(tensor=tensor_obj, value=[Axx, Ayy, Axy, Axz, Ayz], param=['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], errors=errors)
835
836
837 elif param_types == 3:
838
839 Azz, Axxyy, Axy, Axz, Ayz = params
840
841
842 Azz = Azz * scale
843 Axxyy = Axxyy * scale
844 Axy = Axy * scale
845 Axz = Axz * scale
846 Ayz = Ayz * scale
847
848
849 set(tensor=tensor_obj, value=[Azz, Axxyy, Axy, Axz, Ayz], param=['Azz', 'Axxyy', 'Axy', 'Axz', 'Ayz'], errors=errors)
850
851
852 elif param_types == 4:
853
854 Axx, Ayy, Axy, Axz, Ayz = params
855
856
857 r = None
858 for spin in spin_loop():
859
860 if r == None:
861 r = spin.r
862
863
864 if r != spin.r:
865 raise RelaxError("Not all spins have the same bond length.")
866
867
868 scale = scale / kappa() * r**3
869 Axx = Axx * scale
870 Ayy = Ayy * scale
871 Axy = Axy * scale
872 Axz = Axz * scale
873 Ayz = Ayz * scale
874
875
876 set(tensor=tensor_obj, value=[Axx, Ayy, Axy, Axz, Ayz], param=['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], errors=errors)
877
878
879 elif param_types == 5:
880
881 Azz, Axxyy, Axy, Axz, Ayz = params
882
883
884 r = None
885 for spin in spin_loop():
886
887 if r == None:
888 r = spin.r
889
890
891 if r != spin.r:
892 raise RelaxError("Not all spins have the same bond length.")
893
894
895 scale = scale / kappa() * r**3
896 Azz = Azz * scale
897 Axxyy = Axxyy * scale
898 Axy = Axy * scale
899 Axz = Axz * scale
900 Ayz = Ayz * scale
901
902
903 set(tensor=tensor_obj, value=[Azz, Axxyy, Axy, Axz, Ayz], param=['Azz', 'Axxyy', 'Axy', 'Axz', 'Ayz'], errors=errors)
904
905
906 elif param_types == 6:
907
908 Pxx, Pyy, Pxy, Pxz, Pyz = params
909
910
911 Pxx = Pxx * scale
912 Pyy = Pyy * scale
913 Pxy = Pxy * scale
914 Pxz = Pxz * scale
915 Pyz = Pyz * scale
916
917
918 set(tensor=tensor_obj, value=[Pxx, Pyy, Pxy, Pxz, Pyz], param=['Pxx', 'Pyy', 'Pxy', 'Pxz', 'Pyz'], errors=errors)
919
920
921 elif param_types == 7:
922
923 Pzz, Pxxyy, Pxy, Pxz, Pyz = params
924
925
926 Pzz = Pzz * scale
927 Pxxyy = Pxxyy * scale
928 Pxy = Pxy * scale
929 Pxz = Pxz * scale
930 Pyz = Pyz * scale
931
932
933 set(tensor=tensor_obj, value=[Pzz, Pxxyy, Pxy, Pxz, Pyz], param=['Pzz', 'Pxxyy', 'Pxy', 'Pxz', 'Pyz'], errors=errors)
934
935
936 else:
937 raise RelaxUnknownParamCombError('param_types', param_types)
938
939
940 if domain:
941 set_domain(tensor=tensor, domain=domain)
942 if align_id:
943 tensor_obj.set(param='align_id', value=align_id)
944
945
947 """The function for creating bounds for the mapping function."""
948
949
950 if param in ['Axx', 'Ayy', 'Azz', 'Axxyy', 'Axy', 'Axz', 'Ayz']:
951 return [-50, 50]
952
953
954 elif param == 'alpha':
955 return [0, 2*pi]
956
957
958 elif param == 'beta':
959 return [0, pi]
960
961
962 elif param == 'gamma':
963 return [0, 2*pi]
964
965
967 """Function for creating labels, tick locations, and tick values for an OpenDX map.
968
969 @param index: The index (which isn't used here?!?).
970 @type index: int
971 @param params: The list of parameter names.
972 @type params: list of str
973 @param bounds: The bounds of the map.
974 @type bounds: list of lists (of a float and bin)
975 @param swap: An array for switching axes around.
976 @type swap: list of int
977 @param inc: The number of increments of one dimension in the map.
978 @type inc: list of int
979 """
980
981
982 labels = "{"
983 tick_locations = []
984 tick_values = []
985 n = len(params)
986 axis_incs = 5
987 loc_inc = inc / axis_incs
988
989
990 for i in range(n):
991
992 factor = return_conversion_factor(params[swap[i]])
993
994
995 units = return_units(params[swap[i]])
996
997
998 if units:
999 labels = labels + "\"" + params[swap[i]] + " (" + units + ")\""
1000 else:
1001 labels = labels + "\"" + params[swap[i]] + "\""
1002
1003
1004 vals = bounds[swap[i], 0] / factor
1005 val_inc = (bounds[swap[i], 1] - bounds[swap[i], 0]) / (axis_incs * factor)
1006
1007 if i < n - 1:
1008 labels = labels + " "
1009 else:
1010 labels = labels + "}"
1011
1012
1013 string = "{"
1014 val = 0.0
1015 for j in range(axis_incs + 1):
1016 string = string + " " + repr(val)
1017 val = val + loc_inc
1018 string = string + " }"
1019 tick_locations.append(string)
1020
1021
1022 string = "{"
1023 for j in range(axis_incs + 1):
1024 string = string + "\"" + "%.2f" % vals + "\" "
1025 vals = vals + val_inc
1026 string = string + "}"
1027 tick_values.append(string)
1028
1029 return labels, tick_locations, tick_values
1030
1031
1033 """Function for calculating the 5D angles between the alignment tensors.
1034
1035 The basis set used for the 5D vector construction changes the angles calculated.
1036
1037 @param basis_set: The basis set to use for constructing the 5D vectors. If set to 0, the
1038 basis set is {Sxx, Syy, Sxy, Sxz, Syz}. If 1, then the basis set is {Szz,
1039 Sxxyy, Sxy, Sxz, Syz}.
1040 @type basis_set: int
1041 @param tensors: An array of tensors to apply SVD to. If None, all tensors will be used.
1042 @type tensors: None or array of str
1043 """
1044
1045
1046 if not hasattr(cdp, 'align_tensors') or len(cdp.align_tensors) == 0:
1047 raise RelaxNoTensorError('alignment')
1048
1049
1050 tensor_num = 0
1051 for tensor in cdp.align_tensors:
1052 if tensors and tensor.name not in tensors:
1053 continue
1054 tensor_num = tensor_num + 1
1055
1056
1057 matrix = zeros((tensor_num, 5), float64)
1058
1059
1060 i = 0
1061 for tensor in cdp.align_tensors:
1062
1063 if tensors and tensor.name not in tensors:
1064 continue
1065
1066
1067 if basis_set == 0:
1068
1069 matrix[i, 0] = tensor.Sxx
1070 matrix[i, 1] = tensor.Syy
1071 matrix[i, 2] = tensor.Sxy
1072 matrix[i, 3] = tensor.Sxz
1073 matrix[i, 4] = tensor.Syz
1074
1075
1076 elif basis_set == 1:
1077
1078 matrix[i, 0] = tensor.Szz
1079 matrix[i, 1] = tensor.Sxxyy
1080 matrix[i, 2] = tensor.Sxy
1081 matrix[i, 3] = tensor.Sxz
1082 matrix[i, 4] = tensor.Syz
1083
1084
1085 norm = linalg.norm(matrix[i])
1086 matrix[i] = matrix[i] / norm
1087
1088
1089 i = i + 1
1090
1091
1092 cdp.align_tensors.angles = zeros((tensor_num, tensor_num), float64)
1093
1094
1095 sys.stdout.write("\nData pipe: " + repr(pipes.cdp_name()) + "\n")
1096 sys.stdout.write("\n5D angles in deg between the vectors ")
1097 if basis_set == 0:
1098 sys.stdout.write("{Sxx, Syy, Sxy, Sxz, Syz}")
1099 elif basis_set == 1:
1100 sys.stdout.write("{Szz, Sxx-yy, Sxy, Sxz, Syz}")
1101 sys.stdout.write(":\n")
1102
1103
1104 table = []
1105
1106
1107 table.append([''])
1108 for i in range(tensor_num):
1109 if cdp.align_tensors[i].name == None:
1110 table[0].append(repr(i))
1111 else:
1112 table[0].append(cdp.align_tensors[i].name)
1113
1114
1115 for i in range(tensor_num):
1116
1117 if cdp.align_tensors[i].name == None:
1118 table.append([repr(i)])
1119 else:
1120 table.append([cdp.align_tensors[i].name])
1121
1122
1123 for j in range(tensor_num):
1124
1125 delta = dot(matrix[i], matrix[j])
1126
1127
1128 if delta > 1:
1129 delta = 1
1130
1131
1132 cdp.align_tensors.angles[i, j] = arccos(delta)
1133
1134
1135 table[i+1].append("%8.1f" % (cdp.align_tensors.angles[i, j]*180.0/pi))
1136
1137
1138 write_data(out=sys.stdout, data=table)
1139
1140
1142 """Count the number of tensors.
1143
1144 @keyword skip_fixed: If set to True, then only the tensors without the fixed flag will be counted. If set to False, then all tensors will be counted.
1145 @type skip_fixed: bool
1146 @return: The number of tensors (excluding fixed tensors by default).
1147 @rtype: int
1148 """
1149
1150
1151 count = 0
1152
1153
1154 for tensor_cont in cdp.align_tensors:
1155
1156 if skip_fixed and tensor_cont.fixed:
1157 continue
1158
1159
1160 count += 1
1161
1162
1163 return count
1164
1165
1167 """Determine if the PCS or RDC data for the given alignment ID is needed for optimisation.
1168
1169 @keyword align_id: The optional alignment ID string.
1170 @type align_id: str
1171 @return: True if alignment data is to be used for optimisation, False otherwise.
1172 @rtype: bool
1173 """
1174
1175
1176 if not hasattr(cdp, 'align_ids'):
1177 return False
1178
1179
1180 if align_id:
1181 align_ids = [align_id]
1182 else:
1183 align_ids = cdp.align_ids
1184
1185
1186 for align_id in align_ids:
1187 if pipe_control.pcs.opt_uses_pcs(align_id) or pipe_control.rdc.opt_uses_rdc(align_id):
1188 return True
1189
1190
1191 return False
1192
1193
1195 """Determine if the given tensor is to be optimised.
1196
1197 @param tensor: The alignment tensor to check.
1198 @type tensor: AlignmentTensor object.
1199 @return: True if the tensor is to be optimised, False otherwise.
1200 @rtype: bool
1201 """
1202
1203
1204 ids = []
1205 if hasattr(cdp, 'rdc_ids'):
1206 ids += cdp.rdc_ids
1207 if hasattr(cdp, 'pcs_ids'):
1208 ids += cdp.pcs_ids
1209
1210
1211 if tensor.align_id not in ids:
1212 return False
1213
1214
1215 if tensor.fixed:
1216 return False
1217
1218
1219 return True
1220
1221
1222 -def reduction(full_tensor=None, red_tensor=None):
1223 """Specify which tensor is a reduction of which other tensor.
1224
1225 @param full_tensor: The full alignment tensor.
1226 @type full_tensor: str
1227 @param red_tensor: The reduced alignment tensor.
1228 @type red_tensor: str
1229 """
1230
1231
1232 match_full = False
1233 match_red = False
1234 i = 0
1235 for tensor_cont in cdp.align_tensors:
1236
1237 if tensor_cont.name == full_tensor:
1238 match_full = True
1239 index_full = i
1240 if tensor_cont.name == red_tensor:
1241 match_red = True
1242 index_red = i
1243
1244
1245 i = i + 1
1246
1247
1248 if not match_full:
1249 raise RelaxNoTensorError('alignment', full_tensor)
1250 if not match_red:
1251 raise RelaxNoTensorError('alignment', red_tensor)
1252
1253
1254 if not hasattr(cdp.align_tensors, 'reduction'):
1255 cdp.align_tensors.reduction = []
1256 cdp.align_tensors.reduction.append([index_full, index_red])
1257
1258
1260 """Function for returning the factor of conversion between different parameter units.
1261
1262 @param param: The parameter name.
1263 @type param: str
1264 @return: The conversion factor.
1265 @rtype: float
1266 """
1267
1268
1269 object_name = return_data_name(param)
1270
1271
1272 if object_name in ['Axx', 'Ayy', 'Azz', 'Axxyy', 'Axy', 'Axz', 'Ayz']:
1273 return 1.0
1274
1275
1276 elif object_name in ['alpha', 'beta', 'gamma']:
1277 return (2.0*pi) / 360.0
1278
1279
1280 else:
1281 return 1.0
1282
1283
1285 """Return the parameter name.
1286
1287 @param name: The name of the parameter to return the name of.
1288 @type name: str
1289 @return: The parameter name.
1290 @rtype: str
1291 """
1292
1293
1294 if not isinstance(name, str):
1295 raise RelaxStrError('name', name)
1296
1297
1298 if search('^[Ss]xx$', name):
1299 return 'Sxx'
1300
1301
1302 if search('^[Ss]yy$', name):
1303 return 'Syy'
1304
1305
1306 if search('^[Ss]zz$', name):
1307 return 'Szz'
1308
1309
1310 if search('^[Ss]xy$', name):
1311 return 'Sxy'
1312
1313
1314 if search('^[Ss]xz$', name):
1315 return 'Sxz'
1316
1317
1318 if search('^[Ss]yz$', name):
1319 return 'Syz'
1320
1321
1322 if search('^[Ss]xxyy$', name):
1323 return 'Sxxyy'
1324
1325
1326 if search('^[Aa]xx$', name):
1327 return 'Axx'
1328
1329
1330 if search('^[Aa]yy$', name):
1331 return 'Ayy'
1332
1333
1334 if search('^[Aa]zz$', name):
1335 return 'Azz'
1336
1337
1338 if search('^[Aa]xy$', name):
1339 return 'Axy'
1340
1341
1342 if search('^[Aa]xz$', name):
1343 return 'Axz'
1344
1345
1346 if search('^[Aa]yz$', name):
1347 return 'Ayz'
1348
1349
1350 if search('^[Aa]xxyy$', name):
1351 return 'Axxyy'
1352
1353
1354 if search('^[Pp]xx$', name):
1355 return 'Pxx'
1356
1357
1358 if search('^[Pp]yy$', name):
1359 return 'Pyy'
1360
1361
1362 if search('^[Pp]zz$', name):
1363 return 'Pzz'
1364
1365
1366 if search('^[Pp]xy$', name):
1367 return 'Pxy'
1368
1369
1370 if search('^[Pp]xz$', name):
1371 return 'Pxz'
1372
1373
1374 if search('^[Pp]yz$', name):
1375 return 'Pyz'
1376
1377
1378 if search('^[Pp]xxyy$', name):
1379 return 'Pxxyy'
1380
1381
1382 if search('^a$', name) or search('alpha', name):
1383 return 'alpha'
1384
1385
1386 if search('^b$', name) or search('beta', name):
1387 return 'beta'
1388
1389
1390 if search('^g$', name) or search('gamma', name):
1391 return 'gamma'
1392
1393
1394 raise RelaxUnknownParamError(name)
1395
1396
1397 __return_data_name_prompt_doc__ = """
1398 Alignment tensor parameter string matching patterns
1399 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1400
1401 ____________________________________________________________________________________________
1402 | | | |
1403 | Data type | Object name | Patterns |
1404 |________________________________________________________|______________|__________________|
1405 | | | |
1406 | The xx component of the Saupe order matrix - Sxx | 'Sxx' | '^[Sa]xx$' |
1407 | | | |
1408 | The yy component of the Saupe order matrix - Syy | 'Syy' | '^[Sa]yy$' |
1409 | | | |
1410 | The zz component of the Saupe order matrix - Szz | 'Szz' | '^[Sa]zz$' |
1411 | | | |
1412 | The xy component of the Saupe order matrix - Sxy | 'Sxy' | '^[Sa]xy$' |
1413 | | | |
1414 | The xz component of the Saupe order matrix - Sxz | 'Sxz' | '^[Sa]xz$' |
1415 | | | |
1416 | The yz component of the Saupe order matrix - Syz | 'Syz' | '^[Sa]yz$' |
1417 | | | |
1418 | The xx-yy component of the Saupe order matrix - Sxx-yy | 'Sxxyy' | '^[Sa]xxyy$' |
1419 | | | |
1420 | The xx component of the alignment tensor - Axx | 'Axx' | '^[Aa]xx$' |
1421 | | | |
1422 | The yy component of the alignment tensor - Ayy | 'Ayy' | '^[Aa]yy$' |
1423 | | | |
1424 | The zz component of the alignment tensor - Azz | 'Azz' | '^[Aa]zz$' |
1425 | | | |
1426 | The xy component of the alignment tensor - Axy | 'Axy' | '^[Aa]xy$' |
1427 | | | |
1428 | The xz component of the alignment tensor - Axz | 'Axz' | '^[Aa]xz$' |
1429 | | | |
1430 | The yz component of the alignment tensor - Ayz | 'Ayz' | '^[Aa]yz$' |
1431 | | | |
1432 | The xx-yy component of the alignment tensor - Axx-yy | 'Axxyy' | '^[Aa]xxyy$' |
1433 | | | |
1434 | The xx component of the probability matrix - Pxx | 'Pxx' | '^[Pa]xx$' |
1435 | | | |
1436 | The yy component of the probability matrix - Pyy | 'Pyy' | '^[Pa]yy$' |
1437 | | | |
1438 | The zz component of the probability matrix - Pzz | 'Pzz' | '^[Pa]zz$' |
1439 | | | |
1440 | The xy component of the probability matrix - Pxy | 'Pxy' | '^[Pa]xy$' |
1441 | | | |
1442 | The xz component of the probability matrix - Pxz | 'Pxz' | '^[Pa]xz$' |
1443 | | | |
1444 | The yz component of the probability matrix - Pyz | 'Pyz' | '^[Pa]yz$' |
1445 | | | |
1446 | The xx-yy component of the probability matrix - Pxx-yy | 'Pxxyy' | '^[Pa]xxyy$' |
1447 | | | |
1448 | The first Euler angle of the alignment tensor - alpha | 'alpha' | '^a$' or 'alpha' |
1449 | | | |
1450 | The second Euler angle of the alignment tensor - beta | 'beta' | '^b$' or 'beta' |
1451 | | | |
1452 | The third Euler angle of the alignment tensor - gamma | 'gamma' | '^g$' or 'gamma' |
1453 |________________________________________________________|______________|__________________|
1454 """
1455
1456
1458 """Return the tensor container for the given index, skipping fixed tensors if required.
1459
1460 @param index: The index of the tensor (if skip_fixed is True, then fixed tensors are not included in the index count).
1461 @type index: int
1462 @keyword skip_fixed: A flag which if True will exclude fixed tensors from the indexation.
1463 @type skip_fixed: bool
1464 @return: The tensor corresponding to the index.
1465 @rtype: data.align_tensor.AlignTensorData instance
1466 """
1467
1468
1469 count = 0
1470
1471
1472 for tensor_cont in cdp.align_tensors:
1473
1474 if skip_fixed and tensor_cont.fixed:
1475 continue
1476
1477
1478 if index == count:
1479 return tensor_cont
1480
1481
1482 count += 1
1483
1484
1485 return False
1486
1487
1489 """Function for returning a string representing the parameters units.
1490
1491 @param param: The parameter name.
1492 @type param: str
1493 @return: The string representation of the units.
1494 @rtype: str
1495 """
1496
1497
1498 object_name = return_data_name(param)
1499
1500
1501 if object_name in ['Axx', 'Ayy', 'Azz', 'Axxyy', 'Axy', 'Axz', 'Ayz']:
1502 return 'Hz'
1503
1504
1505 elif object_name in ['alpha', 'beta', 'gamma']:
1506 return 'deg'
1507
1508
1509 -def set(tensor=None, value=None, param=None, errors=False):
1510 """Set the tensor.
1511
1512 @keyword tensor: The alignment tensor object.
1513 @type tensor: AlignTensorData instance
1514 @keyword value: The list of values to set the parameters to.
1515 @type value: list of float
1516 @keyword param: The list of parameter names.
1517 @type param: list of str
1518 @keyword errors: A flag which determines if the alignment tensor data or its errors are being
1519 input.
1520 @type errors: bool
1521 """
1522
1523
1524 geo_params = []
1525 geo_values = []
1526 orient_params = []
1527 orient_values = []
1528
1529
1530 for i in range(len(param)):
1531
1532 param[i] = return_data_name(param[i])
1533
1534
1535 if param[i] == None:
1536 raise RelaxUnknownParamError("alignment tensor", 'None')
1537
1538
1539 if value[i] == None:
1540 value[i] = default_value(object_names[i])
1541
1542
1543 if param[i] in ['Sxx', 'Syy', 'Szz', 'Sxxyy', 'Sxy', 'Sxz', 'Syz', 'Axx', 'Ayy', 'Azz', 'Axxyy', 'Axy', 'Axz', 'Ayz', 'Pxx', 'Pyy', 'Pzz', 'Pxxyy', 'Pxy', 'Pxz', 'Pyz']:
1544 geo_params.append(param[i])
1545 geo_values.append(value[i])
1546
1547
1548 if param[i] in ['alpha', 'beta', 'gamma']:
1549 orient_params.append(param[i])
1550 orient_values.append(value[i])
1551
1552
1553
1554
1555
1556
1557 if len(geo_params) == 1:
1558
1559
1560
1561
1562 if geo_params[0] == 'Sxx':
1563 if errors:
1564 tensor.set(param='Sxx', value=geo_values[0], category='err')
1565 else:
1566 tensor.set(param='Sxx', value=geo_values[0])
1567
1568
1569 elif geo_params[0] == 'Syy':
1570 if errors:
1571 tensor.set(param='Syy', value=geo_values[0], category='err')
1572 else:
1573 tensor.set(param='Syy', value=geo_values[0])
1574
1575
1576 elif geo_params[0] == 'Sxy':
1577 if errors:
1578 tensor.set(param='Sxy', value=geo_values[0], category='err')
1579 else:
1580 tensor.set(param='Sxy', value=geo_values[0])
1581
1582
1583 elif geo_params[0] == 'Sxz':
1584 if errors:
1585 tensor.set(param='Sxz', value=geo_values[0], category='err')
1586 else:
1587 tensor.set(param='Sxz', value=geo_values[0])
1588
1589
1590 elif geo_params[0] == 'Syz':
1591 if errors:
1592 tensor.set(param='Syz', value=geo_values[0], category='err')
1593 else:
1594 tensor.set(param='Syz', value=geo_values[0])
1595
1596
1597
1598
1599
1600
1601 elif geo_params[0] == 'Axx':
1602 if errors:
1603 tensor.set(param='Sxx', value=3.0/2.0 * geo_values[0], category='err')
1604 else:
1605 tensor.set(param='Sxx', value=3.0/2.0 * geo_values[0])
1606
1607
1608 elif geo_params[0] == 'Ayy':
1609 if errors:
1610 tensor.set(param='Syy', value=3.0/2.0 * geo_values[0], category='err')
1611 else:
1612 tensor.set(param='Syy', value=3.0/2.0 * geo_values[0])
1613
1614
1615 elif geo_params[0] == 'Axy':
1616 if errors:
1617 tensor.set(param='Sxy', value=3.0/2.0 * geo_values[0], category='err')
1618 else:
1619 tensor.set(param='Sxy', value=3.0/2.0 * geo_values[0])
1620
1621
1622 elif geo_params[0] == 'Axz':
1623 if errors:
1624 tensor.set(param='Sxz', value=3.0/2.0 * geo_values[0], category='err')
1625 else:
1626 tensor.set(param='Sxz', value=3.0/2.0 * geo_values[0])
1627
1628
1629 elif geo_params[0] == 'Ayz':
1630 if errors:
1631 tensor.set(param='Syz', value=3.0/2.0 * geo_values[0], category='err')
1632 else:
1633 tensor.set(param='Syz', value=3.0/2.0 * geo_values[0])
1634
1635
1636
1637
1638
1639
1640 elif geo_params[0] == 'Pxx':
1641 if errors:
1642 tensor.set(param='Sxx', value=3.0/2.0 * (geo_values[0] - 1.0/3.0), category='err')
1643 else:
1644 tensor.set(param='Sxx', value=3.0/2.0 * (geo_values[0] - 1.0/3.0))
1645
1646
1647 elif geo_params[0] == 'Pyy':
1648 if errors:
1649 tensor.set(param='Syy', value=3.0/2.0 * (geo_values[0] - 1.0/3.0), category='err')
1650 else:
1651 tensor.set(param='Syy', value=3.0/2.0 * (geo_values[0] - 1.0/3.0))
1652
1653
1654 elif geo_params[0] == 'Pxy':
1655 if errors:
1656 tensor.set(param='Sxy', value=3.0/2.0 * geo_values[0], category='err')
1657 else:
1658 tensor.set(param='Sxy', value=3.0/2.0 * geo_values[0])
1659
1660
1661 elif geo_params[0] == 'Pxz':
1662 if errors:
1663 tensor.set(param='Sxz', value=3.0/2.0 * geo_values[0], category='err')
1664 else:
1665 tensor.set(param='Sxz', value=3.0/2.0 * geo_values[0])
1666
1667
1668 elif geo_params[0] == 'Pyz':
1669 if errors:
1670 tensor.set(param='Syz', value=3.0/2.0 * geo_values[0], category='err')
1671 else:
1672 tensor.set(param='Syz', value=3.0/2.0 * geo_values[0])
1673
1674
1675 else:
1676 raise RelaxError("The geometric alignment parameter " + repr(geo_params[0]) + " cannot be set.")
1677
1678
1679 elif len(geo_params) == 5:
1680
1681 if geo_params.count('Sxx') == 1 and geo_params.count('Syy') == 1 and geo_params.count('Sxy') == 1 and geo_params.count('Sxz') == 1 and geo_params.count('Syz') == 1:
1682
1683 Sxx = geo_values[geo_params.index('Sxx')]
1684 Syy = geo_values[geo_params.index('Syy')]
1685 Sxy = geo_values[geo_params.index('Sxy')]
1686 Sxz = geo_values[geo_params.index('Sxz')]
1687 Syz = geo_values[geo_params.index('Syz')]
1688
1689
1690 if errors:
1691 tensor.set(param='Axx', value=2.0/3.0 * Sxx, category='err')
1692 tensor.set(param='Ayy', value=2.0/3.0 * Syy, category='err')
1693 tensor.set(param='Axy', value=2.0/3.0 * Sxy, category='err')
1694 tensor.set(param='Axz', value=2.0/3.0 * Sxz, category='err')
1695 tensor.set(param='Ayz', value=2.0/3.0 * Syz, category='err')
1696 else:
1697 tensor.set(param='Axx', value=2.0/3.0 * Sxx)
1698 tensor.set(param='Ayy', value=2.0/3.0 * Syy)
1699 tensor.set(param='Axy', value=2.0/3.0 * Sxy)
1700 tensor.set(param='Axz', value=2.0/3.0 * Sxz)
1701 tensor.set(param='Ayz', value=2.0/3.0 * Syz)
1702
1703
1704 elif geo_params.count('Szz') == 1 and geo_params.count('Sxxyy') == 1 and geo_params.count('Sxy') == 1 and geo_params.count('Sxz') == 1 and geo_params.count('Syz') == 1:
1705
1706 Szz = geo_values[geo_params.index('Szz')]
1707 Sxxyy = geo_values[geo_params.index('Sxxyy')]
1708 Sxy = geo_values[geo_params.index('Sxy')]
1709 Sxz = geo_values[geo_params.index('Sxz')]
1710 Syz = geo_values[geo_params.index('Syz')]
1711
1712
1713 if errors:
1714 tensor.set(param='Axx', value=2.0/3.0 * -0.5*(Szz-Sxxyy), category='err')
1715 tensor.set(param='Ayy', value=2.0/3.0 * -0.5*(Szz+Sxxyy), category='err')
1716 tensor.set(param='Axy', value=2.0/3.0 * Sxy, category='err')
1717 tensor.set(param='Axz', value=2.0/3.0 * Sxz, category='err')
1718 tensor.set(param='Ayz', value=2.0/3.0 * Syz, category='err')
1719 else:
1720 tensor.set(param='Axx', value=2.0/3.0 * -0.5*(Szz-Sxxyy))
1721 tensor.set(param='Ayy', value=2.0/3.0 * -0.5*(Szz+Sxxyy))
1722 tensor.set(param='Axy', value=2.0/3.0 * Sxy)
1723 tensor.set(param='Axz', value=2.0/3.0 * Sxz)
1724 tensor.set(param='Ayz', value=2.0/3.0 * Syz)
1725
1726
1727 elif geo_params.count('Axx') == 1 and geo_params.count('Ayy') == 1 and geo_params.count('Axy') == 1 and geo_params.count('Axz') == 1 and geo_params.count('Ayz') == 1:
1728
1729 Axx = geo_values[geo_params.index('Axx')]
1730 Ayy = geo_values[geo_params.index('Ayy')]
1731 Axy = geo_values[geo_params.index('Axy')]
1732 Axz = geo_values[geo_params.index('Axz')]
1733 Ayz = geo_values[geo_params.index('Ayz')]
1734
1735
1736 if errors:
1737 tensor.set(param='Axx', value=Axx, category='err')
1738 tensor.set(param='Ayy', value=Ayy, category='err')
1739 tensor.set(param='Axy', value=Axy, category='err')
1740 tensor.set(param='Axz', value=Axz, category='err')
1741 tensor.set(param='Ayz', value=Ayz, category='err')
1742 else:
1743 tensor.set(param='Axx', value=Axx)
1744 tensor.set(param='Ayy', value=Ayy)
1745 tensor.set(param='Axy', value=Axy)
1746 tensor.set(param='Axz', value=Axz)
1747 tensor.set(param='Ayz', value=Ayz)
1748
1749
1750 elif geo_params.count('Azz') == 1 and geo_params.count('Axxyy') == 1 and geo_params.count('Axy') == 1 and geo_params.count('Axz') == 1 and geo_params.count('Ayz') == 1:
1751
1752 Azz = geo_values[geo_params.index('Azz')]
1753 Axxyy = geo_values[geo_params.index('Axxyy')]
1754 Axy = geo_values[geo_params.index('Axy')]
1755 Axz = geo_values[geo_params.index('Axz')]
1756 Ayz = geo_values[geo_params.index('Ayz')]
1757
1758
1759 if errors:
1760 tensor.set(param='Axx', value=-0.5*(Azz-Axxyy), category='err')
1761 tensor.set(param='Ayy', value=-0.5*(Azz+Axxyy), category='err')
1762 tensor.set(param='Axy', value=Axy, category='err')
1763 tensor.set(param='Axz', value=Axz, category='err')
1764 tensor.set(param='Ayz', value=Ayz, category='err')
1765 else:
1766 tensor.set(param='Axx', value=-0.5*(Azz-Axxyy))
1767 tensor.set(param='Ayy', value=-0.5*(Azz+Axxyy))
1768 tensor.set(param='Axy', value=Axy)
1769 tensor.set(param='Axz', value=Axz)
1770 tensor.set(param='Ayz', value=Ayz)
1771
1772
1773 elif geo_params.count('Pxx') == 1 and geo_params.count('Pyy') == 1 and geo_params.count('Pxy') == 1 and geo_params.count('Pxz') == 1 and geo_params.count('Pyz') == 1:
1774
1775 Pxx = geo_values[geo_params.index('Pxx')]
1776 Pyy = geo_values[geo_params.index('Pyy')]
1777 Pxy = geo_values[geo_params.index('Pxy')]
1778 Pxz = geo_values[geo_params.index('Pxz')]
1779 Pyz = geo_values[geo_params.index('Pyz')]
1780
1781
1782 if errors:
1783 tensor.set(param='Axx', value=Pxx - 1.0/3.0, category='err')
1784 tensor.set(param='Ayy', value=Pyy - 1.0/3.0, category='err')
1785 tensor.set(param='Axy', value=Pxy, category='err')
1786 tensor.set(param='Axz', value=Pxz, category='err')
1787 tensor.set(param='Ayz', value=Pyz, category='err')
1788 else:
1789 tensor.set(param='Axx', value=Pxx - 1.0/3.0)
1790 tensor.set(param='Ayy', value=Pyy - 1.0/3.0)
1791 tensor.set(param='Axy', value=Pxy)
1792 tensor.set(param='Axz', value=Pxz)
1793 tensor.set(param='Ayz', value=Pyz)
1794
1795
1796 elif geo_params.count('Pzz') == 1 and geo_params.count('Pxxyy') == 1 and geo_params.count('Pxy') == 1 and geo_params.count('Pxz') == 1 and geo_params.count('Pyz') == 1:
1797
1798 Pzz = geo_values[geo_params.index('Pzz')]
1799 Pxxyy = geo_values[geo_params.index('Pxxyy')]
1800 Pxy = geo_values[geo_params.index('Pxy')]
1801 Pxz = geo_values[geo_params.index('Pxz')]
1802 Pyz = geo_values[geo_params.index('Pyz')]
1803
1804
1805 if errors:
1806 tensor.set(param='Axx', value=-0.5*(Pzz-Pxxyy) - 1.0/3.0, category='err')
1807 tensor.set(param='Ayy', value=-0.5*(Pzz+Pxxyy) - 1.0/3.0, category='err')
1808 tensor.set(param='Axy', value=Pxy, category='err')
1809 tensor.set(param='Axz', value=Pxz, category='err')
1810 tensor.set(param='Ayz', value=Pyz, category='err')
1811 else:
1812 tensor.set(param='Axx', value=-0.5*(Pzz-Pxxyy) - 1.0/3.0)
1813 tensor.set(param='Ayy', value=-0.5*(Pzz+Pxxyy) - 1.0/3.0)
1814 tensor.set(param='Axy', value=Pxy)
1815 tensor.set(param='Axz', value=Pxz)
1816 tensor.set(param='Ayz', value=Pyz)
1817
1818
1819 else:
1820 raise RelaxUnknownParamCombError('geometric parameter set', geo_params)
1821
1822
1823
1824 else:
1825 raise RelaxUnknownParamCombError('geometric parameter set', geo_params)
1826
1827
1828
1829
1830
1831
1832 if len(orient_params) == 1:
1833
1834 if orient_params[0] == 'alpha':
1835 if errors:
1836 tensor.set(param='alpha', value=orient_values[orient_params.index('alpha')], category='err')
1837 else:
1838 tensor.set(param='alpha', value=orient_values[orient_params.index('alpha')])
1839
1840
1841 elif orient_params[0] == 'beta':
1842 if errors:
1843 tensor.set(param='beta', value=orient_values[orient_params.index('beta')], category='err')
1844 else:
1845 tensor.set(param='beta', value=orient_values[orient_params.index('beta')])
1846
1847
1848 elif orient_params[0] == 'gamma':
1849 if errors:
1850 tensor.set(param='gamma', value=orient_values[orient_params.index('gamma')], category='err')
1851 else:
1852 tensor.set(param='gamma', value=orient_values[orient_params.index('gamma')])
1853
1854
1855 elif len(orient_params) == 2:
1856
1857 if orient_params.count('alpha') == 1 and orient_params.count('beta') == 1:
1858 if errors:
1859 tensor.set(param='alpha', value=orient_values[orient_params.index('alpha')], category='err')
1860 tensor.set(param='beta', value=orient_values[orient_params.index('beta')], category='err')
1861 else:
1862 tensor.set(param='alpha', value=orient_values[orient_params.index('alpha')])
1863 tensor.set(param='beta', value=orient_values[orient_params.index('beta')])
1864
1865
1866 if orient_params.count('alpha') == 1 and orient_params.count('gamma') == 1:
1867 if errors:
1868 tensor.set(param='alpha', value=orient_values[orient_params.index('alpha')], category='err')
1869 tensor.set(param='gamma', value=orient_values[orient_params.index('gamma')], category='err')
1870 else:
1871 tensor.set(param='alpha', value=orient_values[orient_params.index('alpha')])
1872 tensor.set(param='gamma', value=orient_values[orient_params.index('gamma')])
1873
1874
1875 if orient_params.count('beta') == 1 and orient_params.count('gamma') == 1:
1876 if errors:
1877 tensor.set(param='beta', value=orient_values[orient_params.index('beta')], category='err')
1878 tensor.set(param='gamma', value=orient_values[orient_params.index('gamma')], category='err')
1879 else:
1880 tensor.set(param='beta', value=orient_values[orient_params.index('beta')])
1881 tensor.set(param='gamma', value=orient_values[orient_params.index('gamma')])
1882
1883
1884 else:
1885 raise RelaxUnknownParamCombError('orientational parameter set', orient_params)
1886
1887
1888 elif len(orient_params) == 3:
1889
1890 if orient_params.count('alpha') == 1 and orient_params.count('beta') == 1:
1891 if errors:
1892 tensor.set(param='alpha', value=orient_values[orient_params.index('alpha')], category='err')
1893 tensor.set(param='beta', value=orient_values[orient_params.index('beta')], category='err')
1894 tensor.set(param='gamma', value=orient_values[orient_params.index('gamma')], category='err')
1895 else:
1896 tensor.set(param='alpha', value=orient_values[orient_params.index('alpha')])
1897 tensor.set(param='beta', value=orient_values[orient_params.index('beta')])
1898 tensor.set(param='gamma', value=orient_values[orient_params.index('gamma')])
1899
1900
1901 else:
1902 raise RelaxUnknownParamCombError('orientational parameter set', orient_params)
1903
1904
1905 elif len(orient_params) > 3:
1906 raise RelaxUnknownParamCombError('orientational parameter set', orient_params)
1907
1908
1909
1910
1911
1912 if orient_params:
1913 fold_angles()
1914
1915
1916 __set_prompt_doc__ = """
1917 Alignment tensor set details
1918 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1919
1920 If the alignment tensor has not been setup, use the more powerful function
1921 'alignment_tensor.init' to initialise the tensor parameters.
1922
1923 The alignment tensor parameters can only be set when the data pipe corresponds to model-free
1924 analysis. The units of the parameters are:
1925
1926 Unitless for Sxx, Syy, Szz, Sxxyy, Sxy, Sxz, Syz.
1927 Unitless for Axx, Ayy, Azz, Axxyy, Axy, Axz, Ayz.
1928 Unitless for Pxx, Pyy, Pzz, Pxxyy, Pxy, Pxz, Pyz.
1929 Radians for all angles (alpha, beta, gamma).
1930
1931 If a single geometric parameter is supplied, it must be one of Bxx, Byy, Bxy, Bxz, Byz, where B
1932 is one of S, A, or P. For the parameters Bzz and Bxxyy, it is not possible to determine how to
1933 use the currently set values together with the supplied value to calculate the new internal
1934 parameters. When supplying multiple geometric parameters, the set must belong to one of
1935
1936 {Sxx, Syy, Sxy, Sxz, Syz},
1937 {Szz, Sxxyy, Sxy, Sxz, Syz}.
1938 {Axx, Ayy, Axy, Axz, Ayz},
1939 {Azz, Axxyy, Axy, Axz, Ayz}.
1940 {Pxx, Pyy, Pxy, Pxz, Pyz},
1941 {Pzz, Pxxyy, Pxy, Pxz, Pyz}.
1942 """
1943
1944
1946 """Set the align ID string for the given tensor.
1947
1948 @keyword tensor: The alignment tensor label.
1949 @type tensor: str
1950 @keyword align_id: The alignment ID string.
1951 @type align_id: str
1952 """
1953
1954
1955 match = False
1956 for tensor_cont in cdp.align_tensors:
1957
1958 if tensor_cont.name == tensor:
1959 tensor_cont.align_id = align_id
1960 match = True
1961
1962
1963 if not match:
1964 raise RelaxNoTensorError('alignment', tensor)
1965
1966
1967 -def set_domain(tensor=None, domain=None):
1968 """Set the domain label for the given tensor.
1969
1970 @param tensor: The alignment tensor label.
1971 @type tensor: str
1972 @param domain: The domain label.
1973 @type domain: str
1974 """
1975
1976
1977 if not hasattr(cdp, 'domain') or domain not in cdp.domain.keys():
1978 raise RelaxError("The domain '%s' has not been defined. Please use the domain user function." % domain)
1979
1980
1981 match = False
1982 for tensor_cont in cdp.align_tensors:
1983
1984 if tensor_cont.name == tensor:
1985 tensor_cont.set(param='domain', value=domain)
1986 match = True
1987
1988
1989 if not match:
1990 raise RelaxNoTensorError('alignment', tensor)
1991
1992
1993 -def svd(basis_set=0, tensors=None):
1994 """Function for calculating the singular values of all the loaded tensors.
1995
1996 The matrix on which SVD will be performed is::
1997
1998 | Sxx1 Syy1 Sxy1 Sxz1 Syz1 |
1999 | Sxx2 Syy2 Sxy2 Sxz2 Syz2 |
2000 | Sxx3 Syy3 Sxy3 Sxz3 Syz3 |
2001 | . . . . . |
2002 | . . . . . |
2003 | . . . . . |
2004 | SxxN SyyN SxyN SxzN SyzN |
2005
2006 This is the default unitary basis set (selected when basis_set is 0). Alternatively a geometric
2007 basis set consisting of the stretching and skewing parameters Szz and Sxx-yy respectively
2008 replacing Sxx and Syy can be chosen by setting basis_set to 1. The matrix in this case is::
2009
2010 | Szz1 Sxxyy1 Sxy1 Sxz1 Syz1 |
2011 | Szz2 Sxxyy2 Sxy2 Sxz2 Syz2 |
2012 | Szz3 Sxxyy3 Sxy3 Sxz3 Syz3 |
2013 | . . . . . |
2014 | . . . . . |
2015 | . . . . . |
2016 | SzzN SxxyyN SxyN SxzN SyzN |
2017
2018 The relationships between the geometric and unitary basis sets are::
2019
2020 Szz = - Sxx - Syy,
2021 Sxxyy = Sxx - Syy,
2022
2023 The SVD values and condition number are dependendent upon the basis set chosen.
2024
2025
2026 @param basis_set: The basis set to create the 5 by n matrix on which to perform SVD.
2027 @type basis_set: int
2028 @param tensors: An array of tensors to apply SVD to. If None, all tensors will be used.
2029 @type tensors: None or array of str
2030 """
2031
2032
2033 if not hasattr(cdp, 'align_tensors') or len(cdp.align_tensors) == 0:
2034 raise RelaxNoTensorError('alignment')
2035
2036
2037 tensor_num = 0
2038 for tensor in cdp.align_tensors:
2039 if tensors and tensor.name not in tensors:
2040 continue
2041 tensor_num = tensor_num + 1
2042
2043
2044 matrix = zeros((tensor_num, 5), float64)
2045
2046
2047 i = 0
2048 for tensor in cdp.align_tensors:
2049
2050 if tensors and tensor.name not in tensors:
2051 continue
2052
2053
2054 if basis_set == 0:
2055 matrix[i, 0] = tensor.Sxx
2056 matrix[i, 1] = tensor.Syy
2057 matrix[i, 2] = tensor.Sxy
2058 matrix[i, 3] = tensor.Sxz
2059 matrix[i, 4] = tensor.Syz
2060
2061
2062 elif basis_set == 1:
2063 matrix[i, 0] = tensor.Szz
2064 matrix[i, 1] = tensor.Sxxyy
2065 matrix[i, 2] = tensor.Sxy
2066 matrix[i, 3] = tensor.Sxz
2067 matrix[i, 4] = tensor.Syz
2068
2069
2070 i = i + 1
2071
2072
2073 u, s, vh = linalg.svd(matrix)
2074
2075
2076 cdp.align_tensors.singular_vals = s
2077
2078
2079 cdp.align_tensors.cond_num = s[0] / s[-1]
2080
2081
2082 print("\nData pipe: " + repr(pipes.cdp_name()))
2083 print("\nSingular values:")
2084 for val in s:
2085 print(" %.4e" % val)
2086 print("\nCondition number: %.2f" % cdp.align_tensors.cond_num)
2087