Package data_store :: Module align_tensor
[hide private]
[frames] | no frames]

Source Code for Module data_store.align_tensor

   1  ############################################################################### 
   2  #                                                                             # 
   3  # Copyright (C) 2001-2004,2006-2009,2011-2012,2014-2015 Edward d'Auvergne     # 
   4  # Copyright (C) 2006 Chris MacRaild                                           # 
   5  # Copyright (C) 2008 Sebastien Morin                                          # 
   6  #                                                                             # 
   7  # This file is part of the program relax (http://www.nmr-relax.com).          # 
   8  #                                                                             # 
   9  # This program is free software: you can redistribute it and/or modify        # 
  10  # it under the terms of the GNU General Public License as published by        # 
  11  # the Free Software Foundation, either version 3 of the License, or           # 
  12  # (at your option) any later version.                                         # 
  13  #                                                                             # 
  14  # This program is distributed in the hope that it will be useful,             # 
  15  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
  16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
  17  # GNU General Public License for more details.                                # 
  18  #                                                                             # 
  19  # You should have received a copy of the GNU General Public License           # 
  20  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
  21  #                                                                             # 
  22  ############################################################################### 
  23   
  24  # Module docstring. 
  25  """The alignment tensor objects of the relax data store.""" 
  26   
  27  # Python module imports. 
  28  from math import pi, sqrt 
  29  from numpy import eye, float64, zeros 
  30  from numpy.linalg import det, eig, eigvals 
  31  from re import search 
  32   
  33  # relax module imports. 
  34  from data_store.data_classes import Element 
  35  from lib.float import nan 
  36  from lib.geometry.rotations import R_to_euler_zyz 
  37  from lib.errors import RelaxError 
  38  from lib.xml import fill_object_contents, xml_to_object 
  39   
  40   
  41  # Constants (once off calculations for speed). 
  42  fact_A2 = sqrt(2.0*pi / 15.0) 
  43  fact_A1 = sqrt(8.0*pi / 15.0) 
  44  fact_A0 = sqrt(4.0*pi / 5.0) 
  45   
  46   
47 -def calc_A(Axx, Ayy, Azz, Axy, Axz, Ayz):
48 """Function for calculating the alignment tensor (in the structural frame). 49 50 @param Axx: The Axx tensor element. 51 @type Axx: float 52 @param Ayy: The Ayy tensor element. 53 @type Ayy: float 54 @param Azz: The Azz tensor element. 55 @type Azz: float 56 @param Axy: The Axy tensor element. 57 @type Axy: float 58 @param Axz: The Axz tensor element. 59 @type Axz: float 60 @param Ayz: The Ayz tensor element. 61 @type Ayz: float 62 @return: The alignment tensor (within the structural frame). 63 @rtype: 3x3 numpy float64 array 64 """ 65 66 # Initialise the tensor. 67 tensor = zeros((3, 3), float64) 68 69 # Populate the diagonal elements. 70 tensor[0, 0] = Axx 71 tensor[1, 1] = Ayy 72 tensor[2, 2] = Azz 73 74 # Populate the off diagonal elements. 75 tensor[0, 1] = tensor[1, 0] = Axy 76 tensor[0, 2] = tensor[2, 0] = Axz 77 tensor[1, 2] = tensor[2, 1] = Ayz 78 79 # Return the tensor. 80 return tensor
81 82
83 -def calc_A_5D(Axx, Ayy, Azz, Axy, Axz, Ayz):
84 """Function for calculating the alignment tensor in the 5D vector notation. 85 86 @param Axx: The Axx tensor element. 87 @type Axx: float 88 @param Ayy: The Ayy tensor element. 89 @type Ayy: float 90 @param Azz: The Azz tensor element. 91 @type Azz: float 92 @param Axy: The Axy tensor element. 93 @type Axy: float 94 @param Axz: The Axz tensor element. 95 @type Axz: float 96 @param Ayz: The Ayz tensor element. 97 @type Ayz: float 98 @return: The alignment 5D tensor (within the structural frame). 99 @rtype: numpy rank-1 5D tensor 100 """ 101 102 # Initialise the tensor. 103 tensor = zeros(5, float64) 104 105 # Populate the tensor. 106 tensor[0] = Axx 107 tensor[1] = Ayy 108 tensor[2] = Axy 109 tensor[3] = Axz 110 tensor[4] = Ayz 111 112 # Return the tensor. 113 return tensor
114 115
116 -def calc_A_diag(A):
117 """Calculate the diagonalised alignment tensor. 118 119 The diagonalised alignment tensor is defined as:: 120 121 | Axx' 0 0 | 122 tensor = | 0 Ayy' 0 |. 123 | 0 0 Azz'| 124 125 The diagonalised alignment tensor is calculated by eigenvalue decomposition. 126 127 128 @param A: The full alignment tensor. 129 @type A: numpy array ((3, 3), float64) 130 @return: The diagonalised alignment tensor. 131 @rtype: numpy array ((3, 3), float64) 132 """ 133 134 # The eigenvalues. 135 vals = eigvals(A) 136 137 # Find the |x| < |y| < |z| indices. 138 abs_vals = abs(vals).tolist() 139 Axx_index = abs_vals.index(min(abs_vals)) 140 Azz_index = abs_vals.index(max(abs_vals)) 141 last_index = list(range(3)) 142 last_index.pop(max(Axx_index, Azz_index)) 143 last_index.pop(min(Axx_index, Azz_index)) 144 Ayy_index = last_index[0] 145 146 # Empty tensor. 147 tensor_diag = zeros((3, 3), float64) 148 149 # Fill the elements. 150 tensor_diag[0, 0] = vals[Axx_index] 151 tensor_diag[1, 1] = vals[Ayy_index] 152 tensor_diag[2, 2] = vals[Azz_index] 153 154 # Return the tensor. 155 return tensor_diag
156 157
158 -def calc_Aa(A_diag):
159 """Calculate the anisotropic parameter Aa. 160 161 This is given by:: 162 163 Aa = 3/2Azz = Szz, 164 165 where Azz and Szz are the eigenvalues. 166 167 168 @param A_diag: The full alignment tensor, diagonalised. 169 @type A_diag: numpy array ((3, 3), float64) 170 @return: The Aa parameter 171 @rtype: float 172 """ 173 174 # Return Aa. 175 return 1.5 * A_diag[2, 2]
176 177
178 -def calc_Ar(A_diag):
179 """Calculate the rhombic parameter Ar. 180 181 This is given by:: 182 183 Ar = Axx - Ayy, 184 185 where Axx and Ayy are the eigenvalues. 186 187 188 @param A_diag: The full alignment tensor, diagonalised. 189 @type A_diag: numpy array ((3, 3), float64) 190 @return: The Ar parameter 191 @rtype: float 192 """ 193 194 # Return Ar. 195 return A_diag[0, 0] - A_diag[1, 1]
196 197
198 -def calc_Axxyy(Axx, Ayy):
199 """Function for calculating the Axx-yy value. 200 201 The equation for calculating the parameter is:: 202 203 Axx-yy = Axx - Ayy. 204 205 @param Axx: The Axx component of the alignment tensor. 206 @type Axx: float 207 @param Ayy: The Ayy component of the alignment tensor. 208 @type Ayy: float 209 @return: The Axx-yy component of the alignment tensor. 210 @rtype: float 211 """ 212 213 # Calculate and return the Axx-yy value. 214 return Axx - Ayy
215 216
217 -def calc_Azz(Axx, Ayy):
218 """Function for calculating the Azz value. 219 220 The equation for calculating the parameter is:: 221 222 Azz = - Axx - Ayy. 223 224 @param Axx: The Axx component of the alignment tensor. 225 @type Axx: float 226 @param Ayy: The Ayy component of the alignment tensor. 227 @type Ayy: float 228 @return: The Azz component of the alignment tensor. 229 @rtype: float 230 """ 231 232 # Calculate and return the Azz value. 233 return - Axx - Ayy
234 235
236 -def calc_eigvals(A):
237 """Calculate the eigenvalues and eigenvectors of the alignment tensor (A). 238 239 @param A: The full alignment tensor. 240 @type A: numpy array ((3, 3), float64) 241 @return: The eigensystem. 242 @rtype: tuple of numpy array (float64) 243 """ 244 245 # The eigenvalues. 246 vals = eigvals(A) 247 248 # Find the |x| < |y| < |z| indices. 249 abs_vals = abs(vals).tolist() 250 x_index = abs_vals.index(min(abs_vals)) 251 z_index = abs_vals.index(max(abs_vals)) 252 last_index = list(range(3)) 253 last_index.pop(max(x_index, z_index)) 254 last_index.pop(min(x_index, z_index)) 255 y_index = last_index[0] 256 257 # Return the sorted eigenvalues. 258 return [vals[x_index], vals[y_index], vals[z_index]]
259 260
261 -def calc_eta(A_diag):
262 """Calculate the asymmetry parameter eta. 263 264 This is given by:: 265 266 eta = (Axx - Ayy) / Azz 267 268 where Aii are the eigenvalues. 269 270 271 @param A_diag: The full alignment tensor, diagonalised. 272 @type A_diag: numpy array ((3, 3), float64) 273 @return: The eta parameter 274 @rtype: float 275 """ 276 277 # Zero Azz value, so return NaN. 278 if A_diag[2, 2] == 0: 279 return nan 280 281 # Return eta. 282 return (A_diag[0, 0] - A_diag[1, 1]) / A_diag[2, 2]
283 284
285 -def calc_euler(rotation):
286 """Calculate the zyz notation Euler angles. 287 288 @param rotation: The rotation matrix. 289 @type rotation: numpy 3D, rank-2 array 290 @return: The Euler angles alpha, beta, and gamma in zyz notation. 291 @rtype: tuple of float 292 """ 293 294 return R_to_euler_zyz(rotation)
295 296
297 -def calc_S(Sxx, Syy, Szz, Sxy, Sxz, Syz):
298 """Function for calculating the alignment tensor (in the structural frame). 299 300 @param Sxx: The Sxx tensor element. 301 @type Sxx: float 302 @param Syy: The Syy tensor element. 303 @type Syy: float 304 @param Szz: The Szz tensor element. 305 @type Szz: float 306 @param Sxy: The Sxy tensor element. 307 @type Sxy: float 308 @param Sxz: The Sxz tensor element. 309 @type Sxz: float 310 @param Syz: The Syz tensor element. 311 @type Syz: float 312 @return: The alignment tensor (within the structural frame). 313 @rtype: 3x3 numpy float64 array 314 """ 315 316 # Initialise the tensor. 317 tensor = zeros((3, 3), float64) 318 319 # Populate the diagonal elements. 320 tensor[0, 0] = Sxx 321 tensor[1, 1] = Syy 322 tensor[2, 2] = Szz 323 324 # Populate the off diagonal elements. 325 tensor[0, 1] = tensor[1, 0] = Sxy 326 tensor[0, 2] = tensor[2, 0] = Sxz 327 tensor[1, 2] = tensor[2, 1] = Syz 328 329 # Return the tensor. 330 return tensor
331 332
333 -def calc_S_5D(Sxx, Syy, Szz, Sxy, Sxz, Syz):
334 """Function for calculating the alignment tensor in the 5D vector notation. 335 336 @param Sxx: The Sxx tensor element. 337 @type Sxx: float 338 @param Syy: The Syy tensor element. 339 @type Syy: float 340 @param Szz: The Szz tensor element. 341 @type Szz: float 342 @param Sxy: The Sxy tensor element. 343 @type Sxy: float 344 @param Sxz: The Sxz tensor element. 345 @type Sxz: float 346 @param Syz: The Syz tensor element. 347 @type Syz: float 348 @return: The alignment 5D tensor (within the structural frame). 349 @rtype: numpy rank-1 5D tensor 350 """ 351 352 # Initialise the tensor. 353 tensor = zeros(5, float64) 354 355 # Populate the tensor. 356 tensor[0] = Sxx 357 tensor[1] = Syy 358 tensor[2] = Sxy 359 tensor[3] = Sxz 360 tensor[4] = Syz 361 362 # Return the tensor. 363 return tensor
364 365
366 -def calc_S_diag(tensor):
367 """Calculate the diagonalised alignment tensor. 368 369 The diagonalised alignment tensor is defined as:: 370 371 | Sxx' 0 0 | 372 tensor = | 0 Syy' 0 |. 373 | 0 0 Szz'| 374 375 The diagonalised alignment tensor is calculated by eigenvalue decomposition. 376 377 378 @param tensor: The full alignment tensor in its eigenframe. 379 @type tensor: numpy array ((3, 3), float64) 380 @return: The diagonalised alignment tensor. 381 @rtype: numpy array ((3, 3), float64) 382 """ 383 384 # The eigenvalues. 385 vals = eigvals(tensor) 386 387 # Find the |x| < |y| < |z| indices. 388 abs_vals = abs(vals).tolist() 389 Sxx_index = abs_vals.index(min(abs_vals)) 390 Szz_index = abs_vals.index(max(abs_vals)) 391 last_index = list(range(3)) 392 last_index.pop(max(Sxx_index, Szz_index)) 393 last_index.pop(min(Sxx_index, Szz_index)) 394 Syy_index = last_index[0] 395 396 # Empty tensor. 397 tensor_diag = zeros((3, 3), float64) 398 399 # Fill the elements. 400 tensor_diag[0, 0] = vals[Sxx_index] 401 tensor_diag[1, 1] = vals[Syy_index] 402 tensor_diag[2, 2] = vals[Szz_index] 403 404 # Return the tensor. 405 return tensor_diag
406 407
408 -def calc_A0(Szz):
409 """Function for calculating the A0 irreducible component of the Saupe order matrix. 410 411 The equation for calculating the parameter is:: 412 413 / 4pi \ 1/2 414 A0 = | --- | Szz . 415 \ 5 / 416 417 418 @param Szz: The Szz component of the Saupe order matrix. 419 @type Szz: float 420 @return: The A0 irreducible component of the Saupe order matrix. 421 @rtype: float 422 """ 423 424 # Calculate and return the A0 value. 425 return fact_A0 * Szz
426 427
428 -def calc_A1(Sxz, Syz):
429 """Function for calculating the A1 irreducible component of the Saupe order matrix. 430 431 The equation for calculating the parameter is:: 432 433 / 8pi \ 1/2 434 A1 = | --- | (Sxz + iSyz) . 435 \ 15 / 436 437 438 @param Sxz: The Sxz component of the Saupe order matrix. 439 @type Sxz: float 440 @param Syz: The Syz component of the Saupe order matrix. 441 @type Syz: float 442 @return: The A1 irreducible component of the Saupe order matrix. 443 @rtype: float 444 """ 445 446 # Calculate and return the A1 value. 447 return fact_A1 * (Sxz + 1.j*Syz)
448 449
450 -def calc_A2(Sxx, Syy, Sxy):
451 """Function for calculating the A2 irreducible component of the Saupe order matrix. 452 453 The equation for calculating the parameter is:: 454 455 / 2pi \ 1/2 456 A2 = | --- | (Sxx - Syy + 2iSxy) . 457 \ 15 / 458 459 460 @param Sxx: The Sxx component of the Saupe order matrix. 461 @type Sxx: float 462 @param Syy: The Syy component of the Saupe order matrix. 463 @type Syy: float 464 @return: The A2 irreducible component of the Saupe order matrix. 465 @rtype: float 466 """ 467 468 # Calculate and return the A2 value. 469 return fact_A2 * (Sxx - Syy + 2.j*Sxy)
470 471
472 -def calc_Am1(Sxz, Syz):
473 """Function for calculating the A-1 irreducible component of the Saupe order matrix. 474 475 The equation for calculating the parameter is:: 476 477 / 8pi \ 1/2 478 A-1 = - | --- | (Sxz - iSyz) . 479 \ 15 / 480 481 482 @param Sxz: The Sxz component of the Saupe order matrix. 483 @type Sxz: float 484 @param Syz: The Syz component of the Saupe order matrix. 485 @type Syz: float 486 @return: The A-1 irreducible component of the Saupe order matrix. 487 @rtype: float 488 """ 489 490 # Calculate and return the A-1 value. 491 return -fact_A1 * (Sxz - 1.j*Syz)
492 493
494 -def calc_Am2(Sxx, Syy, Sxy):
495 """Function for calculating the A-2 irreducible component of the Saupe order matrix. 496 497 The equation for calculating the parameter is:: 498 499 / 2pi \ 1/2 500 A-2 = | --- | (Sxx - Syy - 2iSxy) , 501 \ 15 / 502 503 504 @param Sxx: The Sxx component of the Saupe order matrix. 505 @type Sxx: float 506 @param Syy: The Syy component of the Saupe order matrix. 507 @type Syy: float 508 @return: The A-2 irreducible component of the Saupe order matrix. 509 @rtype: float 510 """ 511 512 # Calculate and return the A-2 value. 513 return fact_A2 * (Sxx - Syy - 2.j*Sxy)
514 515
516 -def calc_Sxx(Axx):
517 """Function for calculating the Axx value. 518 519 The equation for calculating the parameter is:: 520 521 Sxx = 3/2 Axx. 522 523 @param Axx: The Axx component of the alignment tensor. 524 @type Axx: float 525 @rtype: float 526 """ 527 528 # Calculate and return the Axx value. 529 return 3.0/2.0 * Axx
530 531
532 -def calc_Sxxyy(Sxx, Syy):
533 """Function for calculating the Sxx-yy value. 534 535 The equation for calculating the parameter is:: 536 537 Sxx-yy = Sxx - Syy. 538 539 @param Sxx: The Sxx component of the Saupe order matrix. 540 @type Sxx: float 541 @param Syy: The Syy component of the Saupe order matrix. 542 @type Syy: float 543 @return: The Sxx-yy component of the Saupe order matrix. 544 @rtype: float 545 """ 546 547 # Calculate and return the Sxx-yy value. 548 return Sxx - Syy
549 550
551 -def calc_Sxy(Axy):
552 """Function for calculating the Axy value. 553 554 The equation for calculating the parameter is:: 555 556 Sxy = 3/2 Axy. 557 558 @param Axy: The Axy component of the alignment tensor. 559 @type Axy: float 560 @rtype: float 561 """ 562 563 # Calculate and return the Axy value. 564 return 3.0/2.0 * Axy
565 566
567 -def calc_Sxz(Axz):
568 """Function for calculating the Axz value. 569 570 The equation for calculating the parameter is:: 571 572 Sxz = 3/2 Axz. 573 574 @param Axz: The Axz component of the alignment tensor. 575 @type Axz: float 576 @rtype: float 577 """ 578 579 # Calculate and return the Axz value. 580 return 3.0/2.0 * Axz
581 582
583 -def calc_Syy(Ayy):
584 """Function for calculating the Ayy value. 585 586 The equation for calculating the parameter is:: 587 588 Syy = 3/2 Ayy. 589 590 @param Ayy: The Ayy component of the alignment tensor. 591 @type Ayy: float 592 @rtype: float 593 """ 594 595 # Calculate and return the Ayy value. 596 return 3.0/2.0 * Ayy
597 598
599 -def calc_Syz(Ayz):
600 """Function for calculating the Ayz value. 601 602 The equation for calculating the parameter is:: 603 604 Syz = 3/2 Ayz. 605 606 @param Ayz: The Ayz component of the alignment tensor. 607 @type Ayz: float 608 @rtype: float 609 """ 610 611 # Calculate and return the Ayz value. 612 return 3.0/2.0 * Ayz
613 614
615 -def calc_Szz(Sxx, Syy):
616 """Function for calculating the Szz value. 617 618 The equation for calculating the parameter is:: 619 620 Szz = - Sxx - Syy. 621 622 @param Sxx: The Sxx component of the Saupe order matrix. 623 @type Sxx: float 624 @param Syy: The Syy component of the Saupe order matrix. 625 @type Syy: float 626 @return: The Szz component of the Saupe order matrix. 627 @rtype: float 628 """ 629 630 # Calculate and return the Szz value. 631 return - Sxx - Syy
632 633
634 -def calc_P(Axx, Ayy, Azz, Axy, Axz, Ayz):
635 """Function for calculating the alignment tensor (in the structural frame). 636 637 @param Axx: The Axx tensor element. 638 @type Axx: float 639 @param Ayy: The Ayy tensor element. 640 @type Ayy: float 641 @param Azz: The Azz tensor element. 642 @type Azz: float 643 @param Axy: The Axy tensor element. 644 @type Axy: float 645 @param Axz: The Axz tensor element. 646 @type Axz: float 647 @param Ayz: The Ayz tensor element. 648 @type Ayz: float 649 @return: The alignment tensor (within the structural frame). 650 @rtype: 3x3 numpy float64 array 651 """ 652 653 # Initialise the tensor. 654 tensor = zeros((3, 3), float64) 655 656 # Populate the diagonal elements. 657 tensor[0, 0] = Axx 658 tensor[1, 1] = Ayy 659 tensor[2, 2] = Azz 660 661 # Populate the off diagonal elements. 662 tensor[0, 1] = tensor[1, 0] = Axy 663 tensor[0, 2] = tensor[2, 0] = Axz 664 tensor[1, 2] = tensor[2, 1] = Ayz 665 666 # Add 1/3 the identity matrix. 667 tensor = tensor + eye(3)/3.0 668 669 # Return the tensor. 670 return tensor
671 672
673 -def calc_P_5D(Axx, Ayy, Azz, Axy, Axz, Ayz):
674 """Function for calculating the alignment tensor in the 5D vector notation. 675 676 @param Axx: The Axx tensor element. 677 @type Axx: float 678 @param Ayy: The Ayy tensor element. 679 @type Ayy: float 680 @param Azz: The Azz tensor element. 681 @type Azz: float 682 @param Axy: The Axy tensor element. 683 @type Axy: float 684 @param Axz: The Axz tensor element. 685 @type Axz: float 686 @param Ayz: The Ayz tensor element. 687 @type Ayz: float 688 @return: The alignment 5D tensor (within the structural frame). 689 @rtype: numpy rank-1 5D tensor 690 """ 691 692 # Initialise the tensor. 693 tensor = zeros(5, float64) 694 695 # Populate the tensor. 696 tensor[0] = Axx + 1.0/3.0 697 tensor[1] = Ayy + 1.0/3.0 698 tensor[2] = Axy 699 tensor[3] = Axz 700 tensor[4] = Ayz 701 702 # Return the tensor. 703 return tensor
704 705
706 -def calc_P_diag(tensor):
707 """Calculate the diagonalised alignment tensor. 708 709 The diagonalised alignment tensor is defined as:: 710 711 | Pxx' 0 0 | 712 tensor = | 0 Pyy' 0 |. 713 | 0 0 Pzz'| 714 715 The diagonalised alignment tensor is calculated by eigenvalue decomposition. 716 717 718 @param tensor: The full alignment tensor in its eigenframe. 719 @type tensor: numpy array ((3, 3), float64) 720 @return: The diagonalised alignment tensor. 721 @rtype: numpy array ((3, 3), float64) 722 """ 723 724 # The eigenvalues. 725 vals = eigvals(tensor) 726 727 # Find the |x| < |y| < |z| indices. 728 abs_vals = abs(vals).tolist() 729 Pxx_index = abs_vals.index(min(abs_vals)) 730 Pzz_index = abs_vals.index(max(abs_vals)) 731 last_index = list(range(3)) 732 last_index.pop(max(Pxx_index, Pzz_index)) 733 last_index.pop(min(Pxx_index, Pzz_index)) 734 Pyy_index = last_index[0] 735 736 # Empty tensor. 737 tensor_diag = zeros((3, 3), float64) 738 739 # Fill the elements. 740 tensor_diag[0, 0] = vals[Pxx_index] 741 tensor_diag[1, 1] = vals[Pyy_index] 742 tensor_diag[2, 2] = vals[Pzz_index] 743 744 # Add 1/3 the identity matrix. 745 tensor = tensor + eye(3)/3.0 746 747 # Return the tensor. 748 return tensor_diag
749 750
751 -def calc_Pxx(Axx):
752 """Function for calculating the Pxx value. 753 754 The equation for calculating the parameter is:: 755 756 Pxx = Axx + 1/3. 757 758 @param Axx: The Axx component of the alignment tensor. 759 @type Axx: float 760 @rtype: float 761 """ 762 763 # Calculate and return the Pxx value. 764 return Axx + 1.0/3.0
765 766
767 -def calc_Pxxyy(Pxx, Pyy):
768 """Function for calculating the Pxx-yy value. 769 770 The equation for calculating the parameter is:: 771 772 Pxx-yy = Pxx - Pyy. 773 774 @param Pxx: The Pxx component of the alignment tensor. 775 @type Pxx: float 776 @param Pyy: The Pyy component of the alignment tensor. 777 @type Pyy: float 778 @return: The Pxx-yy component of the alignment tensor. 779 @rtype: float 780 """ 781 782 # Calculate and return the Pxx-yy value. 783 return Pxx - Pyy
784 785
786 -def calc_Pxy(Axy):
787 """Function for calculating the Pxy value. 788 789 The equation for calculating the parameter is:: 790 791 Pxy = Axy. 792 793 @param Axy: The Axy component of the alignment tensor. 794 @type Axy: float 795 @rtype: float 796 """ 797 798 # Calculate and return the Pxy value. 799 return Axy
800 801
802 -def calc_Pxz(Axz):
803 """Function for calculating the Pxz value. 804 805 The equation for calculating the parameter is:: 806 807 Pxz = Axz. 808 809 @param Axz: The Axz component of the alignment tensor. 810 @type Axz: float 811 @rtype: float 812 """ 813 814 # Calculate and return the Pxz value. 815 return Axz
816 817
818 -def calc_Pyy(Ayy):
819 """Function for calculating the Pyy value. 820 821 The equation for calculating the parameter is:: 822 823 Pyy = Ayy + 1/3. 824 825 @param Ayy: The Ayy component of the alignment tensor. 826 @type Ayy: float 827 @rtype: float 828 """ 829 830 # Calculate and return the Pyy value. 831 return Ayy + 1.0/3.0
832 833
834 -def calc_Pyz(Ayz):
835 """Function for calculating the Pyz value. 836 837 The equation for calculating the parameter is:: 838 839 Pyz = Ayz. 840 841 @param Ayz: The Ayz component of the alignment tensor. 842 @type Ayz: float 843 @rtype: float 844 """ 845 846 # Calculate and return the Pyz value. 847 return Ayz
848 849
850 -def calc_Pzz(Pxx, Pyy):
851 """Function for calculating the Pzz value. 852 853 The equation for calculating the parameter is:: 854 855 Pzz = 1 - Pxx - Pyy. 856 857 @param Pxx: The Pxx component of the alignment tensor. 858 @type Pxx: float 859 @param Pyy: The Pyy component of the alignment tensor. 860 @type Pyy: float 861 @return: The Pzz component of the alignment tensor. 862 @rtype: float 863 """ 864 865 # Calculate and return the Pzz value. 866 return 1.0 - Pxx - Pyy
867 868
869 -def calc_R(Aa, Ar):
870 """Calculate the rhombicity parameter R. 871 872 This is given by:: 873 874 R = Ar / Aa. 875 876 877 @param Aa: The Aa parameter. 878 @type Aa: float 879 @param Ar: The Ar parameter. 880 @type Ar: float 881 @return: The R parameter. 882 @rtype: float 883 """ 884 885 # Zero Aa value, so return NaN. 886 if Aa == 0: 887 return nan 888 889 # Return R. 890 return Ar / Aa
891 892
893 -def calc_rotation(A):
894 """Calculate the rotation matrix from the molecular frame to the tensor frame. 895 896 This is defined by:: 897 898 | Azz | >= | Ayy | >= | Axx |. 899 900 901 @param A: The full alignment tensor. 902 @type A: numpy array ((3, 3), float64) 903 @return: The array of x, y, and z indices. 904 @rtype: list 905 """ 906 907 # The eigenvalues. 908 vals, rot = eig(A) 909 910 # Find the |x| < |y| < |z| indices. 911 abs_vals = abs(vals).tolist() 912 x_index = abs_vals.index(min(abs_vals)) 913 z_index = abs_vals.index(max(abs_vals)) 914 last_index = list(range(3)) 915 last_index.pop(max(x_index, z_index)) 916 last_index.pop(min(x_index, z_index)) 917 y_index = last_index[0] 918 919 # Empty rotation matrix for index permutations. 920 rot_perm = zeros((3, 3), float64) 921 922 # Permute the rotation matrix. 923 perm = [x_index, y_index, z_index] 924 for i in range(3): 925 for j in range(3): 926 rot_perm[i, j] = rot[i, perm[j]] 927 928 # Switch from the left handed to right handed universe if required. 929 if abs(det(rot_perm) - 1.0) > 1e-7: 930 rot_perm[:, 0] = -rot_perm[:, 0] 931 932 # Return the permuted rotation matrix. 933 return rot_perm
934 935
936 -def calc_unit_x(rotation):
937 """Calculate the x unit vector. 938 939 This is given by the eigenvalue decomposition. 940 941 942 @param rotation: The rotation matrix. 943 @type rotation: numpy 3D, rank-2 array 944 @return: The x unit vector. 945 @rtype: numpy array (float64) 946 """ 947 948 # Return the x unit vector. 949 return rotation[:, 0]
950 951
952 -def calc_unit_y(rotation):
953 """Calculate the y unit vector. 954 955 This is given by the eigenvalue decomposition. 956 957 958 @param rotation: The rotation matrix. 959 @type rotation: numpy 3D, rank-2 array 960 @return: The y unit vector. 961 @rtype: numpy array (float64) 962 """ 963 964 # Return the y unit vector. 965 return rotation[:, 1]
966 967
968 -def calc_unit_z(rotation):
969 """Calculate the z unit vector. 970 971 This is given by the eigenvalue decomposition. 972 973 974 @param rotation: The rotation matrix. 975 @type rotation: numpy 3D, rank-2 array 976 @return: The z unit vector. 977 @rtype: numpy array (float64) 978 """ 979 980 # Return the z unit vector. 981 return rotation[:, 2]
982 983
984 -def dependency_generator():
985 """Generator for the automatic updating the alignment tensor data structures. 986 987 @return: This generator successively yields three objects, the target object to update, the list of parameters which if modified cause the target to be updated, and the list of parameters that the target depends upon. 988 """ 989 990 # Primary objects (only dependant on the modifiable objects). 991 yield ('A', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Axx', 'Ayy', 'Azz', 'Axy', 'Axz', 'Ayz']) 992 yield ('A_5D', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Axx', 'Ayy', 'Azz', 'Axy', 'Axz', 'Ayz']) 993 yield ('Axxyy', ['Axx', 'Ayy'], ['Axx', 'Ayy']) 994 yield ('Azz', ['Axx', 'Ayy'], ['Axx', 'Ayy']) 995 996 yield ('P', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Axx', 'Ayy', 'Azz', 'Axy', 'Axz', 'Ayz']) 997 yield ('P_5D', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Axx', 'Ayy', 'Azz', 'Axy', 'Axz', 'Ayz']) 998 yield ('Pxx', ['Axx'], ['Axx']) 999 yield ('Pxxyy', ['Axx', 'Ayy'], ['Axx', 'Ayy']) 1000 yield ('Pxy', ['Axy'], ['Axy']) 1001 yield ('Pxz', ['Axz'], ['Axz']) 1002 yield ('Pyy', ['Ayy'], ['Ayy']) 1003 yield ('Pyz', ['Ayz'], ['Ayz']) 1004 1005 yield ('Sxx', ['Axx'], ['Axx']) 1006 yield ('Sxy', ['Axy'], ['Axy']) 1007 yield ('Sxz', ['Axz'], ['Axz']) 1008 yield ('Syy', ['Ayy'], ['Ayy']) 1009 yield ('Syz', ['Ayz'], ['Ayz']) 1010 1011 # Secondary objects (dependant on the primary objects). 1012 yield ('A_diag', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A']) 1013 yield ('eigvals', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A']) 1014 yield ('rotation', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A']) 1015 1016 yield ('P_diag', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['P']) 1017 yield ('Pzz', ['Axx', 'Ayy'], ['Pxx', 'Pyy']) 1018 1019 yield ('S', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Sxx', 'Syy', 'Szz', 'Sxy', 'Sxz', 'Syz']) 1020 yield ('S_5D', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Sxx', 'Syy', 'Szz', 'Sxy', 'Sxz', 'Syz']) 1021 yield ('S_diag', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['S']) 1022 yield ('Sxxyy', ['Axx', 'Ayy'], ['Sxx', 'Syy']) 1023 yield ('Szz', ['Axx', 'Ayy'], ['Sxx', 'Syy']) 1024 1025 yield ('Am2', ['Axx', 'Ayy', 'Axy'], ['Sxx', 'Syy', 'Sxy']) 1026 yield ('Am1', ['Axy', 'Ayz'], ['Sxz', 'Syz']) 1027 yield ('A0', ['Axx', 'Ayy'], ['Szz']) 1028 yield ('A1', ['Axy', 'Ayz'], ['Sxz', 'Syz']) 1029 yield ('A2', ['Axx', 'Ayy', 'Axy'], ['Sxx', 'Syy', 'Sxy']) 1030 1031 # Tertiary objects (dependant on the secondary objects). 1032 yield ('Aa', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A_diag']) 1033 yield ('Ar', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A_diag']) 1034 yield ('eta', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['A_diag']) 1035 1036 yield ('unit_x', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['rotation']) 1037 yield ('unit_y', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['rotation']) 1038 yield ('unit_z', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['rotation']) 1039 1040 yield ('euler', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['rotation']) 1041 1042 # Quaternary objects (dependant on the tertiary objects). 1043 yield ('R', ['Axx', 'Ayy', 'Axy', 'Axz', 'Ayz'], ['Aa', 'Ar'])
1044 1045 1046 1047 # Alignment tensor specific data. 1048 ################################# 1049
1050 -class AlignTensorList(list):
1051 """List type data container for holding all the alignment tensors. 1052 1053 The elements of the list should be AlignTensorData instances. 1054 """ 1055
1056 - def __repr__(self):
1057 """Replacement function for displaying an instance of this class.""" 1058 1059 text = "Alignment tensors.\n\n" 1060 text = text + "%-8s%-20s\n" % ("Index", "Name") 1061 for i in range(len(self)): 1062 text = text + "%-8i%-20s\n" % (i, self[i].name) 1063 text = text + "\nThese can be accessed by typing 'pipe.align_tensor[index]'.\n" 1064 return text
1065 1066
1067 - def add_item(self, name):
1068 """Append a new AlignTensorData instance to the list. 1069 1070 @param name: The tensor ID string. 1071 @type name: str 1072 @return: The tensor object. 1073 @rtype: AlignTensorData instance 1074 """ 1075 1076 # Create the instance. 1077 obj = AlignTensorData(name) 1078 1079 # Append the object. 1080 self.append(obj) 1081 1082 # Return the object. 1083 return obj
1084 1085
1086 - def from_xml(self, align_tensor_super_node, file_version=1):
1087 """Recreate the alignment tensor data structure from the XML alignment tensor node. 1088 1089 @param align_tensor_super_node: The alignment tensor XML nodes. 1090 @type align_tensor_super_node: xml.dom.minicompat.Element instance 1091 @keyword file_version: The relax XML version of the XML file. 1092 @type file_version: int 1093 """ 1094 1095 # Recreate all the alignment tensor data structures. 1096 xml_to_object(align_tensor_super_node, self, file_version=file_version, blacklist=['align_tensor']) 1097 1098 # Get the individual tensors. 1099 align_tensor_nodes = align_tensor_super_node.getElementsByTagName('align_tensor') 1100 1101 # Loop over the child nodes. 1102 for align_tensor_node in align_tensor_nodes: 1103 # Add the alignment tensor data container. 1104 self.add_item(align_tensor_node.getAttribute('name')) 1105 1106 # A temporary object to pack the structures from the XML data into. 1107 temp_obj = Element() 1108 1109 # Recreate all the other data structures (into the temporary object). 1110 xml_to_object(align_tensor_node, temp_obj, file_version=file_version) 1111 1112 # Loop over all modifiable objects in the temporary object and make soft copies of them. 1113 for name in self[-1]._mod_attr: 1114 # Skip if missing from the object. 1115 if not hasattr(temp_obj, name): 1116 continue 1117 1118 # The category. 1119 if search('_err$', name): 1120 category = 'err' 1121 param = name.replace('_err', '') 1122 elif search('_sim$', name): 1123 category = 'sim' 1124 param = name.replace('_sim', '') 1125 else: 1126 category = 'val' 1127 param = name 1128 1129 # Get the object. 1130 value = getattr(temp_obj, name) 1131 1132 # Normal parameters. 1133 if category == 'val': 1134 self[-1].set(param=param, value=value, category=category, update=False) 1135 1136 # Errors. 1137 elif category == 'err': 1138 self[-1].set(param=param, value=value, category=category, update=False) 1139 1140 # Simulation objects objects. 1141 else: 1142 # Set the simulation number if needed. 1143 if not hasattr(self[-1], '_sim_num') or self[-1]._sim_num == None: 1144 self[-1].set_sim_num(len(value)) 1145 1146 # Recreate the list elements. 1147 for i in range(len(value)): 1148 self[-1].set(param=param, value=value[i], category=category, sim_index=i, update=False) 1149 1150 # Update the data structures. 1151 for target, update_if_set, depends in dependency_generator(): 1152 self[-1]._update_object(param, target, update_if_set, depends, category) 1153 1154 # Delete the temporary object. 1155 del temp_obj
1156 1157
1158 - def names(self):
1159 """Return a list of the alignment tensor names.""" 1160 1161 # Loop over the tensors. 1162 names = [] 1163 for i in range(len(self)): 1164 names.append(self[i].name) 1165 1166 # Return the list. 1167 return names
1168 1169
1170 - def to_xml(self, doc, element):
1171 """Create an XML element for the alignment tensors. 1172 1173 @param doc: The XML document object. 1174 @type doc: xml.dom.minidom.Document instance 1175 @param element: The element to add the alignment tensors XML element to. 1176 @type element: XML element object 1177 """ 1178 1179 # Create the alignment tensors element and add it to the higher level element. 1180 tensor_list_element = doc.createElement('align_tensors') 1181 element.appendChild(tensor_list_element) 1182 1183 # Set the alignment tensor attributes. 1184 tensor_list_element.setAttribute('desc', 'Alignment tensor list') 1185 1186 # Add all simple python objects within the PipeContainer to the pipe element. 1187 fill_object_contents(doc, tensor_list_element, object=self, blacklist=list(self.__class__.__dict__.keys())+list(list.__dict__.keys())) 1188 1189 # Loop over the tensors. 1190 for i in range(len(self)): 1191 # Create an XML element for a single tensor. 1192 tensor_element = doc.createElement('align_tensor') 1193 tensor_list_element.appendChild(tensor_element) 1194 tensor_element.setAttribute('index', repr(i)) 1195 tensor_element.setAttribute('desc', 'Alignment tensor') 1196 1197 # The blacklist. 1198 blacklist = ['type', 'is_empty'] + list(self[i].__class__.__dict__.keys()) 1199 for name in dir(self): 1200 if name not in self[i]._mod_attr: 1201 blacklist.append(name) 1202 1203 # Add all simple python objects within the PipeContainer to the pipe element. 1204 fill_object_contents(doc, tensor_element, object=self[i], blacklist=blacklist)
1205 1206
1207 -class AlignTensorData(Element):
1208 """An empty data container for the alignment tensor elements.""" 1209 1210 # List of modifiable attributes. 1211 _mod_attr = [ 1212 'name', 1213 'Axx', 'Axx_sim', 'Axx_err', 1214 'Ayy', 'Ayy_sim', 'Ayy_err', 1215 'Axy', 'Axy_sim', 'Axy_err', 1216 'Axz', 'Axz_sim', 'Axz_err', 1217 'Ayz', 'Ayz_sim', 'Ayz_err', 1218 'align_id', 1219 'domain', 1220 'red', 1221 'fixed' 1222 ] 1223
1224 - def __init__(self, name, fixed=False):
1225 """Set up the tensor data. 1226 1227 @param name: The tensor ID string. 1228 @type name: str 1229 @keyword fixed: The optimisation flag. 1230 @type fixed: bool 1231 """ 1232 1233 # Store the values. 1234 self.__dict__['name'] = name 1235 self.__dict__['fixed'] = fixed 1236 1237 # The number of simulations. 1238 self.__dict__['_sim_num'] = None
1239 1240
1241 - def __setattr__(self, name, value):
1242 """Make this object read-only.""" 1243 1244 raise RelaxError("The alignment tensor is a read-only object. The alignment tensor set() method must be used instead.")
1245 1246
1247 - def _update_object(self, param_name, target, update_if_set, depends, category, sim_index=None):
1248 """Function for updating the target object, its error, and the MC simulations. 1249 1250 If the base name of the object is not within the 'update_if_set' list, this function returns 1251 without doing anything (to avoid wasting time). Dependant upon the category the object 1252 (target), its error (target+'_err'), or all Monte Carlo simulations (target+'_sim') are 1253 updated. 1254 1255 @param param_name: The parameter name which is being set in the __setattr__() function. 1256 @type param_name: str 1257 @param target: The name of the object to update. 1258 @type target: str 1259 @param update_if_set: If the parameter being set by the __setattr__() function is not within this list of parameters, don't waste time updating the target. 1260 @param depends: An array of names objects that the target is dependent upon. 1261 @type depends: array of str 1262 @param category: The category of the object to update (one of 'val', 'err', or 'sim'). 1263 @type category: str 1264 @keyword sim_index: The index for a Monte Carlo simulation for simulated parameter. 1265 @type sim_index: int or None 1266 @return: None 1267 """ 1268 1269 # Only update if the parameter name is within the 'update_if_set' list. 1270 if not param_name in update_if_set: 1271 return 1272 1273 # Get the function for calculating the value. 1274 fn = globals()['calc_'+target] 1275 1276 1277 # The value. 1278 ############ 1279 1280 if category == 'val': 1281 # Get all the dependencies if possible. 1282 missing_dep = 0 1283 deps = () 1284 for dep_name in depends: 1285 # Test if the object exists. 1286 if not hasattr(self, dep_name): 1287 missing_dep = 1 1288 break 1289 1290 # Get the object and place it into the 'deps' tuple. 1291 deps = deps+(getattr(self, dep_name),) 1292 1293 # Only update the object if its dependencies exist. 1294 if not missing_dep: 1295 # Calculate the value. 1296 value = fn(*deps) 1297 1298 # Set the attribute. 1299 self.__dict__[target] = value 1300 1301 1302 # The error. 1303 ############ 1304 1305 if category == 'err': 1306 # Get all the dependencies if possible. 1307 missing_dep = 0 1308 deps = () 1309 for dep_name in depends: 1310 # Test if the error object exists. 1311 if not hasattr(self, dep_name+'_err'): 1312 missing_dep = 1 1313 break 1314 1315 # Get the object and place it into the 'deps' tuple. 1316 deps = deps+(getattr(self, dep_name+'_err'),) 1317 1318 # Only update the error object if its dependencies exist. 1319 if not missing_dep: 1320 # Calculate the value. 1321 value = fn(*deps) 1322 1323 # Set the attribute. 1324 self.__dict__[target+'_err'] = value 1325 1326 1327 # The Monte Carlo simulations. 1328 ############################## 1329 1330 if category == 'sim': 1331 # The simulation indices. 1332 if sim_index != None: 1333 sim_indices = [sim_index] 1334 else: 1335 sim_indices = list(range(self._sim_num)) 1336 1337 # Get all the dependencies if possible. 1338 missing_dep = 0 1339 deps = [] 1340 for dep_name in depends: 1341 # Modify the dependency name. 1342 if dep_name != 'type': 1343 dep_name = dep_name+'_sim' 1344 1345 # Test if the MC sim object exists. 1346 if not hasattr(self, dep_name): 1347 missing_dep = 1 1348 break 1349 1350 # Get the object and place it into the 'deps' tuple. 1351 deps.append(getattr(self, dep_name)) 1352 1353 # Only create the MC simulation object if its dependencies exist. 1354 if not missing_dep: 1355 # Initialise an empty array to store the MC simulation object elements (if it doesn't already exist). 1356 if not target+'_sim' in self.__dict__: 1357 self.__dict__[target+'_sim'] = AlignTensorSimList(elements=self._sim_num) 1358 1359 # Repackage the deps structure. 1360 args = [] 1361 skip = False 1362 for i in sim_indices: 1363 args.append(()) 1364 1365 # Loop over the dependent structures. 1366 for j in range(len(deps)): 1367 # None, so skip. 1368 if deps[j] is None or deps[j][i] is None: 1369 skip = True 1370 1371 # String data type. 1372 if isinstance(deps[j], str): 1373 args[-1] = args[-1] + (deps[j],) 1374 1375 # List data type. 1376 else: 1377 args[-1] = args[-1] + (deps[j][i],) 1378 1379 # Loop over the sims and set the values. 1380 if not skip: 1381 for i in sim_indices: 1382 # Calculate the value. 1383 value = fn(*args[sim_indices.index(i)]) 1384 1385 # Set the attribute. 1386 self.__dict__[target+'_sim']._set(value=value, sim_index=i)
1387 1388
1389 - def set(self, param=None, value=None, category='val', sim_index=None, update=True):
1390 """Set a alignment tensor parameter. 1391 1392 @keyword param: The name of the parameter to set. 1393 @type param: str 1394 @keyword value: The parameter value. 1395 @type value: anything 1396 @keyword category: The type of parameter to set. This can be 'val' for the normal parameter, 'err' for the parameter error, or 'sim' for Monte Carlo or other simulated parameters. 1397 @type category: str 1398 @keyword sim_index: The index for a Monte Carlo simulation for simulated parameter. 1399 @type sim_index: int or None 1400 @keyword update: A flag which if True will cause all the alignment tensor objects to be updated correctly. This can be turned off for speed, as long as the _update_object() method is called prior to using the tensor. 1401 @type update: bool 1402 """ 1403 1404 # Check the type. 1405 if category not in ['val', 'err', 'sim']: 1406 raise RelaxError("The category of the parameter '%s' is incorrectly set to %s - it must be one of 'val', 'err' or 'sim'." % (param, category)) 1407 1408 # Test if the attribute that is trying to be set is modifiable. 1409 if not param in self._mod_attr: 1410 raise RelaxError("The object '%s' is not modifiable." % param) 1411 1412 # Set a parameter value. 1413 if category == 'val': 1414 self.__dict__[param] = value 1415 1416 # Set an error. 1417 elif category == 'err': 1418 self.__dict__[param+'_err'] = value 1419 1420 # Set a simulation value. 1421 else: 1422 # Check that the simulation number has been set. 1423 if self._sim_num == None: 1424 raise RelaxError("The alignment tensor simulation number has not yet been specified, therefore a simulation value cannot be set.") 1425 1426 # The simulation parameter name. 1427 sim_param = param+'_sim' 1428 1429 # No object, so create it. 1430 if not hasattr(self, sim_param): 1431 self.__dict__[sim_param] = AlignTensorSimList(elements=self._sim_num) 1432 1433 # The object. 1434 obj = getattr(self, sim_param) 1435 1436 # Set the value. 1437 obj._set(value=value, sim_index=sim_index) 1438 1439 # Skip the updating process for certain objects. 1440 if param in ['type']: 1441 return 1442 1443 # Update the data structures. 1444 if update: 1445 for target, update_if_set, depends in dependency_generator(): 1446 self._update_object(param, target, update_if_set, depends, category, sim_index=sim_index)
1447 1448
1449 - def set_fixed(self, flag):
1450 """Set if the alignment tensor should be fixed during optimisation or not. 1451 1452 @param flag: The fixed flag. 1453 @type flag: bool 1454 """ 1455 1456 self.__dict__['fixed'] = flag
1457 1458
1459 - def set_sim_num(self, sim_number=None):
1460 """Set the number of Monte Carlo simulations for the construction of the simulation structures. 1461 1462 @keyword sim_number: The number of Monte Carlo simulations. 1463 @type sim_number: int 1464 """ 1465 1466 # Store the value. 1467 self.__dict__['_sim_num'] = sim_number
1468 1469 1470
1471 -class AlignTensorSimList(list):
1472 """Empty data container for Monte Carlo simulation alignment tensor data.""" 1473
1474 - def __init__(self, elements=None):
1475 """Initialise the Monte Carlo simulation parameter list. 1476 1477 @keyword elements: The number of elements to initialise the length of the list to. 1478 @type elements: None or int 1479 """ 1480 1481 # Initialise a length. 1482 for i in range(elements): 1483 self._append(None)
1484 1485
1486 - def __setitem__(self, slice_obj, value):
1487 """This is a read-only object!""" 1488 1489 raise RelaxError("The alignment tensor is a read-only object. The alignment tensor set() method must be used instead.")
1490 1491
1492 - def _append(self, value):
1493 """The secret append method. 1494 1495 @param value: The value to append to the list. 1496 @type value: anything 1497 """ 1498 1499 # Execute the base class method. 1500 super(AlignTensorSimList, self).append(value)
1501 1502
1503 - def _set(self, value=None, sim_index=None):
1504 """Replacement secret method for __setitem__(). 1505 1506 @keyword value: The value to set. 1507 @type value: anything 1508 @keyword sim_index: The index of the simulation value to set. 1509 @type sim_index: int 1510 """ 1511 1512 # Execute the base class method. 1513 super(AlignTensorSimList, self).__setitem__(sim_index, value)
1514