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