1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from copy import deepcopy
24 from math import cos, pi, sin
25 from Numeric import Float64, array, zeros
26 from re import search
27
28
31 """Class containing the function for setting up the diffusion tensor."""
32
33 self.relax = relax
34
35
36 - def copy(self, run1=None, run2=None):
37 """Function for copying diffusion tensor data from run1 to run2."""
38
39
40 if not run1 in self.relax.data.run_names:
41 raise RelaxNoRunError, run1
42
43
44 if not run2 in self.relax.data.run_names:
45 raise RelaxNoRunError, run2
46
47
48 if not self.relax.data.diff.has_key(run1):
49 raise RelaxNoTensorError, run1
50
51
52 if self.relax.data.diff.has_key(run2):
53 raise RelaxTensorError, run2
54
55
56 self.relax.data.diff[run2] = deepcopy(self.relax.data.diff[run1])
57
58
60 """Function for returning a list of names of data structures associated with the sequence."""
61
62 names = [ 'diff_type',
63 'diff_params' ]
64
65 return names
66
67
69 """
70 Diffusion tensor parameter default values
71 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72
73 ________________________________________________________________________
74 | | | |
75 | Data type | Object name | Value |
76 |________________________|____________________|________________________|
77 | | | |
78 | tm | 'tm' | 10 * 1e-9 |
79 | | | |
80 | Diso | 'Diso' | 1.666 * 1e7 |
81 | | | |
82 | Da | 'Da' | 0.0 |
83 | | | |
84 | Dr | 'Dr' | 0.0 |
85 | | | |
86 | Dx | 'Dx' | 1.666 * 1e7 |
87 | | | |
88 | Dy | 'Dy' | 1.666 * 1e7 |
89 | | | |
90 | Dz | 'Dz' | 1.666 * 1e7 |
91 | | | |
92 | Dpar | 'Dpar' | 1.666 * 1e7 |
93 | | | |
94 | Dper | 'Dper' | 1.666 * 1e7 |
95 | | | |
96 | Dratio | 'Dratio' | 1.0 |
97 | | | |
98 | alpha | 'alpha' | 0.0 |
99 | | | |
100 | beta | 'beta' | 0.0 |
101 | | | |
102 | gamma | 'gamma' | 0.0 |
103 | | | |
104 | theta | 'theta' | 0.0 |
105 | | | |
106 | phi | 'phi' | 0.0 |
107 |________________________|____________________|________________________|
108
109 """
110
111
112 if param == 'tm':
113 return 10.0 * 1e-9
114
115
116 elif param == 'Diso' or param == 'Dx' or param == 'Dy' or param == 'Dz' or param == 'Dpar' or param == 'Dper':
117 return 1.666 * 1e7
118
119
120 elif param == 'Dratio':
121 return 1.0
122
123
140
141
143 """Function for displaying the diffusion tensor."""
144
145
146 if not run in self.relax.data.run_names:
147 raise RelaxNoRunError, run
148
149
150 if not self.relax.data.diff.has_key(run):
151 raise RelaxNoTensorError, run
152
153
154 if self.relax.data.diff[run].type == 'sphere':
155
156 print "Type: Spherical diffusion"
157
158
159 print "\nParameters {tm}."
160 print "tm (s): " + `self.relax.data.diff[run].tm`
161
162
163 print "\nAlternate parameters {Diso}."
164 print "Diso (1/s): " + `self.relax.data.diff[run].Diso`
165
166
167 print "\nFixed: " + `self.relax.data.diff[run].fixed`
168
169
170 elif self.relax.data.diff[run].type == 'spheroid':
171
172 print "Type: Spheroidal diffusion"
173
174
175 print "\nParameters {tm, Da, theta, phi}."
176 print "tm (s): " + `self.relax.data.diff[run].tm`
177 print "Da (1/s): " + `self.relax.data.diff[run].Da`
178 print "theta (rad): " + `self.relax.data.diff[run].theta`
179 print "phi (rad): " + `self.relax.data.diff[run].phi`
180
181
182 print "\nAlternate parameters {Diso, Da, theta, phi}."
183 print "Diso (1/s): " + `self.relax.data.diff[run].Diso`
184 print "Da (1/s): " + `self.relax.data.diff[run].Da`
185 print "theta (rad): " + `self.relax.data.diff[run].theta`
186 print "phi (rad): " + `self.relax.data.diff[run].phi`
187
188
189 print "\nAlternate parameters {Dpar, Dper, theta, phi}."
190 print "Dpar (1/s): " + `self.relax.data.diff[run].Dpar`
191 print "Dper (1/s): " + `self.relax.data.diff[run].Dper`
192 print "theta (rad): " + `self.relax.data.diff[run].theta`
193 print "phi (rad): " + `self.relax.data.diff[run].phi`
194
195
196 print "\nAlternate parameters {tm, Dratio, theta, phi}."
197 print "tm (s): " + `self.relax.data.diff[run].tm`
198 print "Dratio: " + `self.relax.data.diff[run].Dratio`
199 print "theta (rad): " + `self.relax.data.diff[run].theta`
200 print "phi (rad): " + `self.relax.data.diff[run].phi`
201
202
203 print "\nFixed: " + `self.relax.data.diff[run].fixed`
204
205
206 elif self.relax.data.diff[run].type == 'ellipsoid':
207
208 print "Type: Ellipsoidal diffusion"
209
210
211 print "\nParameters {tm, Da, Dr, alpha, beta, gamma}."
212 print "tm (s): " + `self.relax.data.diff[run].tm`
213 print "Da (1/s): " + `self.relax.data.diff[run].Da`
214 print "Dr: " + `self.relax.data.diff[run].Dr`
215 print "alpha (rad): " + `self.relax.data.diff[run].alpha`
216 print "beta (rad): " + `self.relax.data.diff[run].beta`
217 print "gamma (rad): " + `self.relax.data.diff[run].gamma`
218
219
220 print "\nAlternate parameters {Diso, Da, Dr, alpha, beta, gamma}."
221 print "Diso (1/s): " + `self.relax.data.diff[run].Diso`
222 print "Da (1/s): " + `self.relax.data.diff[run].Da`
223 print "Dr: " + `self.relax.data.diff[run].Dr`
224 print "alpha (rad): " + `self.relax.data.diff[run].alpha`
225 print "beta (rad): " + `self.relax.data.diff[run].beta`
226 print "gamma (rad): " + `self.relax.data.diff[run].gamma`
227
228
229 print "\nAlternate parameters {Dx, Dy, Dz, alpha, beta, gamma}."
230 print "Dx (1/s): " + `self.relax.data.diff[run].Dx`
231 print "Dy (1/s): " + `self.relax.data.diff[run].Dy`
232 print "Dz (1/s): " + `self.relax.data.diff[run].Dz`
233 print "alpha (rad): " + `self.relax.data.diff[run].alpha`
234 print "beta (rad): " + `self.relax.data.diff[run].beta`
235 print "gamma (rad): " + `self.relax.data.diff[run].gamma`
236
237
238 print "\nFixed: " + `self.relax.data.diff[run].fixed`
239
240
242 """Function for setting up ellipsoidal diffusion."""
243
244
245 self.relax.data.diff[self.run].type = 'ellipsoid'
246
247
248 if self.param_types == 0:
249
250 tm, Da, Dr, alpha, beta, gamma = self.params
251
252
253 tm = tm * self.time_scale
254 Da = Da * self.d_scale
255
256
257 self.set(run=self.run, value=[tm, Da, Dr], param=['tm', 'Da', 'Dr'])
258
259
260 elif self.param_types == 1:
261
262 Diso, Da, Dr, alpha, beta, gamma = self.params
263
264
265 Diso = Diso * self.d_scale
266 Da = Da * self.d_scale
267
268
269 self.set(run=self.run, value=[Diso, Da, Dr], param=['Diso', 'Da', 'Dr'])
270
271
272 elif self.param_types == 2:
273
274 Dx, Dy, Dz, alpha, beta, gamma = self.params
275
276
277 Dx = Dx * self.d_scale
278 Dy = Dy * self.d_scale
279 Dz = Dz * self.d_scale
280
281
282 self.set(run=self.run, value=[Dx, Dy, Dz], param=['Dx', 'Dy', 'Dz'])
283
284
285 else:
286 raise RelaxUnknownParamCombError, ('param_types', self.param_types)
287
288
289 if self.angle_units == 'deg':
290 alpha = (alpha / 360.0) * 2.0 * pi
291 beta = (beta / 360.0) * 2.0 * pi
292 gamma = (gamma / 360.0) * 2.0 * pi
293
294
295 self.set(run=self.run, value=[alpha, beta, gamma], param=['alpha', 'beta', 'gamma'])
296
297
299 """Wrap the Euler or spherical angles and remove the glide reflection and translational symmetries.
300
301 Wrap the angles such that
302
303 0 <= theta <= pi,
304 0 <= phi <= 2pi,
305
306 and
307
308 0 <= alpha <= 2pi,
309 0 <= beta <= pi,
310 0 <= gamma <= 2pi.
311
312
313 For the simulated values, the angles are wrapped as
314
315 theta - pi/2 <= theta_sim <= theta + pi/2
316 phi - pi <= phi_sim <= phi + pi
317
318 and
319
320 alpha - pi <= alpha_sim <= alpha + pi
321 beta - pi/2 <= beta_sim <= beta + pi/2
322 gamma - pi <= gamma_sim <= gamma + pi
323 """
324
325
326
327
328
329 if self.relax.data.diff[self.run].type == 'spheroid':
330
331 theta = self.relax.data.diff[self.run].theta
332 phi = self.relax.data.diff[self.run].phi
333
334
335 if sim_index != None:
336 theta_sim = self.relax.data.diff[self.run].theta_sim[sim_index]
337 phi_sim = self.relax.data.diff[self.run].phi_sim[sim_index]
338
339
340 if sim_index == None:
341 self.relax.data.diff[self.run].theta = self.relax.generic.angles.wrap_angles(theta, 0.0, pi)
342 self.relax.data.diff[self.run].phi = self.relax.generic.angles.wrap_angles(phi, 0.0, 2.0*pi)
343
344
345 else:
346 self.relax.data.diff[self.run].theta_sim[sim_index] = self.relax.generic.angles.wrap_angles(theta_sim, theta - pi/2.0, theta + pi/2.0)
347 self.relax.data.diff[self.run].phi_sim[sim_index] = self.relax.generic.angles.wrap_angles(phi_sim, phi - pi, phi + pi)
348
349
350 elif self.relax.data.diff[self.run].type == 'ellipsoid':
351
352 alpha = self.relax.data.diff[self.run].alpha
353 beta = self.relax.data.diff[self.run].beta
354 gamma = self.relax.data.diff[self.run].gamma
355
356
357 if sim_index != None:
358 alpha_sim = self.relax.data.diff[self.run].alpha_sim[sim_index]
359 beta_sim = self.relax.data.diff[self.run].beta_sim[sim_index]
360 gamma_sim = self.relax.data.diff[self.run].gamma_sim[sim_index]
361
362
363 if sim_index == None:
364 self.relax.data.diff[self.run].alpha = self.relax.generic.angles.wrap_angles(alpha, 0.0, 2.0*pi)
365 self.relax.data.diff[self.run].beta = self.relax.generic.angles.wrap_angles(beta, 0.0, 2.0*pi)
366 self.relax.data.diff[self.run].gamma = self.relax.generic.angles.wrap_angles(gamma, 0.0, 2.0*pi)
367
368
369 else:
370 self.relax.data.diff[self.run].alpha_sim[sim_index] = self.relax.generic.angles.wrap_angles(alpha_sim, alpha - pi, alpha + pi)
371 self.relax.data.diff[self.run].beta_sim[sim_index] = self.relax.generic.angles.wrap_angles(beta_sim, beta - pi, beta + pi)
372 self.relax.data.diff[self.run].gamma_sim[sim_index] = self.relax.generic.angles.wrap_angles(gamma_sim, gamma - pi, gamma + pi)
373
374
375
376
377
378
379 if self.relax.data.diff[self.run].type == 'spheroid':
380
381 if sim_index == None:
382
383 if self.relax.data.diff[self.run].phi >= pi:
384 self.relax.data.diff[self.run].theta = pi - self.relax.data.diff[self.run].theta
385 self.relax.data.diff[self.run].phi = self.relax.data.diff[self.run].phi - pi
386
387
388 else:
389
390 if self.relax.data.diff[self.run].phi_sim[sim_index] >= self.relax.data.diff[self.run].phi + pi/2.0:
391 self.relax.data.diff[self.run].theta_sim[sim_index] = pi - self.relax.data.diff[self.run].theta_sim[sim_index]
392 self.relax.data.diff[self.run].phi_sim[sim_index] = self.relax.data.diff[self.run].phi_sim[sim_index] - pi
393 elif self.relax.data.diff[self.run].phi_sim[sim_index] <= self.relax.data.diff[self.run].phi - pi/2.0:
394 self.relax.data.diff[self.run].theta_sim[sim_index] = pi - self.relax.data.diff[self.run].theta_sim[sim_index]
395 self.relax.data.diff[self.run].phi_sim[sim_index] = self.relax.data.diff[self.run].phi_sim[sim_index] + pi
396
397
398 elif self.relax.data.diff[self.run].type == 'ellipsoid':
399
400 if sim_index == None:
401
402 if self.relax.data.diff[self.run].alpha >= pi:
403 self.relax.data.diff[self.run].alpha = self.relax.data.diff[self.run].alpha - pi
404
405
406 if self.relax.data.diff[self.run].beta >= pi:
407 self.relax.data.diff[self.run].alpha = pi - self.relax.data.diff[self.run].alpha
408 self.relax.data.diff[self.run].beta = self.relax.data.diff[self.run].beta - pi
409
410
411 if self.relax.data.diff[self.run].gamma >= pi:
412 self.relax.data.diff[self.run].alpha = pi - self.relax.data.diff[self.run].alpha
413 self.relax.data.diff[self.run].beta = pi - self.relax.data.diff[self.run].beta
414 self.relax.data.diff[self.run].gamma = self.relax.data.diff[self.run].gamma - pi
415
416
417 else:
418
419 if self.relax.data.diff[self.run].alpha_sim[sim_index] >= self.relax.data.diff[self.run].alpha + pi/2.0:
420 self.relax.data.diff[self.run].alpha_sim[sim_index] = self.relax.data.diff[self.run].alpha_sim[sim_index] - pi
421 elif self.relax.data.diff[self.run].alpha_sim[sim_index] <= self.relax.data.diff[self.run].alpha - pi/2.0:
422 self.relax.data.diff[self.run].alpha_sim[sim_index] = self.relax.data.diff[self.run].alpha_sim[sim_index] + pi
423
424
425 if self.relax.data.diff[self.run].beta_sim[sim_index] >= self.relax.data.diff[self.run].beta + pi/2.0:
426 self.relax.data.diff[self.run].alpha_sim[sim_index] = pi - self.relax.data.diff[self.run].alpha_sim[sim_index]
427 self.relax.data.diff[self.run].beta_sim[sim_index] = self.relax.data.diff[self.run].beta_sim[sim_index] - pi
428 elif self.relax.data.diff[self.run].beta_sim[sim_index] <= self.relax.data.diff[self.run].beta - pi/2.0:
429 self.relax.data.diff[self.run].alpha_sim[sim_index] = pi - self.relax.data.diff[self.run].alpha_sim[sim_index]
430 self.relax.data.diff[self.run].beta_sim[sim_index] = self.relax.data.diff[self.run].beta_sim[sim_index] + pi
431
432
433 if self.relax.data.diff[self.run].gamma_sim[sim_index] >= self.relax.data.diff[self.run].gamma + pi/2.0:
434 self.relax.data.diff[self.run].alpha_sim[sim_index] = pi - self.relax.data.diff[self.run].alpha_sim[sim_index]
435 self.relax.data.diff[self.run].beta_sim[sim_index] = pi - self.relax.data.diff[self.run].beta_sim[sim_index]
436 self.relax.data.diff[self.run].gamma_sim[sim_index] = self.relax.data.diff[self.run].gamma_sim[sim_index] - pi
437 elif self.relax.data.diff[self.run].gamma_sim[sim_index] <= self.relax.data.diff[self.run].gamma - pi/2.0:
438 self.relax.data.diff[self.run].alpha_sim[sim_index] = pi - self.relax.data.diff[self.run].alpha_sim[sim_index]
439 self.relax.data.diff[self.run].beta_sim[sim_index] = pi - self.relax.data.diff[self.run].beta_sim[sim_index]
440 self.relax.data.diff[self.run].gamma_sim[sim_index] = self.relax.data.diff[self.run].gamma_sim[sim_index] + pi
441
442
443 - def init(self, run=None, params=None, time_scale=1.0, d_scale=1.0, angle_units='deg', param_types=0, spheroid_type=None, fixed=1):
444 """Function for initialising the diffusion tensor."""
445
446
447 self.run = run
448 self.params = params
449 self.time_scale = time_scale
450 self.d_scale = d_scale
451 self.angle_units = angle_units
452 self.param_types = param_types
453 self.spheroid_type = spheroid_type
454
455
456 if not self.run in self.relax.data.run_names:
457 raise RelaxNoRunError, self.run
458
459
460 if self.relax.data.diff.has_key(self.run):
461 raise RelaxTensorError, self.run
462
463
464 valid_types = ['deg', 'rad']
465 if not angle_units in valid_types:
466 raise RelaxError, "The diffusion tensor 'angle_units' argument " + `angle_units` + " should be either 'deg' or 'rad'."
467
468
469 self.relax.data.diff.add_item(self.run)
470
471
472 self.relax.data.diff[self.run].fixed = fixed
473
474
475 if type(params) == float:
476 num_params = 1
477 self.sphere()
478
479
480 elif (type(params) == tuple or type(params) == list) and len(params) == 4:
481 num_params = 4
482 self.spheroid()
483
484
485 elif (type(params) == tuple or type(params) == list) and len(params) == 6:
486 num_params = 6
487 self.ellipsoid()
488
489
490 else:
491 raise RelaxError, "The diffusion tensor parameters " + `params` + " are of an unknown type."
492
493
494 self.test_params(num_params)
495
496
498 """The function for creating bounds for the mapping function."""
499
500
501 self.run = run
502
503
504 if param == 'tm':
505 return [0, 10.0 * 1e-9]
506
507
508 if param == 'Diso' or param == 'Dx' or param == 'Dy' or param == 'Dz' or param == 'Dpar' or param == 'Dper':
509 return [1e6, 1e7]
510
511
512 if param == 'Da':
513 return [-3.0/2.0 * 1e7, 3.0 * 1e7]
514
515
516 elif param == 'Dr':
517 return [0, 1]
518
519
520 elif param == 'Dratio':
521 return [1.0/3.0, 3.0]
522
523
524 elif param == 'theta':
525 return [0, pi]
526
527
528 elif param == 'phi':
529 return [0, 2*pi]
530
531
532 elif param == 'alpha':
533 return [0, 2*pi]
534
535
536 elif param == 'beta':
537 return [0, pi]
538
539
540 elif param == 'gamma':
541 return [0, 2*pi]
542
543
544 - def map_labels(self, run, index, params, bounds, swap, inc):
545 """Function for creating labels, tick locations, and tick values for an OpenDX map."""
546
547
548 labels = "{"
549 tick_locations = []
550 tick_values = []
551 n = len(params)
552 axis_incs = 5
553 loc_inc = inc / axis_incs
554
555
556 for i in xrange(n):
557
558 factor = self.return_conversion_factor(params[swap[i]])
559
560
561 units = self.return_units(params[swap[i]])
562
563
564 if units:
565 labels = labels + "\"" + params[swap[i]] + " (" + units + ")\""
566 else:
567 labels = labels + "\"" + params[swap[i]] + "\""
568
569
570 vals = bounds[swap[i], 0] / factor
571 val_inc = (bounds[swap[i], 1] - bounds[swap[i], 0]) / (axis_incs * factor)
572
573 if i < n - 1:
574 labels = labels + " "
575 else:
576 labels = labels + "}"
577
578
579 string = "{"
580 val = 0.0
581 for j in xrange(axis_incs + 1):
582 string = string + " " + `val`
583 val = val + loc_inc
584 string = string + " }"
585 tick_locations.append(string)
586
587
588 string = "{"
589 for j in xrange(axis_incs + 1):
590 string = string + "\"" + "%.2f" % vals + "\" "
591 vals = vals + val_inc
592 string = string + "}"
593 tick_values.append(string)
594
595 return labels, tick_locations, tick_values
596
597
599 """Function for returning the factor of conversion between different parameter units.
600
601 For example, the internal representation of tm is in seconds, whereas the external
602 representation is in nanoseconds, therefore this function will return 1e-9 for tm.
603 """
604
605
606 object_name = self.return_data_name(param)
607
608
609 if object_name == 'tm':
610 return 1e-9
611
612
613 elif object_name in ['Diso', 'Da', 'Dx', 'Dy', 'Dz', 'Dpar', 'Dper']:
614 return 1e6
615
616
617 elif object_name in ['theta', 'phi', 'alpha', 'beta', 'gamma']:
618 return (2.0*pi) / 360.0
619
620
621 else:
622 return 1.0
623
624
626 """
627 Diffusion tensor parameter string matching patterns
628 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
629
630 ____________________________________________________________________________________________
631 | | | |
632 | Data type | Object name | Patterns |
633 |________________________________________________________|______________|__________________|
634 | | | |
635 | Global correlation time - tm | 'tm' | 'tm' |
636 | | | |
637 | Isotropic component of the diffusion tensor - Diso | 'Diso' | '[Dd]iso' |
638 | | | |
639 | Anisotropic component of the diffusion tensor - Da | 'Da' | '[Dd]a' |
640 | | | |
641 | Rhombic component of the diffusion tensor - Dr | 'Dr' | '[Dd]r$' |
642 | | | |
643 | Eigenvalue associated with the x-axis of the diffusion | 'Dx' | '[Dd]x' |
644 | diffusion tensor - Dx | | |
645 | | | |
646 | Eigenvalue associated with the y-axis of the diffusion | 'Dy' | '[Dd]y' |
647 | diffusion tensor - Dy | | |
648 | | | |
649 | Eigenvalue associated with the z-axis of the diffusion | 'Dz' | '[Dd]z' |
650 | diffusion tensor - Dz | | |
651 | | | |
652 | Diffusion coefficient parallel to the major axis of | 'Dpar' | '[Dd]par' |
653 | the spheroid diffusion tensor - Dpar | | |
654 | | | |
655 | Diffusion coefficient perpendicular to the major axis | 'Dper' | '[Dd]per' |
656 | of the spheroid diffusion tensor - Dper | | |
657 | | | |
658 | Ratio of the parallel and perpendicular components of | 'Dratio' | '[Dd]ratio' |
659 | the spheroid diffusion tensor - Dratio | | |
660 | | | |
661 | The first Euler angle of the ellipsoid diffusion | 'alpha' | '^a$' or 'alpha' |
662 | tensor - alpha | | |
663 | | | |
664 | The second Euler angle of the ellipsoid diffusion | 'beta' | '^b$' or 'beta' |
665 | tensor - beta | | |
666 | | | |
667 | The third Euler angle of the ellipsoid diffusion | 'gamma' | '^g$' or 'gamma' |
668 | tensor - gamma | | |
669 | | | |
670 | The polar angle defining the major axis of the | 'theta' | 'theta' |
671 | spheroid diffusion tensor - theta | | |
672 | | | |
673 | The azimuthal angle defining the major axis of the | 'phi' | 'phi' |
674 | spheroid diffusion tensor - phi | | |
675 |________________________________________________________|______________|__________________|
676 """
677
678
679 if search('tm', name):
680 return 'tm'
681
682
683 if search('[Dd]iso', name):
684 return 'Diso'
685
686
687 if search('[Dd]a', name):
688 return 'Da'
689
690
691 if search('[Dd]r$', name):
692 return 'Dr'
693
694
695 if search('[Dd]x', name):
696 return 'Dx'
697
698
699 if search('[Dd]y', name):
700 return 'Dy'
701
702
703 if search('[Dd]z', name):
704 return 'Dz'
705
706
707 if search('[Dd]par', name):
708 return 'Dpar'
709
710
711 if search('[Dd]per', name):
712 return 'Dper'
713
714
715 if search('[Dd]ratio', name):
716 return 'Dratio'
717
718
719 if search('^a$', name) or search('alpha', name):
720 return 'alpha'
721
722
723 if search('^b$', name) or search('beta', name):
724 return 'beta'
725
726
727 if search('^g$', name) or search('gamma', name):
728 return 'gamma'
729
730
731 if search('theta', name):
732 return 'theta'
733
734
735 if search('phi', name):
736 return 'phi'
737
738
740 """Function for returning Dx, Dy, and Dz."""
741
742
743 if run:
744 self.run = run
745
746
747 data = self.relax.data.diff[self.run]
748
749
750 Diso = 1.0 / (6.0 * data.tm)
751
752
753 Dx = Diso - 1.0/3.0 * data.Da * (1.0 + 3.0 * data.Dr)
754
755
756 Dy = Diso - 1.0/3.0 * data.Da * (1.0 - 3.0 * data.Dr)
757
758
759 Dz = Diso + 2.0/3.0 * data.Da
760
761
762 return Dx, Dy, Dz
763
764
766 """Function for returning a string representing the parameters units.
767
768 For example, the internal representation of tm is in seconds, whereas the external
769 representation is in nanoseconds, therefore this function will return the string
770 'nanoseconds' for tm.
771 """
772
773
774 object_name = self.return_data_name(param)
775
776
777 if object_name == 'tm':
778 return 'ns'
779
780
781 elif object_name in ['Diso', 'Da', 'Dx', 'Dy', 'Dz', 'Dpar', 'Dper']:
782 return '1e6 1/s'
783
784
785 elif object_name in ['theta', 'phi', 'alpha', 'beta', 'gamma']:
786 return 'deg'
787
788
789 - def set(self, run=None, value=None, param=None):
790 """
791 Diffusion tensor set details
792 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
793
794 If the diffusion tensor has not been setup, use the more powerful function
795 'diffusion_tensor.init' to initialise the tensor parameters.
796
797 The diffusion tensor parameters can only be set when the run corresponds to model-free
798 analysis. The units of the parameters are:
799
800 Inverse seconds for tm.
801 Seconds for Diso, Da, Dx, Dy, Dz, Dpar, Dper.
802 Unitless for Dratio and Dr.
803 Radians for all angles (alpha, beta, gamma, theta, phi).
804
805
806 When setting a diffusion tensor parameter, the residue number has no effect. As the
807 internal parameters of spherical diffusion are {tm}, spheroidal diffusion are {tm, Da,
808 theta, phi}, and ellipsoidal diffusion are {tm, Da, Dr, alpha, beta, gamma}, supplying
809 geometric parameters must be done in the following way. If a single geometric parameter is
810 supplied, it must be one of tm, Diso, Da, Dr, or Dratio. For the parameters Dpar, Dper, Dx,
811 Dy, and Dx, it is not possible to determine how to use the currently set values together
812 with the supplied value to calculate the new internal parameters. For spheroidal diffusion,
813 when supplying multiple geometric parameters, the set must belong to one of
814
815 {tm, Da},
816 {Diso, Da},
817 {tm, Dratio},
818 {Dpar, Dper},
819 {Diso, Dratio},
820
821 where either theta, phi, or both orientational parameters can be additionally supplied. For
822 ellipsoidal diffusion, again when supplying multiple geometric parameters, the set must
823 belong to one of
824
825 {tm, Da, Dr},
826 {Diso, Da, Dr},
827 {Dx, Dy, Dz},
828
829 where any number of the orientational parameters, alpha, beta, or gamma can be additionally
830 supplied.
831 """
832
833
834 geo_params = []
835 geo_values = []
836 orient_params = []
837 orient_values = []
838
839
840 for i in xrange(len(param)):
841
842 param[i] = self.return_data_name(param[i])
843
844
845 if not param[i]:
846 raise RelaxUnknownParamError, ("diffusion tensor", param[i])
847
848
849 if value[i] == None:
850 value[i] = self.default_value(object_names[i])
851
852
853 if param[i] in ['tm', 'Diso', 'Da', 'Dratio', 'Dper', 'Dpar', 'Dr', 'Dx', 'Dy', 'Dz']:
854 geo_params.append(param[i])
855 geo_values.append(value[i])
856
857
858 if param[i] in ['theta', 'phi', 'alpha', 'beta', 'gamma']:
859 orient_params.append(param[i])
860 orient_values.append(value[i])
861
862
863
864
865
866 if self.relax.data.diff[self.run].type == 'sphere':
867
868
869
870
871 if len(geo_params) == 1:
872
873 if geo_params[0] == 'tm':
874 self.relax.data.diff[self.run].tm = geo_values[0]
875
876
877 elif geo_params[0] == 'Diso':
878 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * geo_values[0])
879
880
881 else:
882 raise RelaxError, "The geometric diffusion parameter " + `geo_params[0]` + " cannot be set."
883
884
885 elif len(geo_params) > 1:
886 raise RelaxUnknownParamCombError, ('geometric parameter set', geo_params)
887
888
889
890
891
892
893 if len(orient_params):
894 raise RelaxError, "For spherical diffusion, the orientation parameters " + `orient_params` + " should not exist."
895
896
897
898
899
900 elif self.relax.data.diff[self.run].type == 'spheroid':
901
902
903
904
905 if len(geo_params) == 1:
906
907 if geo_params[0] == 'tm':
908 self.relax.data.diff[self.run].tm = geo_values[0]
909
910
911 elif geo_params[0] == 'Diso':
912 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * geo_values[0])
913
914
915 elif geo_params[0] == 'Da':
916 self.relax.data.diff[self.run].Da = geo_values[0]
917
918
919 elif geo_params[0] == 'Dratio':
920 Dratio = geo_values[0]
921 self.relax.data.diff[self.run].Da = (Dratio - 1.0) / (2.0 * self.relax.data.diff[self.run].tm * (Dratio + 2.0))
922
923
924 else:
925 raise RelaxError, "The geometric diffusion parameter " + `geo_params[0]` + " cannot be set."
926
927
928 elif len(geo_params) == 2:
929
930 if geo_params.count('tm') == 1 and geo_params.count('Da') == 1:
931
932 tm = geo_values[geo_params.index('tm')]
933 Da = geo_values[geo_params.index('Da')]
934
935
936 self.relax.data.diff[self.run].tm = tm
937 self.relax.data.diff[self.run].Da = Da
938
939
940 elif geo_params.count('Diso') == 1 and geo_params.count('Da') == 1:
941
942 Diso = geo_values[geo_params.index('Diso')]
943 Da = geo_values[geo_params.index('Da')]
944
945
946 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * Diso)
947 self.relax.data.diff[self.run].Da = Da
948
949
950 elif geo_params.count('tm') == 1 and geo_params.count('Dratio') == 1:
951
952 tm = geo_values[geo_params.index('tm')]
953 Dratio = geo_values[geo_params.index('Dratio')]
954
955
956 self.relax.data.diff[self.run].tm = tm
957 self.relax.data.diff[self.run].Da = (Dratio - 1.0) / (2.0 * tm * (Dratio + 2.0))
958
959
960 elif geo_params.count('Dpar') == 1 and geo_params.count('Dpar') == 1:
961
962 Dpar = geo_values[geo_params.index('Dpar')]
963 Dper = geo_values[geo_params.index('Dper')]
964
965
966 self.relax.data.diff[self.run].tm = 1.0 / (2.0 * (Dpar + 2.0*Dper))
967 self.relax.data.diff[self.run].Da = Dpar - Dper
968
969
970 elif geo_params.count('Diso') == 1 and geo_params.count('Dratio') == 1:
971
972 Diso = geo_values[geo_params.index('Diso')]
973 Dratio = geo_values[geo_params.index('Dratio')]
974
975
976 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * Diso)
977 self.relax.data.diff[self.run].Da = 3.0 * Diso * (Dratio - 1.0) / (Dratio + 2.0)
978
979
980 else:
981 raise RelaxUnknownParamCombError, ('geometric parameter set', geo_params)
982
983
984 elif len(geo_params) > 2:
985 raise RelaxUnknownParamCombError, ('geometric parameter set', geo_params)
986
987
988
989
990
991
992 if len(orient_params) == 1:
993
994 if orient_params[0] == 'theta':
995 self.relax.data.diff[self.run].theta = orient_values[orient_params.index('theta')]
996
997
998 elif orient_params[0] == 'phi':
999 self.relax.data.diff[self.run].phi = orient_values[orient_params.index('phi')]
1000
1001
1002 elif len(orient_params) == 2:
1003
1004 if orient_params.count('theta') == 1 and orient_params.count('phi') == 1:
1005 self.relax.data.diff[self.run].theta = orient_values[orient_params.index('theta')]
1006 self.relax.data.diff[self.run].phi = orient_values[orient_params.index('phi')]
1007
1008
1009 else:
1010 raise RelaxUnknownParamCombError, ('orientational parameter set', orient_params)
1011
1012
1013 elif len(orient_params) > 2:
1014 raise RelaxUnknownParamCombError, ('orientational parameter set', orient_params)
1015
1016
1017
1018
1019
1020 elif self.relax.data.diff[self.run].type == 'ellipsoid':
1021
1022
1023
1024
1025 if len(geo_params) == 1:
1026
1027 if geo_params[0] == 'tm':
1028 self.relax.data.diff[self.run].tm = geo_values[0]
1029
1030
1031 elif geo_params[0] == 'Diso':
1032 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * geo_values[0])
1033
1034
1035 elif geo_params[0] == 'Da':
1036 self.relax.data.diff[self.run].Da = geo_values[0]
1037
1038
1039 elif geo_params[0] == 'Dr':
1040 self.relax.data.diff[self.run].Dr = geo_values[0]
1041
1042
1043 else:
1044 raise RelaxError, "The geometric diffusion parameter " + `geo_params[0]` + " cannot be set."
1045
1046
1047 elif len(geo_params) == 2:
1048
1049 if geo_params.count('tm') == 1 and geo_params.count('Da') == 1:
1050
1051 tm = geo_values[geo_params.index('tm')]
1052 Da = geo_values[geo_params.index('Da')]
1053
1054
1055 self.relax.data.diff[self.run].tm = tm
1056 self.relax.data.diff[self.run].Da = Da
1057
1058
1059 elif geo_params.count('tm') == 1 and geo_params.count('Dr') == 1:
1060
1061 tm = geo_values[geo_params.index('tm')]
1062 Dr = geo_values[geo_params.index('Dr')]
1063
1064
1065 self.relax.data.diff[self.run].tm = tm
1066 self.relax.data.diff[self.run].Dr = Dr
1067
1068
1069 elif geo_params.count('Diso') == 1 and geo_params.count('Da') == 1:
1070
1071 Diso = geo_values[geo_params.index('Diso')]
1072 Da = geo_values[geo_params.index('Da')]
1073
1074
1075 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * Diso)
1076 self.relax.data.diff[self.run].Da = Da
1077
1078
1079 elif geo_params.count('Diso') == 1 and geo_params.count('Dr') == 1:
1080
1081 Diso = geo_values[geo_params.index('Diso')]
1082 Dr = geo_values[geo_params.index('Dr')]
1083
1084
1085 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * Diso)
1086 self.relax.data.diff[self.run].Dr = Dr
1087
1088
1089 elif geo_params.count('Da') == 1 and geo_params.count('Dr') == 1:
1090
1091 Da = geo_values[geo_params.index('Da')]
1092 Dr = geo_values[geo_params.index('Dr')]
1093
1094
1095 self.relax.data.diff[self.run].Da = Da
1096 self.relax.data.diff[self.run].Da = Dr
1097
1098
1099 else:
1100 raise RelaxUnknownParamCombError, ('geometric parameter set', geo_params)
1101
1102
1103 elif len(geo_params) == 3:
1104
1105 if geo_params.count('tm') == 1 and geo_params.count('Da') == 1 and geo_params.count('Dr') == 1:
1106
1107 tm = geo_values[geo_params.index('tm')]
1108 Da = geo_values[geo_params.index('Da')]
1109 Dr = geo_values[geo_params.index('Dr')]
1110
1111
1112 self.relax.data.diff[self.run].tm = tm
1113 self.relax.data.diff[self.run].Da = Da
1114 self.relax.data.diff[self.run].Dr = Dr
1115
1116
1117 elif geo_params.count('Diso') == 1 and geo_params.count('Da') == 1 and geo_params.count('Dr') == 1:
1118
1119 Diso = geo_values[geo_params.index('Diso')]
1120 Da = geo_values[geo_params.index('Da')]
1121 Dr = geo_values[geo_params.index('Dr')]
1122
1123
1124 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * Diso)
1125 self.relax.data.diff[self.run].Da = Da
1126 self.relax.data.diff[self.run].Dr = Dr
1127
1128
1129 elif geo_params.count('Dx') == 1 and geo_params.count('Dy') == 1 and geo_params.count('Dz') == 1:
1130
1131 Dx = geo_values[geo_params.index('Dx')]
1132 Dy = geo_values[geo_params.index('Dy')]
1133 Dz = geo_values[geo_params.index('Dz')]
1134
1135
1136 if Dx + Dy + Dz == 0.0:
1137 self.relax.data.diff[self.run].tm = 1e99
1138 else:
1139 self.relax.data.diff[self.run].tm = 0.5 / (Dx + Dy + Dz)
1140
1141
1142 self.relax.data.diff[self.run].Da = Dz - 0.5*(Dx + Dy)
1143
1144
1145 if self.relax.data.diff[self.run].Da == 0.0:
1146 self.relax.data.diff[self.run].Dr = (Dy - Dx) * 1e99
1147 else:
1148 self.relax.data.diff[self.run].Dr = (Dy - Dx) / (2.0*self.relax.data.diff[self.run].Da)
1149
1150
1151 else:
1152 raise RelaxUnknownParamCombError, ('geometric parameter set', geo_params)
1153
1154
1155
1156 elif len(geo_params) > 3:
1157 raise RelaxUnknownParamCombError, ('geometric parameter set', geo_params)
1158
1159
1160
1161
1162
1163
1164 if len(orient_params) == 1:
1165
1166 if orient_params[0] == 'alpha':
1167 self.relax.data.diff[self.run].alpha = orient_values[orient_params.index('alpha')]
1168
1169
1170 elif orient_params[0] == 'beta':
1171 self.relax.data.diff[self.run].beta = orient_values[orient_params.index('beta')]
1172
1173
1174 elif orient_params[0] == 'gamma':
1175 self.relax.data.diff[self.run].gamma = orient_values[orient_params.index('gamma')]
1176
1177
1178 elif len(orient_params) == 2:
1179
1180 if orient_params.count('alpha') == 1 and orient_params.count('beta') == 1:
1181 self.relax.data.diff[self.run].alpha = orient_values[orient_params.index('alpha')]
1182 self.relax.data.diff[self.run].beta = orient_values[orient_params.index('beta')]
1183
1184
1185 if orient_params.count('alpha') == 1 and orient_params.count('gamma') == 1:
1186 self.relax.data.diff[self.run].alpha = orient_values[orient_params.index('alpha')]
1187 self.relax.data.diff[self.run].gamma = orient_values[orient_params.index('gamma')]
1188
1189
1190 if orient_params.count('beta') == 1 and orient_params.count('gamma') == 1:
1191 self.relax.data.diff[self.run].beta = orient_values[orient_params.index('beta')]
1192 self.relax.data.diff[self.run].gamma = orient_values[orient_params.index('gamma')]
1193
1194
1195 else:
1196 raise RelaxUnknownParamCombError, ('orientational parameter set', orient_params)
1197
1198
1199 elif len(orient_params) == 3:
1200
1201 if orient_params.count('alpha') == 1 and orient_params.count('beta') == 1:
1202 self.relax.data.diff[self.run].alpha = orient_values[orient_params.index('alpha')]
1203 self.relax.data.diff[self.run].beta = orient_values[orient_params.index('beta')]
1204 self.relax.data.diff[self.run].gamma = orient_values[orient_params.index('gamma')]
1205
1206
1207 else:
1208 raise RelaxUnknownParamCombError, ('orientational parameter set', orient_params)
1209
1210
1211 elif len(orient_params) > 3:
1212 raise RelaxUnknownParamCombError, ('orientational parameter set', orient_params)
1213
1214
1215
1216
1217
1218 if orient_params:
1219 self.fold_angles()
1220
1221
1223 """Function for setting up spherical diffusion."""
1224
1225
1226 self.relax.data.diff[self.run].type = 'sphere'
1227
1228
1229 if self.param_types == 0:
1230
1231 self.relax.data.diff[self.run].tm = self.params * self.time_scale
1232
1233
1234 self.relax.data.diff[self.run].Diso = 6.0 / self.relax.data.diff[self.run].tm
1235
1236
1237 elif self.param_types == 1:
1238
1239 self.relax.data.diff[self.run].Diso = self.params * self.d_scale
1240
1241
1242 self.relax.data.diff[self.run].tm = 1.0 / (6.0 * self.relax.data.diff[self.run].Diso)
1243
1244
1245 else:
1246 raise RelaxUnknownParamCombError, ('param_types', self.param_types)
1247
1248
1250 """Function for setting up spheroidal diffusion."""
1251
1252
1253 self.relax.data.diff[self.run].type = 'spheroid'
1254
1255
1256 allowed_types = [None, 'oblate', 'prolate']
1257 if self.spheroid_type not in allowed_types:
1258 raise RelaxError, "The 'spheroid_type' argument " + `self.spheroid_type` + " should be 'oblate', 'prolate', or None."
1259 self.relax.data.diff[self.run].spheroid_type = self.spheroid_type
1260
1261
1262 if self.param_types == 0:
1263
1264 tm, Da, theta, phi = self.params
1265
1266
1267 tm = tm * self.time_scale
1268 Da = Da * self.d_scale
1269
1270
1271 self.set(run=self.run, value=[tm, Da], param=['tm', 'Da'])
1272
1273
1274 elif self.param_types == 1:
1275
1276 Diso, Da, theta, phi = self.params
1277
1278
1279 Diso = Diso * self.d_scale
1280 Da = Da * self.d_scale
1281
1282
1283 self.set(run=self.run, value=[Diso, Da], param=['Diso', 'Da'])
1284
1285
1286 elif self.param_types == 2:
1287
1288 tm, Dratio, theta, phi = self.params
1289
1290
1291 tm = tm * self.time_scale
1292
1293
1294 self.set(run=self.run, value=[tm, Dratio], param=['tm', 'Dratio'])
1295
1296
1297 elif self.param_types == 3:
1298
1299 Dpar, Dper, theta, phi = self.params
1300
1301
1302 Dpar = Dpar * self.d_scale
1303 Dper = Dper * self.d_scale
1304
1305
1306 self.set(run=self.run, value=[Dpar, Dper], param=['Dpar', 'Dper'])
1307
1308
1309 elif self.param_types == 4:
1310
1311 Diso, Dratio, theta, phi = self.params
1312
1313
1314 Diso = Diso * self.d_scale
1315
1316
1317 self.set(run=self.run, value=[Diso, Dratio], param=['Diso', 'Dratio'])
1318
1319
1320 else:
1321 raise RelaxUnknownParamCombError, ('param_types', self.param_types)
1322
1323
1324 if self.angle_units == 'deg':
1325 theta = (theta / 360.0) * 2.0 * pi
1326 phi = (phi / 360.0) * 2.0 * pi
1327
1328
1329 self.set(run=self.run, value=[theta, phi], param=['theta', 'phi'])
1330
1331
1333 """Function for testing the validity of the input parameters."""
1334
1335
1336 tm = self.relax.data.diff[self.run].tm
1337 if tm <= 0.0 or tm > 1e-6:
1338 raise RelaxError, "The tm value of " + `tm` + " should be between zero and one microsecond."
1339
1340
1341 if num_params == 4:
1342
1343 Diso = 1.0 / (6.0 * self.relax.data.diff[self.run].tm)
1344 Da = self.relax.data.diff[self.run].Da
1345
1346
1347 if Da < -1.5*Diso or Da > 3.0*Diso:
1348 raise RelaxError, "The Da value of " + `Da` + " should be between -3/2 * Diso and 3Diso."
1349
1350
1351 if num_params == 6:
1352
1353 Diso = 1.0 / (6.0 * self.relax.data.diff[self.run].tm)
1354 Da = self.relax.data.diff[self.run].Da
1355 Dr = self.relax.data.diff[self.run].Dr
1356
1357
1358 if Da < 0.0 or Da > 3.0*Diso:
1359 raise RelaxError, "The Da value of " + `Da` + " should be between zero and 3Diso."
1360
1361
1362 if Dr < 0.0 or Dr > 1.0:
1363 raise RelaxError, "The Dr value of " + `Dr` + " should be between zero and one."
1364
1365
1367 """Function for calculating the unit axes of the diffusion tensor.
1368
1369 Spheroid
1370 ~~~~~~~~
1371
1372 The unit Dpar vector is
1373
1374 | sin(theta) * cos(phi) |
1375 Dpar = | sin(theta) * sin(phi) |
1376 | cos(theta) |
1377
1378
1379 Ellipsoid
1380 ~~~~~~~~~
1381
1382 The unit Dx vector is
1383
1384 | -sin(alpha) * sin(gamma) + cos(alpha) * cos(beta) * cos(gamma) |
1385 Dx = | -sin(alpha) * cos(gamma) - cos(alpha) * cos(beta) * sin(gamma) |
1386 | cos(alpha) * sin(beta) |
1387
1388 The unit Dy vector is
1389
1390 | cos(alpha) * sin(gamma) + sin(alpha) * cos(beta) * cos(gamma) |
1391 Dy = | cos(alpha) * cos(gamma) - sin(alpha) * cos(beta) * sin(gamma) |
1392 | sin(alpha) * sin(beta) |
1393
1394 The unit Dz vector is
1395
1396 | -sin(beta) * cos(gamma) |
1397 Dz = | sin(beta) * sin(gamma) |
1398 | cos(beta) |
1399
1400 """
1401
1402
1403 if self.relax.data.diff[self.run].type == 'spheroid':
1404
1405 Dpar = zeros(3, Float64)
1406
1407
1408 sin_theta = sin(self.relax.data.diff[self.run].theta)
1409 cos_theta = cos(self.relax.data.diff[self.run].theta)
1410 sin_phi = sin(self.relax.data.diff[self.run].phi)
1411 cos_phi = cos(self.relax.data.diff[self.run].phi)
1412
1413
1414 Dpar[0] = sin_theta * cos_phi
1415 Dpar[1] = sin_theta * sin_phi
1416 Dpar[2] = cos_theta
1417
1418
1419 return Dpar
1420
1421
1422 if self.relax.data.diff[self.run].type == 'ellipsoid':
1423
1424 Dx = zeros(3, Float64)
1425 Dy = zeros(3, Float64)
1426 Dz = zeros(3, Float64)
1427
1428
1429 sin_alpha = sin(self.relax.data.diff[self.run].alpha)
1430 cos_alpha = cos(self.relax.data.diff[self.run].alpha)
1431 sin_beta = sin(self.relax.data.diff[self.run].beta)
1432 cos_beta = cos(self.relax.data.diff[self.run].beta)
1433 sin_gamma = sin(self.relax.data.diff[self.run].gamma)
1434 cos_gamma = cos(self.relax.data.diff[self.run].gamma)
1435
1436
1437 Dx[0] = -sin_alpha * sin_gamma + cos_alpha * cos_beta * cos_gamma
1438 Dx[1] = -sin_alpha * cos_gamma - cos_alpha * cos_beta * sin_gamma
1439 Dx[2] = cos_alpha * sin_beta
1440
1441
1442 Dx[0] = cos_alpha * sin_gamma + sin_alpha * cos_beta * cos_gamma
1443 Dx[1] = cos_alpha * cos_gamma - sin_alpha * cos_beta * sin_gamma
1444 Dx[2] = sin_alpha * sin_beta
1445
1446
1447 Dx[0] = -sin_beta * cos_gamma
1448 Dx[1] = sin_beta * sin_gamma
1449 Dx[2] = cos_beta
1450
1451
1452 return Dx, Dy, Dz
1453