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