1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Module for the support of diffusion tensors."""
25
26
27 from copy import deepcopy
28 from math import cos, pi, sin
29 from numpy import cross, float64, int32, ones, transpose, zeros
30 from numpy.linalg import norm, svd
31 from operator import itemgetter
32 from re import search
33 import string
34
35
36 from angles import wrap_angles
37 from data.diff_tensor import DiffTensorData
38 from generic_fns import pipes
39 from generic_fns.angles import fold_spherical_angles
40 from generic_fns.mol_res_spin import get_molecule_names, spin_loop
41 from maths_fns.coord_transform import cartesian_to_spherical
42 from maths_fns.rotation_matrix import R_to_euler_zyz
43 from physical_constants import element_from_isotope, number_from_isotope
44 from relax_errors import RelaxError, RelaxNoTensorError, RelaxStrError, RelaxTensorError, RelaxUnknownParamCombError, RelaxUnknownParamError
45
46
48 """Read the relaxation data from the NMR-STAR dictionary object.
49
50 @param star: The NMR-STAR dictionary object.
51 @type star: NMR_STAR instance
52 """
53
54
55 found = 0
56 for data in star.tensor.loop():
57
58 if data == None:
59 continue
60
61
62 if data['tensor_type'] != 'diffusion':
63 continue
64
65
66 found = found + 1
67
68
69 if not found:
70 return
71
72
73 if found != 1:
74 raise RelaxError("More than one diffusion tensor found.")
75
76
77 tensor = zeros((3, 3), float64)
78 tensor[0, 0] = data['tensor_11'][0]
79 tensor[0, 1] = data['tensor_12'][0]
80 tensor[0, 2] = data['tensor_13'][0]
81 tensor[1, 0] = data['tensor_21'][0]
82 tensor[1, 1] = data['tensor_22'][0]
83 tensor[1, 2] = data['tensor_23'][0]
84 tensor[2, 0] = data['tensor_31'][0]
85 tensor[2, 1] = data['tensor_32'][0]
86 tensor[2, 2] = data['tensor_33'][0]
87
88
89 Di, R, alpha, beta, gamma = tensor_eigen_system(tensor)
90
91
92 xy_match = False
93 epsilon = 1e-1
94 if abs(Di[0] - Di[1]) < epsilon:
95 xy_match = True
96
97
98 yz_match = False
99 if abs(Di[1] - Di[2]) < epsilon:
100 yz_match = True
101
102
103 if xy_match and yz_match:
104 shape = ['sphere']
105 elif xy_match:
106 shape = ['spheroid', 'prolate spheroid']
107 type = 'prolate'
108 Dpar = Di[2]
109 Dper = Di[0]
110 elif yz_match:
111 shape = ['spheroid', 'oblate spheroid']
112 type = 'oblate'
113 Dpar = Di[0]
114 Dper = Di[2]
115 else:
116 shape = ['ellipsoid']
117
118
119 if data['geometric_shape'] not in shape:
120 raise RelaxError("The tensor with eigenvalues %s does not match the %s geometric shape." % (Di, shape[0]))
121
122
123 cdp.diff_tensor = DiffTensorData()
124
125
126 cdp.diff_tensor.fixed = True
127
128
129 if data['geometric_shape'] == 'sphere':
130 sphere(params=Di[0], d_scale=1.0, param_types=1)
131
132
133 elif data['geometric_shape'] in ['spheroid', 'oblate spheroid', 'prolate spheroid']:
134
135 theta = data['axial_sym_axis_polar_angle'][0]
136 phi = data['axial_sym_axis_azimuthal_angle'][0]
137
138
139 spheroid(params=(Dpar, Dper, theta, phi), d_scale=1.0, param_types=3, spheroid_type=type)
140
141
142 elif data['geometric_shape'] == 'ellipsoid':
143 ellipsoid(params=(Di[0], Di[1], Di[2], alpha, beta, gamma), d_scale=1.0, param_types=3)
144
145
147 """Generate the diffusion tensor saveframes for the NMR-STAR dictionary object.
148
149 @param star: The NMR-STAR dictionary object.
150 @type star: NMR_STAR instance
151 """
152
153
154 cdp = pipes.get_pipe()
155
156
157 mol_name_list = []
158 res_num_list = []
159 res_name_list = []
160 atom_name_list = []
161 isotope_list = []
162 element_list = []
163 attached_atom_name_list = []
164 attached_isotope_list = []
165 attached_element_list = []
166
167
168 for spin, mol_name, res_num, res_name, spin_id in spin_loop(full_info=True, return_id=True):
169
170 if not spin.select:
171 continue
172
173
174 if res_num == None:
175 raise RelaxError("For the BMRB, the residue of spin '%s' must be numbered." % spin_id)
176 if res_name == None:
177 raise RelaxError("For the BMRB, the residue of spin '%s' must be named." % spin_id)
178 if spin.name == None:
179 raise RelaxError("For the BMRB, the spin '%s' must be named." % spin_id)
180 if spin.heteronuc_type == None:
181 raise RelaxError("For the BMRB, the spin isotope type of '%s' must be specified." % spin_id)
182
183
184 mol_name_list.append(mol_name)
185 res_num_list.append(str(res_num))
186 res_name_list.append(str(res_name))
187 atom_name_list.append(str(spin.name))
188
189
190 if hasattr(spin, 'attached_atom'):
191 attached_atom_name_list.append(str(spin.attached_atom))
192 else:
193 attached_atom_name_list.append(str(spin.attached_proton))
194 attached_element_list.append(element_from_isotope(spin.proton_type))
195 attached_isotope_list.append(str(number_from_isotope(spin.proton_type)))
196
197
198 isotope_list.append(int(string.strip(spin.heteronuc_type, string.ascii_letters)))
199 element_list.append(spin.element)
200
201
202 entity_ids = zeros(len(mol_name_list), int32)
203 mol_names = get_molecule_names()
204 for i in range(len(mol_name_list)):
205 for j in range(len(mol_names)):
206 if mol_name_list[i] == mol_names[j]:
207 entity_ids[i] = j+1
208
209
210 geometric_shape = cdp.diff_tensor.type
211 if geometric_shape == 'spheroid':
212 geometric_shape = "%s %s" % (cdp.diff_tensor.spheroid_type, geometric_shape)
213
214
215 shapes = ['sphere', 'oblate spheroid', 'prolate spheroid', 'ellipsoid']
216 sym = ['isotropic', 'axial symmetry', 'axial symmetry', 'rhombic']
217 for i in range(len(shapes)):
218 if geometric_shape == shapes[i]:
219 tensor_symmetry = sym[i]
220
221
222 theta = None
223 phi = None
224 if tensor_symmetry == 'axial symmetry':
225 theta = cdp.diff_tensor.theta
226 phi = cdp.diff_tensor.phi
227
228
229 alpha, beta, gamma = None, None, None
230 if tensor_symmetry == 'rhombic':
231 alpha = cdp.diff_tensor.alpha
232 beta = cdp.diff_tensor.beta
233 gamma = cdp.diff_tensor.gamma
234
235
236 Diso = cdp.diff_tensor.Diso
237 Da = None
238 Dr = None
239 if tensor_symmetry == 'axial symmetry':
240 Da = cdp.diff_tensor.Da
241 elif tensor_symmetry == 'rhombic':
242 Dr = cdp.diff_tensor.Dr
243
244
245 tensor_11 = cdp.diff_tensor.tensor[0, 0]
246 tensor_12 = cdp.diff_tensor.tensor[0, 1]
247 tensor_13 = cdp.diff_tensor.tensor[0, 2]
248 tensor_21 = cdp.diff_tensor.tensor[1, 0]
249 tensor_22 = cdp.diff_tensor.tensor[1, 1]
250 tensor_23 = cdp.diff_tensor.tensor[1, 2]
251 tensor_31 = cdp.diff_tensor.tensor[2, 0]
252 tensor_32 = cdp.diff_tensor.tensor[2, 1]
253 tensor_33 = cdp.diff_tensor.tensor[2, 2]
254
255
256
257 star.tensor.add(tensor_type='diffusion', euler_type='zyz', geometric_shape=geometric_shape, tensor_symmetry=tensor_symmetry, matrix_val_units='s-1', angle_units='rad', iso_val_formula='Diso = 1/(6.tm)', aniso_val_formula='Da = Dpar - Dper', rhomb_val_formula='Dr = (Dy - Dx)/2Da', entity_ids=entity_ids, res_nums=res_num_list, res_names=res_name_list, atom_names=atom_name_list, atom_types=element_list, isotope=isotope_list, axial_sym_axis_polar_angle=theta, axial_sym_axis_azimuthal_angle=phi, iso_val=Diso, aniso_val=Da, rhombic_val=Dr, euler_alpha=alpha, euler_beta=beta, euler_gamma=gamma, tensor_11=tensor_11, tensor_12=tensor_12, tensor_13=tensor_13, tensor_21=tensor_21, tensor_22=tensor_22, tensor_23=tensor_23, tensor_31=tensor_31, tensor_32=tensor_32, tensor_33=tensor_33)
258
259
260
261 -def copy(pipe_from=None, pipe_to=None):
262 """Function for copying diffusion tensor data from one data pipe to another.
263
264 @param pipe_from: The data pipe to copy the diffusion tensor data from. This defaults to the
265 current data pipe.
266 @type pipe_from: str
267 @param pipe_to: The data pipe to copy the diffusion tensor data to. This defaults to the
268 current data pipe.
269 @type pipe_to: str
270 """
271
272
273 if pipe_from == None and pipe_to == None:
274 raise RelaxError("The pipe_from and pipe_to arguments cannot both be set to None.")
275 elif pipe_from == None:
276 pipe_from = pipes.cdp_name()
277 elif pipe_to == None:
278 pipe_to = pipes.cdp_name()
279
280
281 pipes.test(pipe_from)
282 pipes.test(pipe_to)
283
284
285 dp_from = pipes.get_pipe(pipe_from)
286 dp_to = pipes.get_pipe(pipe_to)
287
288
289 if not diff_data_exists(pipe_from):
290 raise RelaxNoTensorError('diffusion')
291
292
293 if diff_data_exists(pipe_to):
294 raise RelaxTensorError('diffusion')
295
296
297 dp_to.diff_tensor = deepcopy(dp_from.diff_tensor)
298
299
301 """Function for returning a list of names of data structures associated with the sequence."""
302
303 names = [ 'diff_type',
304 'diff_params' ]
305
306 return names
307
308
310 """Return the default values for the diffusion tensor parameters.
311
312 @param param: The name of the parameter.
313 @type param: str
314 @return: The default value.
315 @rtype: float
316 """
317
318
319 if param == 'tm':
320 return 10.0 * 1e-9
321
322
323 elif param == 'Diso' or param == 'Dx' or param == 'Dy' or param == 'Dz' or param == 'Dpar' or param == 'Dper':
324 return 1.666 * 1e7
325
326
327 elif param == 'Da' or param == 'Dr':
328 return 0.0
329
330
331 elif param == 'Dratio':
332 return 1.0
333
334
335 elif param == 'alpha' or param == 'beta' or param == 'gamma' or param == 'theta' or param == 'phi':
336 return 0.0
337
338
339 __default_value_prompt_doc__ = ["Diffusion tensor parameter default values", """
340 ________________________________________________________________________
341 | | | |
342 | Data type | Object name | Value |
343 |________________________|____________________|________________________|
344 | | | |
345 | tm | 'tm' | 10 * 1e-9 |
346 | | | |
347 | Diso | 'Diso' | 1.666 * 1e7 |
348 | | | |
349 | Da | 'Da' | 0.0 |
350 | | | |
351 | Dr | 'Dr' | 0.0 |
352 | | | |
353 | Dx | 'Dx' | 1.666 * 1e7 |
354 | | | |
355 | Dy | 'Dy' | 1.666 * 1e7 |
356 | | | |
357 | Dz | 'Dz' | 1.666 * 1e7 |
358 | | | |
359 | Dpar | 'Dpar' | 1.666 * 1e7 |
360 | | | |
361 | Dper | 'Dper' | 1.666 * 1e7 |
362 | | | |
363 | Dratio | 'Dratio' | 1.0 |
364 | | | |
365 | alpha | 'alpha' | 0.0 |
366 | | | |
367 | beta | 'beta' | 0.0 |
368 | | | |
369 | gamma | 'gamma' | 0.0 |
370 | | | |
371 | theta | 'theta' | 0.0 |
372 | | | |
373 | phi | 'phi' | 0.0 |
374 |________________________|____________________|________________________|
375 """]
376
377
390
391
393 """Function for determining if diffusion data exists in the current data pipe.
394
395 @param pipe: The data pipe to search for data in.
396 @type pipe: str
397 @return: The answer to the question.
398 @rtype: bool
399 """
400
401
402 if pipe == None:
403 pipe = pipes.cdp_name()
404
405
406 dp = pipes.get_pipe(pipe)
407
408
409 if hasattr(dp, 'diff_tensor'):
410 return True
411 else:
412 return False
413
414
416 """Function for displaying the diffusion tensor."""
417
418
419 pipes.test()
420
421
422 if not diff_data_exists():
423 raise RelaxNoTensorError('diffusion')
424
425
426 if cdp.diff_tensor.type == 'sphere':
427
428 print("Type: Spherical diffusion")
429
430
431 print("\nParameters {tm}.")
432 print(("tm (s): " + repr(cdp.diff_tensor.tm)))
433
434
435 print("\nAlternate parameters {Diso}.")
436 print(("Diso (1/s): " + repr(cdp.diff_tensor.Diso)))
437
438
439 print(("\nFixed: " + repr(cdp.diff_tensor.fixed)))
440
441
442 elif cdp.diff_tensor.type == 'spheroid':
443
444 print("Type: Spheroidal diffusion")
445
446
447 print("\nParameters {tm, Da, theta, phi}.")
448 print(("tm (s): " + repr(cdp.diff_tensor.tm)))
449 print(("Da (1/s): " + repr(cdp.diff_tensor.Da)))
450 print(("theta (rad): " + repr(cdp.diff_tensor.theta)))
451 print(("phi (rad): " + repr(cdp.diff_tensor.phi)))
452
453
454 print("\nAlternate parameters {Diso, Da, theta, phi}.")
455 print(("Diso (1/s): " + repr(cdp.diff_tensor.Diso)))
456 print(("Da (1/s): " + repr(cdp.diff_tensor.Da)))
457 print(("theta (rad): " + repr(cdp.diff_tensor.theta)))
458 print(("phi (rad): " + repr(cdp.diff_tensor.phi)))
459
460
461 print("\nAlternate parameters {Dpar, Dper, theta, phi}.")
462 print(("Dpar (1/s): " + repr(cdp.diff_tensor.Dpar)))
463 print(("Dper (1/s): " + repr(cdp.diff_tensor.Dper)))
464 print(("theta (rad): " + repr(cdp.diff_tensor.theta)))
465 print(("phi (rad): " + repr(cdp.diff_tensor.phi)))
466
467
468 print("\nAlternate parameters {tm, Dratio, theta, phi}.")
469 print(("tm (s): " + repr(cdp.diff_tensor.tm)))
470 print(("Dratio: " + repr(cdp.diff_tensor.Dratio)))
471 print(("theta (rad): " + repr(cdp.diff_tensor.theta)))
472 print(("phi (rad): " + repr(cdp.diff_tensor.phi)))
473
474
475 print(("\nFixed: " + repr(cdp.diff_tensor.fixed)))
476
477
478 elif cdp.diff_tensor.type == 'ellipsoid':
479
480 print("Type: Ellipsoidal diffusion")
481
482
483 print("\nParameters {tm, Da, Dr, alpha, beta, gamma}.")
484 print(("tm (s): " + repr(cdp.diff_tensor.tm)))
485 print(("Da (1/s): " + repr(cdp.diff_tensor.Da)))
486 print(("Dr: " + repr(cdp.diff_tensor.Dr)))
487 print(("alpha (rad): " + repr(cdp.diff_tensor.alpha)))
488 print(("beta (rad): " + repr(cdp.diff_tensor.beta)))
489 print(("gamma (rad): " + repr(cdp.diff_tensor.gamma)))
490
491
492 print("\nAlternate parameters {Diso, Da, Dr, alpha, beta, gamma}.")
493 print(("Diso (1/s): " + repr(cdp.diff_tensor.Diso)))
494 print(("Da (1/s): " + repr(cdp.diff_tensor.Da)))
495 print(("Dr: " + repr(cdp.diff_tensor.Dr)))
496 print(("alpha (rad): " + repr(cdp.diff_tensor.alpha)))
497 print(("beta (rad): " + repr(cdp.diff_tensor.beta)))
498 print(("gamma (rad): " + repr(cdp.diff_tensor.gamma)))
499
500
501 print("\nAlternate parameters {Dx, Dy, Dz, alpha, beta, gamma}.")
502 print(("Dx (1/s): " + repr(cdp.diff_tensor.Dx)))
503 print(("Dy (1/s): " + repr(cdp.diff_tensor.Dy)))
504 print(("Dz (1/s): " + repr(cdp.diff_tensor.Dz)))
505 print(("alpha (rad): " + repr(cdp.diff_tensor.alpha)))
506 print(("beta (rad): " + repr(cdp.diff_tensor.beta)))
507 print(("gamma (rad): " + repr(cdp.diff_tensor.gamma)))
508
509
510 print(("\nFixed: " + repr(cdp.diff_tensor.fixed)))
511
512
513 -def ellipsoid(params=None, time_scale=None, d_scale=None, angle_units=None, param_types=None):
514 """Function for setting up a ellipsoidal diffusion tensor.
515
516 @param params: The diffusion tensor parameter.
517 @type params: float
518 @param time_scale: The correlation time scaling value.
519 @type time_scale: float
520 @param d_scale: The diffusion tensor eigenvalue scaling value.
521 @type d_scale: float
522 @param angle_units: The units for the angle parameters which can be either 'deg' or 'rad'.
523 @type angle_units: str
524 @param param_types: The type of parameters supplied. These correspond to 0: {tm, Da, theta,
525 phi}, 1: {Diso, Da, theta, phi}, 2: {tm, Dratio, theta, phi}, 3: {Dpar,
526 Dper, theta, phi}, 4: {Diso, Dratio, theta, phi}.
527 @type param_types: int
528 """
529
530
531 cdp.diff_tensor.type = 'ellipsoid'
532
533
534 if param_types == 0:
535
536 tm, Da, Dr, alpha, beta, gamma = params
537
538
539 tm = tm * time_scale
540 Da = Da * d_scale
541
542
543 set(value=[tm, Da, Dr], param=['tm', 'Da', 'Dr'])
544
545
546 elif param_types == 1:
547
548 Diso, Da, Dr, alpha, beta, gamma = params
549
550
551 Diso = Diso * d_scale
552 Da = Da * d_scale
553
554
555 set(value=[Diso, Da, Dr], param=['Diso', 'Da', 'Dr'])
556
557
558 elif param_types == 2:
559
560 Dx, Dy, Dz, alpha, beta, gamma = params
561
562
563 Dx = Dx * d_scale
564 Dy = Dy * d_scale
565 Dz = Dz * d_scale
566
567
568 set(value=[Dx, Dy, Dz], param=['Dx', 'Dy', 'Dz'])
569
570
571 elif param_types == 3:
572
573 Dxx, Dyy, Dzz, Dxy, Dxz, Dyz = params
574
575
576 tensor = zeros((3, 3), float64)
577 tensor[0, 0] = Dxx
578 tensor[1, 1] = Dyy
579 tensor[2, 2] = Dzz
580 tensor[0, 1] = tensor[1, 0] = Dxy
581 tensor[0, 2] = tensor[2, 0] = Dxz
582 tensor[1, 2] = tensor[2, 1] = Dyz
583
584
585 tensor = tensor * d_scale
586
587
588 Di, R, alpha, beta, gamma = tensor_eigen_system(tensor)
589
590
591 set(value=[Di[0], Di[1], Di[2]], param=['Dx', 'Dy', 'Dz'])
592
593
594 angle_units = 'rad'
595
596
597 else:
598 raise RelaxUnknownParamCombError('param_types', param_types)
599
600
601 if angle_units == 'deg':
602 print("Converting the angles from degrees to radian units.")
603 alpha = (alpha / 360.0) * 2.0 * pi
604 beta = (beta / 360.0) * 2.0 * pi
605 gamma = (gamma / 360.0) * 2.0 * pi
606
607
608 set(value=[alpha, beta, gamma], param=['alpha', 'beta', 'gamma'])
609
610
612 """Wrap the Euler or spherical angles and remove the glide reflection and translational symmetries.
613
614 Wrap the angles such that::
615
616 0 <= theta <= pi,
617 0 <= phi <= 2pi,
618
619 and::
620
621 0 <= alpha <= 2pi,
622 0 <= beta <= pi,
623 0 <= gamma <= 2pi.
624
625
626 For the simulated values, the angles are wrapped as::
627
628 theta - pi/2 <= theta_sim <= theta + pi/2
629 phi - pi <= phi_sim <= phi + pi
630
631 and::
632
633 alpha - pi <= alpha_sim <= alpha + pi
634 beta - pi/2 <= beta_sim <= beta + pi/2
635 gamma - pi <= gamma_sim <= gamma + pi
636
637
638 @param sim_index: The simulation index. If set to None then the actual values will be folded
639 rather than the simulation values.
640 @type sim_index: int or None
641 """
642
643
644
645
646
647
648 if cdp.diff_tensor.type == 'spheroid':
649
650 theta = cdp.diff_tensor.theta
651 phi = cdp.diff_tensor.phi
652
653
654 if sim_index != None:
655 theta_sim = cdp.diff_tensor.theta_sim[sim_index]
656 phi_sim = cdp.diff_tensor.phi_sim[sim_index]
657
658
659 if sim_index == None:
660 cdp.diff_tensor.theta = wrap_angles(theta, 0.0, 2.0*pi)
661 cdp.diff_tensor.phi = wrap_angles(phi, 0.0, 2.0*pi)
662
663
664 else:
665 cdp.diff_tensor.theta_sim[sim_index] = wrap_angles(theta_sim, theta - pi, theta + pi)
666 cdp.diff_tensor.phi_sim[sim_index] = wrap_angles(phi_sim, phi - pi, phi + pi)
667
668
669 elif cdp.diff_tensor.type == 'ellipsoid':
670
671 alpha = cdp.diff_tensor.alpha
672 beta = cdp.diff_tensor.beta
673 gamma = cdp.diff_tensor.gamma
674
675
676 if sim_index != None:
677 alpha_sim = cdp.diff_tensor.alpha_sim[sim_index]
678 beta_sim = cdp.diff_tensor.beta_sim[sim_index]
679 gamma_sim = cdp.diff_tensor.gamma_sim[sim_index]
680
681
682 if sim_index == None:
683 cdp.diff_tensor.alpha = wrap_angles(alpha, 0.0, 2.0*pi)
684 cdp.diff_tensor.beta = wrap_angles(beta, 0.0, 2.0*pi)
685 cdp.diff_tensor.gamma = wrap_angles(gamma, 0.0, 2.0*pi)
686
687
688 else:
689 cdp.diff_tensor.alpha_sim[sim_index] = wrap_angles(alpha_sim, alpha - pi, alpha + pi)
690 cdp.diff_tensor.beta_sim[sim_index] = wrap_angles(beta_sim, beta - pi, beta + pi)
691 cdp.diff_tensor.gamma_sim[sim_index] = wrap_angles(gamma_sim, gamma - pi, gamma + pi)
692
693
694
695
696
697
698 if cdp.diff_tensor.type == 'spheroid':
699
700 if sim_index == None:
701
702 if cdp.diff_tensor.phi >= pi:
703 theta, phi = fold_spherical_angles(cdp.diff_tensor.theta, cdp.diff_tensor.phi)
704 cdp.diff_tensor.theta = theta
705 cdp.diff_tensor.phi = phi
706
707
708 else:
709
710 if cdp.diff_tensor.phi_sim[sim_index] >= cdp.diff_tensor.phi + pi/2.0:
711 cdp.diff_tensor.theta_sim[sim_index] = pi - cdp.diff_tensor.theta_sim[sim_index]
712 cdp.diff_tensor.phi_sim[sim_index] = cdp.diff_tensor.phi_sim[sim_index] - pi
713 elif cdp.diff_tensor.phi_sim[sim_index] <= cdp.diff_tensor.phi - pi/2.0:
714 cdp.diff_tensor.theta_sim[sim_index] = pi - cdp.diff_tensor.theta_sim[sim_index]
715 cdp.diff_tensor.phi_sim[sim_index] = cdp.diff_tensor.phi_sim[sim_index] + pi
716
717
718 elif cdp.diff_tensor.type == 'ellipsoid':
719
720 if sim_index == None:
721
722 if cdp.diff_tensor.alpha >= pi:
723 cdp.diff_tensor.alpha = cdp.diff_tensor.alpha - pi
724
725
726 if cdp.diff_tensor.beta >= pi:
727 cdp.diff_tensor.alpha = pi - cdp.diff_tensor.alpha
728 cdp.diff_tensor.beta = cdp.diff_tensor.beta - pi
729
730
731 if cdp.diff_tensor.gamma >= pi:
732 cdp.diff_tensor.alpha = pi - cdp.diff_tensor.alpha
733 cdp.diff_tensor.beta = pi - cdp.diff_tensor.beta
734 cdp.diff_tensor.gamma = cdp.diff_tensor.gamma - pi
735
736
737 else:
738
739 if cdp.diff_tensor.alpha_sim[sim_index] >= cdp.diff_tensor.alpha + pi/2.0:
740 cdp.diff_tensor.alpha_sim[sim_index] = cdp.diff_tensor.alpha_sim[sim_index] - pi
741 elif cdp.diff_tensor.alpha_sim[sim_index] <= cdp.diff_tensor.alpha - pi/2.0:
742 cdp.diff_tensor.alpha_sim[sim_index] = cdp.diff_tensor.alpha_sim[sim_index] + pi
743
744
745 if cdp.diff_tensor.beta_sim[sim_index] >= cdp.diff_tensor.beta + pi/2.0:
746 cdp.diff_tensor.alpha_sim[sim_index] = pi - cdp.diff_tensor.alpha_sim[sim_index]
747 cdp.diff_tensor.beta_sim[sim_index] = cdp.diff_tensor.beta_sim[sim_index] - pi
748 elif cdp.diff_tensor.beta_sim[sim_index] <= cdp.diff_tensor.beta - pi/2.0:
749 cdp.diff_tensor.alpha_sim[sim_index] = pi - cdp.diff_tensor.alpha_sim[sim_index]
750 cdp.diff_tensor.beta_sim[sim_index] = cdp.diff_tensor.beta_sim[sim_index] + pi
751
752
753 if cdp.diff_tensor.gamma_sim[sim_index] >= cdp.diff_tensor.gamma + pi/2.0:
754 cdp.diff_tensor.alpha_sim[sim_index] = pi - cdp.diff_tensor.alpha_sim[sim_index]
755 cdp.diff_tensor.beta_sim[sim_index] = pi - cdp.diff_tensor.beta_sim[sim_index]
756 cdp.diff_tensor.gamma_sim[sim_index] = cdp.diff_tensor.gamma_sim[sim_index] - pi
757 elif cdp.diff_tensor.gamma_sim[sim_index] <= cdp.diff_tensor.gamma - pi/2.0:
758 cdp.diff_tensor.alpha_sim[sim_index] = pi - cdp.diff_tensor.alpha_sim[sim_index]
759 cdp.diff_tensor.beta_sim[sim_index] = pi - cdp.diff_tensor.beta_sim[sim_index]
760 cdp.diff_tensor.gamma_sim[sim_index] = cdp.diff_tensor.gamma_sim[sim_index] + pi
761
762
763 -def init(params=None, time_scale=1.0, d_scale=1.0, angle_units='deg', param_types=0, spheroid_type=None, fixed=1):
764 """Function for initialising the diffusion tensor.
765
766 @param params: The diffusion tensor parameters.
767 @type params: float
768 @param time_scale: The correlation time scaling value.
769 @type time_scale: float
770 @param d_scale: The diffusion tensor eigenvalue scaling value.
771 @type d_scale: float
772 @param angle_units: The units for the angle parameters.
773 @type angle_units: str (either 'deg' or 'rad')
774 @param param_types: The type of parameters supplied. For spherical diffusion, the flag
775 values correspond to 0: tm, 1: Diso. For spheroidal diffusion, 0: {tm,
776 Da, theta, phi}, 1: {Diso, Da, theta, phi}, 2: {tm, Dratio, theta, phi},
777 3: {Dpar, Dper, theta, phi}, 4: {Diso, Dratio, theta, phi}. For
778 ellipsoidal diffusion, 0: {tm, Da, Dr, alpha, beta, gamma}, 1: {Diso,
779 Da, Dr, alpha, beta, gamma}, 2: {Dx, Dy, Dz, alpha, beta, gamma}.
780 @type param_types: int
781 @param spheroid_type: A string which, if supplied together with spheroid parameters, will
782 restrict the tensor to either being 'oblate' or 'prolate'.
783 @type spheroid_type: str
784 @param fixed: A flag specifying whether the diffusion tensor is fixed or can be
785 optimised.
786 @type fixed: bin
787 """
788
789
790 pipes.test()
791
792
793 if diff_data_exists():
794 raise RelaxTensorError('diffusion')
795
796
797 valid_types = ['deg', 'rad']
798 if not angle_units in valid_types:
799 raise RelaxError("The diffusion tensor 'angle_units' argument " + repr(angle_units) + " should be either 'deg' or 'rad'.")
800
801
802 cdp.diff_tensor = DiffTensorData()
803
804
805 cdp.diff_tensor.fixed = fixed
806
807
808 if isinstance(params, float):
809 num_params = 1
810 sphere(params, time_scale, param_types)
811
812
813 elif (isinstance(params, tuple) or isinstance(params, list)) and len(params) == 4:
814 num_params = 4
815 spheroid(params, time_scale, d_scale, angle_units, param_types, spheroid_type)
816
817
818 elif (isinstance(params, tuple) or isinstance(params, list)) and len(params) == 6:
819 num_params = 6
820 ellipsoid(params, time_scale, d_scale, angle_units, param_types)
821
822
823 else:
824 raise RelaxError("The diffusion tensor parameters " + repr(params) + " are of an unknown type.")
825
826
827 test_params(num_params)
828
829
831 """The function for creating bounds for the mapping function.
832
833 @param param: The name of the parameter to return the bounds for.
834 @type param: str
835 @keyword spin_id: The spin identification string. This arg is unused.
836 @type spin_id: None or str
837 @return: The bounds for the parameter.
838 @rtype: list of len 2 of floats
839 """
840
841
842 if param == 'tm':
843 return [0, 10.0 * 1e-9]
844
845
846 if param == 'Diso' or param == 'Dx' or param == 'Dy' or param == 'Dz' or param == 'Dpar' or param == 'Dper':
847 return [1e6, 1e7]
848
849
850 if param == 'Da':
851 return [-3.0/2.0 * 1e7, 3.0 * 1e7]
852
853
854 if param == 'Dr':
855 return [0, 1]
856
857
858 if param == 'Dratio':
859 return [1.0/3.0, 3.0]
860
861
862 if param == 'theta':
863 return [0, pi]
864
865
866 if param == 'phi':
867 return [0, 2*pi]
868
869
870 if param == 'alpha':
871 return [0, 2*pi]
872
873
874 if param == 'beta':
875 return [0, pi]
876
877
878 if param == 'gamma':
879 return [0, 2*pi]
880
881
883 """Function for creating labels, tick locations, and tick values for an OpenDX map."""
884
885
886 labels = "{"
887 tick_locations = []
888 tick_values = []
889 n = len(params)
890 axis_incs = 5
891 loc_inc = inc / axis_incs
892
893
894 for i in xrange(n):
895
896 factor = return_conversion_factor(params[swap[i]])
897
898
899 units = return_units(params[swap[i]])
900
901
902 if units:
903 labels = labels + "\"" + params[swap[i]] + " (" + units + ")\""
904 else:
905 labels = labels + "\"" + params[swap[i]] + "\""
906
907
908 vals = bounds[swap[i], 0] / factor
909 val_inc = (bounds[swap[i], 1] - bounds[swap[i], 0]) / (axis_incs * factor)
910
911 if i < n - 1:
912 labels = labels + " "
913 else:
914 labels = labels + "}"
915
916
917 string = "{"
918 val = 0.0
919 for j in xrange(axis_incs + 1):
920 string = string + " " + repr(val)
921 val = val + loc_inc
922 string = string + " }"
923 tick_locations.append(string)
924
925
926 string = "{"
927 for j in xrange(axis_incs + 1):
928 string = string + "\"" + "%.2f" % vals + "\" "
929 vals = vals + val_inc
930 string = string + "}"
931 tick_values.append(string)
932
933 return labels, tick_locations, tick_values
934
935
937 """Function for returning the factor of conversion between different parameter units.
938
939 For example, the internal representation of tm is in seconds, whereas the external
940 representation is in nanoseconds, therefore this function will return 1e-9 for tm.
941
942
943 @param param: The name of the parameter to return the conversion factor for.
944 @type param: str
945 @return: The conversion factor.
946 @rtype: float
947 """
948
949
950 object_name = return_data_name(param)
951
952
953 if object_name == 'tm':
954 return 1e-9
955
956
957 if object_name in ['Diso', 'Da', 'Dx', 'Dy', 'Dz', 'Dpar', 'Dper']:
958 return 1e6
959
960
961 if object_name in ['theta', 'phi', 'alpha', 'beta', 'gamma']:
962 return (2.0*pi) / 360.0
963
964
965 return 1.0
966
967
969 """Return the parameter name.
970
971 @param name: The name of the parameter to return the name of.
972 @type name: str
973 @return: The parameter name.
974 @rtype: str
975 """
976
977
978 if not isinstance(name, str):
979 raise RelaxStrError('name', name)
980
981
982 if search('^tm$', name):
983 return 'tm'
984
985
986 if search('[Dd]iso', name):
987 return 'Diso'
988
989
990 if search('[Dd]a', name):
991 return 'Da'
992
993
994 if search('[Dd]r$', name):
995 return 'Dr'
996
997
998 if search('[Dd]x', name):
999 return 'Dx'
1000
1001
1002 if search('[Dd]y', name):
1003 return 'Dy'
1004
1005
1006 if search('[Dd]z', name):
1007 return 'Dz'
1008
1009
1010 if search('[Dd]par', name):
1011 return 'Dpar'
1012
1013
1014 if search('[Dd]per', name):
1015 return 'Dper'
1016
1017
1018 if search('[Dd]ratio', name):
1019 return 'Dratio'
1020
1021
1022 if search('^a$', name) or search('alpha', name):
1023 return 'alpha'
1024
1025
1026 if search('^b$', name) or search('beta', name):
1027 return 'beta'
1028
1029
1030 if search('^g$', name) or search('gamma', name):
1031 return 'gamma'
1032
1033
1034 if search('theta', name):
1035 return 'theta'
1036
1037
1038 if search('phi', name):
1039 return 'phi'
1040
1041
1042 __return_data_name_prompt_doc__ = ["Diffusion tensor parameter string matching patterns", """
1043 ____________________________________________________________________________________________
1044 | | | |
1045 | Data type | Object name | Patterns |
1046 |________________________________________________________|______________|__________________|
1047 | | | |
1048 | Global correlation time - tm | 'tm' | '^tm$' |
1049 | | | |
1050 | Isotropic component of the diffusion tensor - Diso | 'Diso' | '[Dd]iso' |
1051 | | | |
1052 | Anisotropic component of the diffusion tensor - Da | 'Da' | '[Dd]a' |
1053 | | | |
1054 | Rhombic component of the diffusion tensor - Dr | 'Dr' | '[Dd]r$' |
1055 | | | |
1056 | Eigenvalue associated with the x-axis of the diffusion | 'Dx' | '[Dd]x' |
1057 | diffusion tensor - Dx | | |
1058 | | | |
1059 | Eigenvalue associated with the y-axis of the diffusion | 'Dy' | '[Dd]y' |
1060 | diffusion tensor - Dy | | |
1061 | | | |
1062 | Eigenvalue associated with the z-axis of the diffusion | 'Dz' | '[Dd]z' |
1063 | diffusion tensor - Dz | | |
1064 | | | |
1065 | Diffusion coefficient parallel to the major axis of | 'Dpar' | '[Dd]par' |
1066 | the spheroid diffusion tensor - Dpar | | |
1067 | | | |
1068 | Diffusion coefficient perpendicular to the major axis | 'Dper' | '[Dd]per' |
1069 | of the spheroid diffusion tensor - Dper | | |
1070 | | | |
1071 | Ratio of the parallel and perpendicular components of | 'Dratio' | '[Dd]ratio' |
1072 | the spheroid diffusion tensor - Dratio | | |
1073 | | | |
1074 | The first Euler angle of the ellipsoid diffusion | 'alpha' | '^a$' or 'alpha' |
1075 | tensor - alpha | | |
1076 | | | |
1077 | The second Euler angle of the ellipsoid diffusion | 'beta' | '^b$' or 'beta' |
1078 | tensor - beta | | |
1079 | | | |
1080 | The third Euler angle of the ellipsoid diffusion | 'gamma' | '^g$' or 'gamma' |
1081 | tensor - gamma | | |
1082 | | | |
1083 | The polar angle defining the major axis of the | 'theta' | 'theta' |
1084 | spheroid diffusion tensor - theta | | |
1085 | | | |
1086 | The azimuthal angle defining the major axis of the | 'phi' | 'phi' |
1087 | spheroid diffusion tensor - phi | | |
1088 |________________________________________________________|______________|__________________|
1089 """]
1090
1091
1093 """Function for returning Dx, Dy, and Dz."""
1094
1095
1096 data = cdp.diff_tensor
1097
1098
1099 Diso = 1.0 / (6.0 * data.tm)
1100
1101
1102 Dx = Diso - 1.0/3.0 * data.Da * (1.0 + 3.0 * data.Dr)
1103
1104
1105 Dy = Diso - 1.0/3.0 * data.Da * (1.0 - 3.0 * data.Dr)
1106
1107
1108 Dz = Diso + 2.0/3.0 * data.Da
1109
1110
1111 return Dx, Dy, Dz
1112
1113
1115 """Function for returning a string representing the parameters units.
1116
1117 For example, the internal representation of tm is in seconds, whereas the external
1118 representation is in nanoseconds, therefore this function will return the string
1119 'nanoseconds' for tm.
1120
1121
1122 @param param: The name of the parameter to return the units for.
1123 @type param: str
1124 @return: The parameter units string.
1125 @rtype: str
1126 """
1127
1128
1129 object_name = return_data_name(param)
1130
1131
1132 if object_name == 'tm':
1133 return 'ns'
1134
1135
1136 if object_name in ['Diso', 'Da', 'Dx', 'Dy', 'Dz', 'Dpar', 'Dper']:
1137 return '1e6 1/s'
1138
1139
1140 if object_name in ['theta', 'phi', 'alpha', 'beta', 'gamma']:
1141 return 'deg'
1142
1143
1144 -def set(value=None, param=None):
1145 """Set the diffusion tensor parameters.
1146
1147 @keyword tensor: The diffusion tensor object.
1148 @type tensor: DiffTensorData instance
1149 @keyword value: The list of values to set the parameters to.
1150 @type value: list of float
1151 @keyword param: The list of parameter names.
1152 @type param: list of str
1153 """
1154
1155
1156 if not diff_data_exists():
1157 raise RelaxNoTensorError('diffusion')
1158
1159
1160 geo_params = []
1161 geo_values = []
1162 orient_params = []
1163 orient_values = []
1164
1165
1166 for i in xrange(len(param)):
1167
1168 param[i] = return_data_name(param[i])
1169
1170
1171 if not param[i]:
1172 raise RelaxUnknownParamError("diffusion tensor", param[i])
1173
1174
1175 if value[i] == None:
1176 value[i] = default_value(param[i])
1177
1178
1179 if param[i] in ['tm', 'Diso', 'Da', 'Dratio', 'Dper', 'Dpar', 'Dr', 'Dx', 'Dy', 'Dz']:
1180 geo_params.append(param[i])
1181 geo_values.append(value[i])
1182
1183
1184 if param[i] in ['theta', 'phi', 'alpha', 'beta', 'gamma']:
1185 orient_params.append(param[i])
1186 orient_values.append(value[i])
1187
1188
1189
1190
1191
1192 if cdp.diff_tensor.type == 'sphere':
1193
1194
1195
1196
1197 if len(geo_params) == 1:
1198
1199 if geo_params[0] == 'tm':
1200 cdp.diff_tensor.tm = geo_values[0]
1201
1202
1203 elif geo_params[0] == 'Diso':
1204 cdp.diff_tensor.tm = 1.0 / (6.0 * geo_values[0])
1205
1206
1207 else:
1208 raise RelaxError("The geometric diffusion parameter " + repr(geo_params[0]) + " cannot be set.")
1209
1210
1211 elif len(geo_params) > 1:
1212 raise RelaxUnknownParamCombError('geometric parameter set', geo_params)
1213
1214
1215
1216
1217
1218
1219 if len(orient_params):
1220 raise RelaxError("For spherical diffusion, the orientation parameters " + repr(orient_params) + " should not exist.")
1221
1222
1223
1224
1225
1226 elif cdp.diff_tensor.type == 'spheroid':
1227
1228
1229
1230
1231 if len(geo_params) == 1:
1232
1233 if geo_params[0] == 'tm':
1234 cdp.diff_tensor.tm = geo_values[0]
1235
1236
1237 elif geo_params[0] == 'Diso':
1238 cdp.diff_tensor.tm = 1.0 / (6.0 * geo_values[0])
1239
1240
1241 elif geo_params[0] == 'Da':
1242 cdp.diff_tensor.Da = geo_values[0]
1243
1244
1245 elif geo_params[0] == 'Dratio':
1246 Dratio = geo_values[0]
1247 cdp.diff_tensor.Da = (Dratio - 1.0) / (2.0 * cdp.diff_tensor.tm * (Dratio + 2.0))
1248
1249
1250 else:
1251 raise RelaxError("The geometric diffusion parameter " + repr(geo_params[0]) + " cannot be set.")
1252
1253
1254 elif len(geo_params) == 2:
1255
1256 if geo_params.count('tm') == 1 and geo_params.count('Da') == 1:
1257
1258 tm = geo_values[geo_params.index('tm')]
1259 Da = geo_values[geo_params.index('Da')]
1260
1261
1262 cdp.diff_tensor.tm = tm
1263 cdp.diff_tensor.Da = Da
1264
1265
1266 elif geo_params.count('Diso') == 1 and geo_params.count('Da') == 1:
1267
1268 Diso = geo_values[geo_params.index('Diso')]
1269 Da = geo_values[geo_params.index('Da')]
1270
1271
1272 cdp.diff_tensor.tm = 1.0 / (6.0 * Diso)
1273 cdp.diff_tensor.Da = Da
1274
1275
1276 elif geo_params.count('tm') == 1 and geo_params.count('Dratio') == 1:
1277
1278 tm = geo_values[geo_params.index('tm')]
1279 Dratio = geo_values[geo_params.index('Dratio')]
1280
1281
1282 cdp.diff_tensor.tm = tm
1283 cdp.diff_tensor.Da = (Dratio - 1.0) / (2.0 * tm * (Dratio + 2.0))
1284
1285
1286 elif geo_params.count('Dpar') == 1 and geo_params.count('Dper') == 1:
1287
1288 Dpar = geo_values[geo_params.index('Dpar')]
1289 Dper = geo_values[geo_params.index('Dper')]
1290
1291
1292 cdp.diff_tensor.tm = 1.0 / (2.0 * (Dpar + 2.0*Dper))
1293 cdp.diff_tensor.Da = Dpar - Dper
1294
1295
1296 elif geo_params.count('Diso') == 1 and geo_params.count('Dratio') == 1:
1297
1298 Diso = geo_values[geo_params.index('Diso')]
1299 Dratio = geo_values[geo_params.index('Dratio')]
1300
1301
1302 cdp.diff_tensor.tm = 1.0 / (6.0 * Diso)
1303 cdp.diff_tensor.Da = 3.0 * Diso * (Dratio - 1.0) / (Dratio + 2.0)
1304
1305
1306 else:
1307 raise RelaxUnknownParamCombError('geometric parameter set', geo_params)
1308
1309
1310 elif len(geo_params) > 2:
1311 raise RelaxUnknownParamCombError('geometric parameter set', geo_params)
1312
1313
1314
1315
1316
1317
1318 if len(orient_params) == 1:
1319
1320 if orient_params[0] == 'theta':
1321 cdp.diff_tensor.theta = orient_values[orient_params.index('theta')]
1322
1323
1324 elif orient_params[0] == 'phi':
1325 cdp.diff_tensor.phi = orient_values[orient_params.index('phi')]
1326
1327
1328 else:
1329 raise RelaxError("For spheroidal diffusion, the orientation parameter " + repr(orient_params) + " cannot be set.")
1330
1331
1332 elif len(orient_params) == 2:
1333
1334 if orient_params.count('theta') == 1 and orient_params.count('phi') == 1:
1335 cdp.diff_tensor.theta = orient_values[orient_params.index('theta')]
1336 cdp.diff_tensor.phi = orient_values[orient_params.index('phi')]
1337
1338
1339 else:
1340 raise RelaxUnknownParamCombError('orientational parameter set', orient_params)
1341
1342
1343 elif len(orient_params) > 2:
1344 raise RelaxUnknownParamCombError('orientational parameter set', orient_params)
1345
1346
1347
1348
1349
1350 elif cdp.diff_tensor.type == 'ellipsoid':
1351
1352
1353
1354
1355 if len(geo_params) == 1:
1356
1357 if geo_params[0] == 'tm':
1358 cdp.diff_tensor.tm = geo_values[0]
1359
1360
1361 elif geo_params[0] == 'Diso':
1362 cdp.diff_tensor.tm = 1.0 / (6.0 * geo_values[0])
1363
1364
1365 elif geo_params[0] == 'Da':
1366 cdp.diff_tensor.Da = geo_values[0]
1367
1368
1369 elif geo_params[0] == 'Dr':
1370 cdp.diff_tensor.Dr = geo_values[0]
1371
1372
1373 else:
1374 raise RelaxError("The geometric diffusion parameter " + repr(geo_params[0]) + " cannot be set.")
1375
1376
1377 elif len(geo_params) == 2:
1378
1379 if geo_params.count('tm') == 1 and geo_params.count('Da') == 1:
1380
1381 tm = geo_values[geo_params.index('tm')]
1382 Da = geo_values[geo_params.index('Da')]
1383
1384
1385 cdp.diff_tensor.tm = tm
1386 cdp.diff_tensor.Da = Da
1387
1388
1389 elif geo_params.count('tm') == 1 and geo_params.count('Dr') == 1:
1390
1391 tm = geo_values[geo_params.index('tm')]
1392 Dr = geo_values[geo_params.index('Dr')]
1393
1394
1395 cdp.diff_tensor.tm = tm
1396 cdp.diff_tensor.Dr = Dr
1397
1398
1399 elif geo_params.count('Diso') == 1 and geo_params.count('Da') == 1:
1400
1401 Diso = geo_values[geo_params.index('Diso')]
1402 Da = geo_values[geo_params.index('Da')]
1403
1404
1405 cdp.diff_tensor.tm = 1.0 / (6.0 * Diso)
1406 cdp.diff_tensor.Da = Da
1407
1408
1409 elif geo_params.count('Diso') == 1 and geo_params.count('Dr') == 1:
1410
1411 Diso = geo_values[geo_params.index('Diso')]
1412 Dr = geo_values[geo_params.index('Dr')]
1413
1414
1415 cdp.diff_tensor.tm = 1.0 / (6.0 * Diso)
1416 cdp.diff_tensor.Dr = Dr
1417
1418
1419 elif geo_params.count('Da') == 1 and geo_params.count('Dr') == 1:
1420
1421 Da = geo_values[geo_params.index('Da')]
1422 Dr = geo_values[geo_params.index('Dr')]
1423
1424
1425 cdp.diff_tensor.Da = Da
1426 cdp.diff_tensor.Da = Dr
1427
1428
1429 else:
1430 raise RelaxUnknownParamCombError('geometric parameter set', geo_params)
1431
1432
1433 elif len(geo_params) == 3:
1434
1435 if geo_params.count('tm') == 1 and geo_params.count('Da') == 1 and geo_params.count('Dr') == 1:
1436
1437 tm = geo_values[geo_params.index('tm')]
1438 Da = geo_values[geo_params.index('Da')]
1439 Dr = geo_values[geo_params.index('Dr')]
1440
1441
1442 cdp.diff_tensor.tm = tm
1443 cdp.diff_tensor.Da = Da
1444 cdp.diff_tensor.Dr = Dr
1445
1446
1447 elif geo_params.count('Diso') == 1 and geo_params.count('Da') == 1 and geo_params.count('Dr') == 1:
1448
1449 Diso = geo_values[geo_params.index('Diso')]
1450 Da = geo_values[geo_params.index('Da')]
1451 Dr = geo_values[geo_params.index('Dr')]
1452
1453
1454 cdp.diff_tensor.tm = 1.0 / (6.0 * Diso)
1455 cdp.diff_tensor.Da = Da
1456 cdp.diff_tensor.Dr = Dr
1457
1458
1459 elif geo_params.count('Dx') == 1 and geo_params.count('Dy') == 1 and geo_params.count('Dz') == 1:
1460
1461 Dx = geo_values[geo_params.index('Dx')]
1462 Dy = geo_values[geo_params.index('Dy')]
1463 Dz = geo_values[geo_params.index('Dz')]
1464
1465
1466 if Dx + Dy + Dz == 0.0:
1467 cdp.diff_tensor.tm = 1e99
1468 else:
1469 cdp.diff_tensor.tm = 0.5 / (Dx + Dy + Dz)
1470
1471
1472 cdp.diff_tensor.Da = Dz - 0.5*(Dx + Dy)
1473
1474
1475 if cdp.diff_tensor.Da == 0.0:
1476 cdp.diff_tensor.Dr = (Dy - Dx) * 1e99
1477 else:
1478 cdp.diff_tensor.Dr = (Dy - Dx) / (2.0*cdp.diff_tensor.Da)
1479
1480
1481 else:
1482 raise RelaxUnknownParamCombError('geometric parameter set', geo_params)
1483
1484
1485
1486 elif len(geo_params) > 3:
1487 raise RelaxUnknownParamCombError('geometric parameter set', geo_params)
1488
1489
1490
1491
1492
1493
1494 if len(orient_params) == 1:
1495
1496 if orient_params[0] == 'alpha':
1497 cdp.diff_tensor.alpha = orient_values[orient_params.index('alpha')]
1498
1499
1500 elif orient_params[0] == 'beta':
1501 cdp.diff_tensor.beta = orient_values[orient_params.index('beta')]
1502
1503
1504 elif orient_params[0] == 'gamma':
1505 cdp.diff_tensor.gamma = orient_values[orient_params.index('gamma')]
1506
1507
1508 else:
1509 raise RelaxError("For ellipsoidal diffusion, the orientation parameter " + repr(orient_params) + " cannot be set.")
1510
1511
1512 elif len(orient_params) == 2:
1513
1514 if orient_params.count('alpha') == 1 and orient_params.count('beta') == 1:
1515 cdp.diff_tensor.alpha = orient_values[orient_params.index('alpha')]
1516 cdp.diff_tensor.beta = orient_values[orient_params.index('beta')]
1517
1518
1519 if orient_params.count('alpha') == 1 and orient_params.count('gamma') == 1:
1520 cdp.diff_tensor.alpha = orient_values[orient_params.index('alpha')]
1521 cdp.diff_tensor.gamma = orient_values[orient_params.index('gamma')]
1522
1523
1524 if orient_params.count('beta') == 1 and orient_params.count('gamma') == 1:
1525 cdp.diff_tensor.beta = orient_values[orient_params.index('beta')]
1526 cdp.diff_tensor.gamma = orient_values[orient_params.index('gamma')]
1527
1528
1529 else:
1530 raise RelaxUnknownParamCombError('orientational parameter set', orient_params)
1531
1532
1533 elif len(orient_params) == 3:
1534
1535 if orient_params.count('alpha') == 1 and orient_params.count('beta') == 1:
1536 cdp.diff_tensor.alpha = orient_values[orient_params.index('alpha')]
1537 cdp.diff_tensor.beta = orient_values[orient_params.index('beta')]
1538 cdp.diff_tensor.gamma = orient_values[orient_params.index('gamma')]
1539
1540
1541 else:
1542 raise RelaxUnknownParamCombError('orientational parameter set', orient_params)
1543
1544
1545 elif len(orient_params) > 3:
1546 raise RelaxUnknownParamCombError('orientational parameter set', orient_params)
1547
1548
1549
1550
1551
1552 if orient_params:
1553 fold_angles()
1554
1555
1556 __set_prompt_doc__ = ["Diffusion tensor set details", """
1557 If the diffusion tensor has not been setup, use the more powerful function 'diffusion_tensor.init' to initialise the tensor parameters. This function cannot be used to initialise a diffusion tensor.
1558
1559 The units of the parameters are:
1560
1561 Inverse seconds for tm.
1562 Seconds for Diso, Da, Dx, Dy, Dz, Dpar, Dper.
1563 Unitless for Dratio and Dr.
1564 Radians for all angles (alpha, beta, gamma, theta, phi).
1565
1566 When setting a diffusion tensor parameter, the residue number has no effect. As the internal parameters of spherical diffusion are {tm}, spheroidal diffusion are {tm, Da, theta, phi}, and ellipsoidal diffusion are {tm, Da, Dr, alpha, beta, gamma}, supplying geometric parameters must be done in the following way. If a single geometric parameter is supplied, it must be one of tm, Diso, Da, Dr, or Dratio. For the parameters Dpar, Dper, Dx, Dy, and Dx, it is not possible to determine how to use the currently set values together with the supplied value to calculate the new internal parameters. For spheroidal diffusion, when supplying multiple geometric parameters, the set must belong to one of
1567
1568 {tm, Da},
1569 {Diso, Da},
1570 {tm, Dratio},
1571 {Dpar, Dper},
1572 {Diso, Dratio},
1573
1574 where either theta, phi, or both orientational parameters can be additionally supplied. For ellipsoidal diffusion, again when supplying multiple geometric parameters, the set must belong to one of
1575
1576 {tm, Da, Dr},
1577 {Diso, Da, Dr},
1578 {Dx, Dy, Dz},
1579
1580 where any number of the orientational parameters, alpha, beta, or gamma can be additionally supplied.
1581 """]
1582
1583
1584 -def sphere(params=None, time_scale=None, param_types=None):
1585 """Function for setting up a spherical diffusion tensor.
1586
1587 @param params: The diffusion tensor parameter.
1588 @type params: float
1589 @param time_scale: The correlation time scaling value.
1590 @type time_scale: float
1591 @param param_types: The type of parameter supplied. If 0, then the parameter is tm. If 1, then
1592 the parameter is Diso.
1593 @type param_types: int
1594 """
1595
1596
1597 cdp.diff_tensor.type = 'sphere'
1598
1599
1600 if param_types == 0:
1601
1602 tm = params * time_scale
1603
1604
1605 set(value=[tm], param=['tm'])
1606
1607
1608 elif param_types == 1:
1609
1610 Diso = params * d_scale
1611
1612
1613 set(value=[Diso], param=['Diso'])
1614
1615
1616 else:
1617 raise RelaxUnknownParamCombError('param_types', param_types)
1618
1619
1620 -def spheroid(params=None, time_scale=None, d_scale=None, angle_units=None, param_types=None, spheroid_type=None):
1621 """Function for setting up a spheroidal diffusion tensor.
1622
1623 @param params: The diffusion tensor parameter.
1624 @type params: float
1625 @param time_scale: The correlation time scaling value.
1626 @type time_scale: float
1627 @param d_scale: The diffusion tensor eigenvalue scaling value.
1628 @type d_scale: float
1629 @param angle_units: The units for the angle parameters which can be either 'deg' or 'rad'.
1630 @type angle_units: str
1631 @param param_types: The type of parameters supplied. These correspond to 0: {tm, Da, theta,
1632 phi}, 1: {Diso, Da, theta, phi}, 2: {tm, Dratio, theta, phi}, 3: {Dpar,
1633 Dper, theta, phi}, 4: {Diso, Dratio, theta, phi}.
1634 @type param_types: int
1635 @param spheroid_type: A string which, if supplied together with spheroid parameters, will
1636 restrict the tensor to either being 'oblate' or 'prolate'.
1637 @type spheroid_type: str
1638 """
1639
1640
1641 cdp.diff_tensor.type = 'spheroid'
1642
1643
1644 allowed_types = [None, 'oblate', 'prolate']
1645 if spheroid_type not in allowed_types:
1646 raise RelaxError("The 'spheroid_type' argument " + repr(spheroid_type) + " should be 'oblate', 'prolate', or None.")
1647 cdp.diff_tensor.spheroid_type = spheroid_type
1648
1649
1650 if param_types == 0:
1651
1652 tm, Da, theta, phi = params
1653
1654
1655 tm = tm * time_scale
1656 Da = Da * d_scale
1657
1658
1659 set(value=[tm, Da], param=['tm', 'Da'])
1660
1661
1662 elif param_types == 1:
1663
1664 Diso, Da, theta, phi = params
1665
1666
1667 Diso = Diso * d_scale
1668 Da = Da * d_scale
1669
1670
1671 set(value=[Diso, Da], param=['Diso', 'Da'])
1672
1673
1674 elif param_types == 2:
1675
1676 tm, Dratio, theta, phi = params
1677
1678
1679 tm = tm * time_scale
1680
1681
1682 set(value=[tm, Dratio], param=['tm', 'Dratio'])
1683
1684
1685 elif param_types == 3:
1686
1687 Dpar, Dper, theta, phi = params
1688
1689
1690 Dpar = Dpar * d_scale
1691 Dper = Dper * d_scale
1692
1693
1694 set(value=[Dpar, Dper], param=['Dpar', 'Dper'])
1695
1696
1697 elif param_types == 4:
1698
1699 Diso, Dratio, theta, phi = params
1700
1701
1702 Diso = Diso * d_scale
1703
1704
1705 set(value=[Diso, Dratio], param=['Diso', 'Dratio'])
1706
1707
1708 else:
1709 raise RelaxUnknownParamCombError('param_types', param_types)
1710
1711
1712 if angle_units == 'deg':
1713 print("Converting the angles from degrees to radian units.")
1714 theta = (theta / 360.0) * 2.0 * pi
1715 phi = (phi / 360.0) * 2.0 * pi
1716
1717
1718 set(value=[theta, phi], param=['theta', 'phi'])
1719
1720
1722 """Determine the eigenvalues and vectors for the tensor, sorting the entries.
1723
1724 @return: The eigenvalues, rotation matrix, and the Euler angles in zyz notation.
1725 @rtype: 3D rank-1 array, 3D rank-2 array, float, float, float
1726 """
1727
1728
1729 R, Di, A = svd(tensor)
1730 D_diag = zeros((3, 3), float64)
1731 for i in range(3):
1732 D_diag[i, i] = Di[i]
1733
1734
1735 tup_struct = []
1736 for i in range(3):
1737 tup_struct.append((i, Di[i]))
1738
1739
1740 reorder_data = sorted(tup_struct, key=itemgetter(1))
1741 reorder = zeros(3, int)
1742 Di_sort = zeros(3, float)
1743 for i in range(3):
1744 reorder[i], Di_sort[i] = reorder_data[i]
1745
1746
1747 R_new = zeros((3, 3), float64)
1748 for i in range(3):
1749 R_new[:, i] = R[:, reorder[i]]
1750
1751
1752 if norm(cross(R_new[:, 0], R_new[:, 1]) - R_new[:, 2]) > 1e-7:
1753 R_new[:, 2] = -R_new[:, 2]
1754
1755
1756 R_new = transpose(R_new)
1757
1758
1759 gamma, beta, alpha = R_to_euler_zyz(R_new)
1760
1761
1762 if alpha >= pi:
1763 alpha = alpha - pi
1764 if gamma >= pi:
1765 alpha = pi - alpha
1766 beta = pi - beta
1767 gamma = gamma - pi
1768 if beta >= pi:
1769 alpha = pi - alpha
1770 beta = beta - pi
1771
1772
1773 return Di_sort, R_new, alpha, beta, gamma
1774
1775
1777 """Function for testing the validity of the input parameters."""
1778
1779
1780 error = 1e-4
1781
1782
1783 tm = cdp.diff_tensor.tm
1784 if tm <= 0.0 or tm > 1e-6:
1785 raise RelaxError("The tm value of " + repr(tm) + " should be between zero and one microsecond.")
1786
1787
1788 if num_params == 4:
1789
1790 Diso = 1.0 / (6.0 * cdp.diff_tensor.tm)
1791 Da = cdp.diff_tensor.Da
1792
1793
1794 if Da < (-1.5*Diso - error*Diso) or Da > (3.0*Diso + error*Diso):
1795 raise RelaxError("The Da value of " + repr(Da) + " should be between -3/2 * Diso and 3Diso.")
1796
1797
1798 if num_params == 6:
1799
1800 Diso = 1.0 / (6.0 * cdp.diff_tensor.tm)
1801 Da = cdp.diff_tensor.Da
1802 Dr = cdp.diff_tensor.Dr
1803
1804
1805 if Da < (0.0 - error*Diso) or Da > (3.0*Diso + error*Diso):
1806 raise RelaxError("The Da value of " + repr(Da) + " should be between zero and 3Diso.")
1807
1808
1809 if Dr < (0.0 - error) or Dr > (1.0 + error):
1810 raise RelaxError("The Dr value of " + repr(Dr) + " should be between zero and one.")
1811
1812
1814 """Function for calculating the unit axes of the diffusion tensor.
1815
1816 Spheroid
1817 ========
1818
1819 The unit Dpar vector is::
1820
1821 | sin(theta) * cos(phi) |
1822 Dpar = | sin(theta) * sin(phi) |
1823 | cos(theta) |
1824
1825
1826 Ellipsoid
1827 =========
1828
1829 The unit Dx vector is::
1830
1831 | -sin(alpha) * sin(gamma) + cos(alpha) * cos(beta) * cos(gamma) |
1832 Dx = | -sin(alpha) * cos(gamma) - cos(alpha) * cos(beta) * sin(gamma) |
1833 | cos(alpha) * sin(beta) |
1834
1835 The unit Dy vector is::
1836
1837 | cos(alpha) * sin(gamma) + sin(alpha) * cos(beta) * cos(gamma) |
1838 Dy = | cos(alpha) * cos(gamma) - sin(alpha) * cos(beta) * sin(gamma) |
1839 | sin(alpha) * sin(beta) |
1840
1841 The unit Dz vector is::
1842
1843 | -sin(beta) * cos(gamma) |
1844 Dz = | sin(beta) * sin(gamma) |
1845 | cos(beta) |
1846
1847 """
1848
1849
1850 if cdp.diff_tensor.type == 'spheroid':
1851
1852 Dpar = zeros(3, float64)
1853
1854
1855 sin_theta = sin(cdp.diff_tensor.theta)
1856 cos_theta = cos(cdp.diff_tensor.theta)
1857 sin_phi = sin(cdp.diff_tensor.phi)
1858 cos_phi = cos(cdp.diff_tensor.phi)
1859
1860
1861 Dpar[0] = sin_theta * cos_phi
1862 Dpar[1] = sin_theta * sin_phi
1863 Dpar[2] = cos_theta
1864
1865
1866 return Dpar
1867
1868
1869 if cdp.diff_tensor.type == 'ellipsoid':
1870
1871 Dx = zeros(3, float64)
1872 Dy = zeros(3, float64)
1873 Dz = zeros(3, float64)
1874
1875
1876 sin_alpha = sin(cdp.diff_tensor.alpha)
1877 cos_alpha = cos(cdp.diff_tensor.alpha)
1878 sin_beta = sin(cdp.diff_tensor.beta)
1879 cos_beta = cos(cdp.diff_tensor.beta)
1880 sin_gamma = sin(cdp.diff_tensor.gamma)
1881 cos_gamma = cos(cdp.diff_tensor.gamma)
1882
1883
1884 Dx[0] = -sin_alpha * sin_gamma + cos_alpha * cos_beta * cos_gamma
1885 Dx[1] = -sin_alpha * cos_gamma - cos_alpha * cos_beta * sin_gamma
1886 Dx[2] = cos_alpha * sin_beta
1887
1888
1889 Dx[0] = cos_alpha * sin_gamma + sin_alpha * cos_beta * cos_gamma
1890 Dx[1] = cos_alpha * cos_gamma - sin_alpha * cos_beta * sin_gamma
1891 Dx[2] = sin_alpha * sin_beta
1892
1893
1894 Dx[0] = -sin_beta * cos_gamma
1895 Dx[1] = sin_beta * sin_gamma
1896 Dx[2] = cos_beta
1897
1898
1899 return Dx, Dy, Dz
1900