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