LALSimulation  5.4.0.1-ec27e42
quaternion_utils.py
Go to the documentation of this file.
1 import numpy as np
2 
3 #-----------------------------------------------------------------------------
4 def multiply_quats(q1, q2):
5  """q1, q2 must be [scalar, x, y, z] but those may be arrays or scalars"""
6  return np.array([
7  q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3],
8  q1[2]*q2[3] - q2[2]*q1[3] + q1[0]*q2[1] + q2[0]*q1[1],
9  q1[3]*q2[1] - q2[3]*q1[1] + q1[0]*q2[2] + q2[0]*q1[2],
10  q1[1]*q2[2] - q2[1]*q1[2] + q1[0]*q2[3] + q2[0]*q1[3]])
11 
12 #-----------------------------------------------------------------------------
13 def quat_inv(q):
14  """Returns QBar such that Q*QBar = 1"""
15  qConj = -q
16  qConj[0] = -qConj[0]
17  normSqr = multiply_quats(q, qConj)[0]
18  return qConj/normSqr
19 
20 #-----------------------------------------------------------------------------
21 def align_vec_quat(vec):
22  """Returns a unit quaternion that will align vec with the z-axis"""
23  alpha = np.arctan2(vec[1], vec[0])
24  beta = np.arccos(vec[2])
25  gamma = -alpha*vec[2]
26  cb = np.cos(0.5*beta)
27  sb = np.sin(0.5*beta)
28  return np.array([cb*np.cos(0.5*(alpha + gamma)),
29  sb*np.sin(0.5*(gamma - alpha)),
30  sb*np.cos(0.5*(gamma - alpha)),
31  cb*np.sin(0.5*(alpha + gamma))])
32 
33 #-----------------------------------------------------------------------------
34 def transform_time_dependent_vector(quat, vec, inverse=0):
35  """Given (for example) a minimal rotation frame quat, transforms
36  vec from the minimal rotation frame to the inertial frame.
37  With inverse=1, transforms from the inertial frame to the minimal
38  rotation frame."""
39  qInv = quat_inv(quat)
40  if inverse:
41  return transform_time_dependent_vector(qInv, vec, inverse=0)
42 
43  return multiply_quats(quat, multiply_quats(np.append(np.array([
44  np.zeros(len(vec[0]))]), vec, 0), qInv))[1:]
45 
46 
47 #-----------------------------------------------------------------------------
48 def rotate_in_plane(chi, phase):
49  """ Rotates a given vector, chi, by a clockwise angle, phase, about the
50  z-axis. Can be used for transforming spins from the coprecessing frame to
51  the coorbital frame"""
52  v = chi.T
53  sp = np.sin(phase)
54  cp = np.cos(phase)
55  res = 1.*v
56  res[0] = v[0]*cp + v[1]*sp
57  res[1] = v[1]*cp - v[0]*sp
58  return res.T
59 
60 #-----------------------------------------------------------------------------
61 def transform_vector_coorb_to_inertial(vec_coorb, orbPhase, quat_copr):
62  """Given a vector (of size 3) in coorbital frame, orbital phase in
63  coprecessing frame and a minimal rotation frame quat, transforms
64  the vector from the coorbital to the LAL inertial frame.
65  """
66 
67  # Transform to coprecessing frame
68  vec_copr = rotate_in_plane(vec_coorb, -orbPhase)
69 
70  # Transform to inertial frame (for the surrogate)
71  vec = transform_time_dependent_vector(np.array([quat_copr]).T,
72  np.array([vec_copr]).T).T[0]
73 
74  return np.array(vec)
def align_vec_quat(vec)
Returns a unit quaternion that will align vec with the z-axis.
def rotate_in_plane(chi, phase)
Rotates a given vector, chi, by a clockwise angle, phase, about the z-axis.
def transform_vector_coorb_to_inertial(vec_coorb, orbPhase, quat_copr)
Given a vector (of size 3) in coorbital frame, orbital phase in coprecessing frame and a minimal rota...
def transform_time_dependent_vector(quat, vec, inverse=0)
Given (for example) a minimal rotation frame quat, transforms vec from the minimal rotation frame to ...
def multiply_quats(q1, q2)
q1, q2 must be [scalar, x, y, z] but those may be arrays or scalars
def quat_inv(q)
Returns QBar such that Q*QBar = 1.