soprano.nmr.utils#

Utility functions for NMR-related properties

soprano.nmr.utils._J_constant(Kij, gi, gj)[source]#

J coupling constants for pairs ij, with reduced constant Kij and gyromagnetic ratios gi and gj

soprano.nmr.utils._anisotropy(haeb_evals, reduced=False)[source]#

Calculate anisotropy given eigenvalues sorted with Haeberlen convention

soprano.nmr.utils._asymmetry(haeb_evals)[source]#

Calculate asymmetry

soprano.nmr.utils._dip_constant(Rij, gi, gj)[source]#

Dipolar constants for pairs ij, with distances Rij and gyromagnetic ratios gi and gj

soprano.nmr.utils._dip_tensor(d, r, rotation_axis=None)[source]#

Full dipolar tensor given a constant and a connecting vector

soprano.nmr.utils._equivalent_euler(euler_angles, passive=False)[source]#

Find the equivalent Euler angles for a given set of Euler angles.

This set should be correct for NMR tensors, according to TensorView for MATLAB: [6]

Parameters:
  • euler_angles (ndarray)

  • passive (bool)

soprano.nmr.utils._equivalent_relative_euler(euler_angles, passive=False)[source]#

Returns a list of 16 equivalent relative Euler angles for a given set of Euler angles that corresponds to the relative orientation of two NMR tensors. See TensorView for MATLAB: [6]

Parameters:
  • euler_angles (ndarray)

  • passive (bool)

Return type:

ndarray

soprano.nmr.utils._evals_sort(evals, convention='c', return_indices=False)[source]#

Sort a list of eigenvalue triplets by varios conventions

Return type:

ndarray | Tuple[ndarray, ndarray]

soprano.nmr.utils._evecs_2_quat(evecs)[source]#

Convert a set of eigenvectors to a Quaternion expressing the rotation of the tensor’s PAS with respect to the Cartesian axes

soprano.nmr.utils._handle_euler_edge_cases(euler_angles, eigenvalues, original_tensor, convention='zyz', passive=False, eps=1e-06)[source]#

Handle edge cases in the Euler angle conventions for degenerate tensors.

Parameters:
  • euler_angles (np.ndarray) – Euler angles in radians

  • eigenvalues (np.ndarray) – Eigenvalues of the tensor

  • original_tensor (np.ndarray) – Original symmetric tensor

  • convention (str, optional) – Euler angle convention. Defaults to “zyz”.

  • eps (float, optional) – Tolerance for degeneracy. Defaults to 1e-6.

  • passive (bool)

soprano.nmr.utils._matrix_to_euler(R, convention='zyz', passive=False)[source]#

Convert a rotation matrix to Euler angles (in radians)

We use the scipy Rotation class to do this, but we need to make sure that the angles are in the conventional ranges for NMR. This function does that.

Note that SciPy uses the convention that upper case letters are extrinsic rotations and lower case letters are intrinsic rotations (note this distinction is not that same as active vs passive. We enforce extrinsic rotations here by converting all to upper case.

We use an explicit keyword argument to specify passive rotations, and transpose the rotation matrix if necessary.

Parameters:
  • R (Union[List[List[float]], np.ndarray]) – Rotation matrix. Note that SciPy will convert this to a proper rotation matrix if it is not already one. (i.e. det(R) = 1)

  • convention (str, optional) – Euler angle convention. Defaults to “zyz”. This will be converted to upper case to enforce extrinsic rotations.

  • passive (bool, optional) – Whether the angles are passive rotations. Defaults to False.

Returns:

Euler angles in radians

Return type:

np.ndarray

soprano.nmr.utils._normalise_euler_angles(euler_angles, passive=False, eps=1e-06)[source]#

Normalise Euler angles to standard ranges for NMR as defined in: TensorView for MATLAB [6]

Parameters:
  • euler_angles (np.ndarray) – Euler angles in radians

  • passive (bool, optional) – Whether the angles are passive rotations. Defaults to False.

  • eps (float, optional) – Tolerance for degeneracy. Defaults to 1e-6.

Return type:

ndarray

soprano.nmr.utils._skew(evals)[source]#

Calculate skew

\[\kappa = 3 (\sigma_{iso} - \sigma_{22}) / \Omega\]

where \(\Omega\) is the span of the tensor.

Note that for chemical shift tensors (\(\delta\)), the sign is reversed.

soprano.nmr.utils._span(evals)[source]#

Calculate span

\[\Omega = \sigma_{33} - \sigma_{11}\]

where \(\sigma_{33}\) is the largest, and \(\sigma_{11}\) is the smallest eigenvalue.

soprano.nmr.utils._split_species(species)[source]#

Validate the species string and extract the isotope number and element.

Parameters:

species (str) – The species string to validate. e.g. ‘13C’ or ‘1H’.

Returns:

A tuple containing the isotope number (int), and element symbol (str, such as ‘C’ or ‘H’).

Return type:

tuple

soprano.nmr.utils._test_euler_rotation(euler_angles, eigenvalues, eigenvecs, convention='zyz', passive=False, eps=1e-06)[source]#

Test that the Euler angles correctly rotate the tensor.

We compare the tensor rotated by the Euler angles to that you get by rotating the tensor with the rotation matrix corresponding to the Euler angles. i.e.

PAS = np.diag(eigenvalues) R = Rotation.from_euler(convention, euler_angles).as_matrix() A_rot = np.dot(R, np.dot(PAS, R.T))

B_rot = np.dot(eigenvecs, np.dot(PAS, eigenvecs.T))

Parameters:
  • euler_angles (np.ndarray) – Euler angles in radians

  • eigenvalues (np.ndarray) – Eigenvalues of the tensor

  • eigenvecs (np.ndarray) – Eigenvectors of the tensor

  • convention (str, optional) – Euler angle convention. Defaults to “zyz”.

  • passive (bool, optional) – Whether the angles are passive rotations. Defaults to False.

  • eps (float, optional) – Tolerance for degeneracy. Defaults to 1e-6.

Returns:

True if the Euler angles correctly rotate the tensor. False otherwise.

Return type:

bool

soprano.nmr.utils._tryallanglestest(euler_angles, pas1, pasv2, arel1, convention, eps=0.001)[source]#

For relative Euler angles from tensor A to B, if B is axially symmetric, we need to try all equivalent Euler angles of the symmetric tensor to find the conventional one.

Go through the 4 equivalent passive angles since we’re using the trick of calculating the A relative angles in the frame of B by calculating the B relative angles in the frame of A with the passive convention.

Credit: function adapted from TensorView for MATLAB: [6]

Parameters:
  • euler_angles (ndarray)

  • pas1 (ndarray)

  • pasv2 (ndarray)

  • arel1 (ndarray)

  • convention (str)

  • eps (float)

Return type:

ndarray