Author: bugman
Date: Tue Nov 18 11:54:21 2014
New Revision: 26611
URL: http://svn.gna.org/viewcvs/relax?rev=26611&view=rev
Log:
Implemented a new default basis set for the align_tensor.matrix_angles user
function.
This is uses standard definition of the inter-matrix angle using the Euclidean
inner product of the
two matrices divided by the product of the Frobenius norm of each matrix. As
this is a linear map,
it should produce the most correct definition of inter-tensor angles.
Modified:
trunk/pipe_control/align_tensor.py
trunk/user_functions/align_tensor.py
Modified: trunk/pipe_control/align_tensor.py
URL:
http://svn.gna.org/viewcvs/relax/trunk/pipe_control/align_tensor.py?rev=26611&r1=26610&r2=26611&view=diff
==============================================================================
--- trunk/pipe_control/align_tensor.py (original)
+++ trunk/pipe_control/align_tensor.py Tue Nov 18 11:54:21 2014
@@ -24,8 +24,8 @@
# Python module imports.
from copy import deepcopy
-from math import pi, sqrt
-from numpy import arccos, dot, float64, linalg, zeros
+from math import acos, pi, sqrt
+from numpy import arccos, dot, float64, inner, linalg, zeros
from numpy.linalg import norm
import sys
from warnings import warn
@@ -907,7 +907,8 @@
tensor_num = tensor_num + 1
# Create the matrix which contains the 5D vectors.
- matrix = zeros((tensor_num, 5), float64)
+ matrix_3D = zeros((tensor_num, 3, 3), float64)
+ matrix_5D = zeros((tensor_num, 5), float64)
# Loop over the tensors.
i = 0
@@ -919,24 +920,29 @@
# Unitary basis set.
if basis_set == 0:
# Pack the elements.
- matrix[i, 0] = tensor.Sxx
- matrix[i, 1] = tensor.Syy
- matrix[i, 2] = tensor.Sxy
- matrix[i, 3] = tensor.Sxz
- matrix[i, 4] = tensor.Syz
+ matrix_5D[i, 0] = tensor.Sxx
+ matrix_5D[i, 1] = tensor.Syy
+ matrix_5D[i, 2] = tensor.Sxy
+ matrix_5D[i, 3] = tensor.Sxz
+ matrix_5D[i, 4] = tensor.Syz
# Geometric basis set.
elif basis_set == 1:
# Pack the elements.
- matrix[i, 0] = tensor.Szz
- matrix[i, 1] = tensor.Sxxyy
- matrix[i, 2] = tensor.Sxy
- matrix[i, 3] = tensor.Sxz
- matrix[i, 4] = tensor.Syz
+ matrix_5D[i, 0] = tensor.Szz
+ matrix_5D[i, 1] = tensor.Sxxyy
+ matrix_5D[i, 2] = tensor.Sxy
+ matrix_5D[i, 3] = tensor.Sxz
+ matrix_5D[i, 4] = tensor.Syz
+
+ # Full matrix.
+ elif basis_set == 2:
+ matrix_3D[i] = tensor.A
# Normalisation.
- norm = linalg.norm(matrix[i])
- matrix[i] = matrix[i] / norm
+ if basis_set in [0, 1]:
+ norm_5D = linalg.norm(matrix_5D[i])
+ matrix_5D[i] = matrix_5D[i] / norm_5D
# Increment the index.
i = i + 1
@@ -945,12 +951,15 @@
cdp.align_tensors.angles = zeros((tensor_num, tensor_num), float64)
# Header printout.
- sys.stdout.write("\nData pipe: " + repr(pipes.cdp_name()) + "\n")
- sys.stdout.write("\n5D angles in deg between the vectors ")
if basis_set == 0:
+ sys.stdout.write("5d angles in deg between the vectors ")
sys.stdout.write("{Sxx, Syy, Sxy, Sxz, Syz}")
elif basis_set == 1:
+ sys.stdout.write("5d angles in deg between the vectors ")
sys.stdout.write("{Szz, Sxx-yy, Sxy, Sxz, Syz}")
+ elif basis_set == 2:
+ sys.stdout.write("Angles in deg between the matrices ")
+ sys.stdout.write("(using the Euclidean inner product and Frobenius
norm)")
sys.stdout.write(":\n")
# Initialise the table of data.
@@ -974,15 +983,35 @@
# Second loop over the columns.
for j in range(tensor_num):
- # Dot product.
- delta = dot(matrix[i], matrix[j])
-
- # Check.
- if delta > 1:
- delta = 1
-
- # The angle (in rad).
- cdp.align_tensors.angles[i, j] = arccos(delta)
+ # The 5D angles.
+ if basis_set in [0, 1]:
+ # Dot product.
+ delta = dot(matrix_5D[i], matrix_5D[j])
+
+ # Check.
+ if delta > 1:
+ delta = 1
+
+ # The angle.
+ theta = arccos(delta)
+
+ # The full matrix angle.
+ elif basis_set in [2]:
+ # The Euclidean inner product.
+ nom = inner(matrix_3D[i].flatten(), matrix_3D[j].flatten())
+
+ # The Frobenius norms.
+ denom = norm(matrix_3D[i]) * norm(matrix_3D[j])
+
+ # The angle.
+ ratio = nom / denom
+ if ratio <= 1.0:
+ theta = arccos(nom / denom)
+ else:
+ theta = 0.0
+
+ # Store the angle (in rad).
+ cdp.align_tensors.angles[i, j] = theta
# Add to the table as degrees.
table[i+1].append("%8.1f" % (cdp.align_tensors.angles[i,
j]*180.0/pi))
Modified: trunk/user_functions/align_tensor.py
URL:
http://svn.gna.org/viewcvs/relax/trunk/user_functions/align_tensor.py?rev=26611&r1=26610&r2=26611&view=diff
==============================================================================
--- trunk/user_functions/align_tensor.py (original)
+++ trunk/user_functions/align_tensor.py Tue Nov 18 11:54:21 2014
@@ -297,18 +297,18 @@
# The align_tensor.matrix_angles user function.
uf = uf_info.add_uf('align_tensor.matrix_angles')
-uf.title = "Calculate the 5D angles between all alignment tensors."
+uf.title = "Calculate the angles between all alignment tensors."
uf.title_short = "Alignment tensor angle calculation."
uf.display = True
uf.add_keyarg(
name = "basis_set",
- default = 0,
+ default = 2,
py_type = "int",
desc_short = "basis set",
desc = "The basis set to operate with.",
wiz_element_type = "combo",
- wiz_combo_choices = ["{Sxx, Syy, Sxy, Sxz, Syz}", "{Szz, Sxxyy, Sxy, Sxz,
Syz}"],
- wiz_combo_data = [0, 1]
+ wiz_combo_choices = ["{Sxx, Syy, Sxy, Sxz, Syz}", "{Szz, Sxxyy, Sxy, Sxz,
Syz}", "Full matrix angles using the Euclidean inner product"],
+ wiz_combo_data = [0, 1, 2]
)
uf.add_keyarg(
name = "tensors",
@@ -322,11 +322,23 @@
)
# Description.
uf.desc.append(Desc_container())
-uf.desc[-1].add_paragraph("This will calculate the angles between all loaded
alignment tensors for the current data pipe. The matrices are first converted
to a 5D vector form and then then angles are calculated. The angles are
dependent on the basis set. If the basis set is set to the default of 0, the
vectors {Sxx, Syy, Sxy, Sxz, Syz} are used. If the basis set is set to 1, the
vectors {Szz, Sxxyy, Sxy, Sxz, Syz} are used instead.")
+uf.desc[-1].add_paragraph("This will calculate the angles between all loaded
alignment tensors for the current data pipe. Depending upon the basis set, the
matrices are first converted to a 5D vector form and then then angles are
calculated. The angles are dependent upon the basis set:")
+uf.desc[-1].add_item_list_element("0", "The basis set {Sxx, Syy, Sxy, Sxz,
Syz},")
+uf.desc[-1].add_item_list_element("1", "The basis set {Szz, Sxxyy, Sxy, Sxz,
Syz} of the Pales standard notation,")
+uf.desc[-1].add_item_list_element("2", "The full matrix angle via the
Euclidean inner product of the alignment matrices together with the Frobenius
norm ||A||_F.")
+uf.desc[-1].add_paragraph("The full matrix angle via the Euclidean inner
product is defined as:")
+uf.desc[-1].add_verbatim("""
+ / <A1 , A2> \
+ theta = arccos | ------------- | ,
+ \ ||A1|| ||A2|| /
+""")
+uf.desc[-1].add_paragraph("where <a,b> is the Euclidean inner product and
||a|| is the Frobenius norm of the matrix.")
+uf.desc[-1].add_paragraph("Note that the inner product solution is a linear
map which hence preserves angles, whereas the {Sxx, Syy, Sxy, Sxz, Syz} and
{Szz, Sxxyy, Sxy, Sxz, Syz} basis sets are non-linear maps which do not
preserve angles. Therefore the angles from all three basis sets will be
different.")
uf.backend = align_tensor.matrix_angles
uf.menu_text = "&matrix_angles"
uf.gui_icon = "oxygen.categories.applications-education"
-uf.wizard_size = (800, 600)
+uf.wizard_height_desc = 500
+uf.wizard_size = (1000, 700)
uf.wizard_image = WIZARD_IMAGE_PATH + 'align_tensor.png'
_______________________________________________
relax (http://www.nmr-relax.com)
This is the relax-commits mailing list
[email protected]
To unsubscribe from this list, get a password
reminder, or change your subscription options,
visit the list information page at
https://mail.gna.org/listinfo/relax-commits