Working with vectors#

atompy provides the Vector and VectorArray classes.

On this page you’ll learn how to use them.

Initialization#

Initialize a single vector and get/set its components

>>> vec = ap.Vector(0, 2, 3)
>>> vec
Vector(0.0, 2.0, 3.0)
>>> vec.x
0.0
>>> vec.y
2.0
>>> vec.z
3.0
>>> vec.x = 1
>>> vec
Vector(1.0, 2.0, 3.0)
>>> for c in vec:
...     c
...
1.0
2.0
3.0

Initialize a collection of vectors:

>>> vecs = ap.VectorArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> vecs
VectorArray([[1., 2., 3.],
             [4., 5., 6.],
             [7., 8., 9.]])

Accessing a component returns all respective values:

>>> vecs.x
array([1., 4., 7.])
>>> vecs.y
array([2., 5., 8.])
>>> vecs.z
array([3., 6., 9.])

You can access one vector of the collection:

>>> vecs[0]
Vector[1.0, 2.0, 3.0]
>>> for vec in vecs:
...     vec
...
Vector[1.0, 2.0, 3.0]
Vector[4.0, 5.0, 6.0]
Vector[7.0, 8.0, 9.0]

You can re-assign components of a vector collection as well

>>> vecs.x = 10, 11, 12
>>> vecs.y = 0
>>> vecs.z = vecs.x
vecs
VectorArray([[10.  0. 10.]
             [11.  0. 11.]
             [12.  0. 12.]])

You can also reassign single vectors in the collection

>>> vecs[0] = vec
>>> vecs[1] = np.array([4, 5, 6])
>>> vecs[2] = 7, 8, 9
vecs
VectorArray([[1. 2. 3.]
             [4. 5. 6.]
             [7. 8. 9.]])

You can also access the underlying NumPy array. This can be helpful if you need to work more efficiently on the data.

>>> vecs.asarray()
array([[1., 2., 3.],
       [4., 5., 6.],
       [7., 8., 9.]])
>>> vecs.asarray()[1:, :2]
array([[4., 5.],
       [7., 8.]])
>>> vecs.asarray()[1:,:2] = 0, 1
vecs
VectorArray([[1. 2. 3.]
             [0. 1. 6.]
             [0. 1. 9.]])

Common vector operations#

Addition and Subtraction#

You can add and subtract two vectors:

>>> vec_a = ap.Vector(1, 2, 3)
>>> vec_a
Vector(1.0, 2.0, 3.0)
>>> vec_b = ap.Vector(3, 2, 1)
>>> vec_b
Vector(3.0, 2.0, 1.0)
>>> vec_a + vec_b
Vector(4.0, 4.0, 4.0)
>>> vec_a - vec_b
Vector(-2.0, 0.0, 2.0)

You can perform operations in place:

>>> vec_b += vec_a
>>> vec_b
Vector(4.0, 4.0, 4.0)

The same, of course, is possible for vector arrays. You can also mix single vectors and vector arrays:

>>> vec = ap.Vector(1, 2, 3)
>>> vecs = ap.VectorArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> vec + vecs
VectorArray([[ 2.  4.  6.]
             [ 5.  7.  9.]
             [ 8. 10. 12.]])

You can also perform calculations in place. Note that adding a VectorArray to a Vector in place converts it to VectorArray:

>>> vecs += vec
vecs
VectorArray([[ 2.  4.  6.]
             [ 5.  7.  9.]
             [ 8. 10. 12.]])
vec
Vector(1.0, 2.0, 3.0)
>>> vec += vecs
vec
VectorArray([[ 3.  6.  9.]
             [ 6.  9. 12.]
             [ 9. 12. 15.]])
vecs
VectorArray([[ 2.  4.  6.]
             [ 5.  7.  9.]
             [ 8. 10. 12.]])

The other operators are not implemented.

If you want to multiply a vector by a factor, use Vector.scale() (VectorArray.scale()).

If you want to perform the dot product with another vector, use Vector.dot() (VectorArray.dot()).

If you want to perform the outer (cross) product with another vector, use Vector.cross() (VectorArray.cross()).

Scaling a vector#

You can scale a vector using the Vector.scale() and VectorArray.scale() methods:

>>> vec = ap.Vector(1, 2, 3)
>>> vec.scale(10)
Vector(10.0, 20.0, 30.0)
>>> vecs = ap.VectorArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> vecs.scale(10)
VectorArray([[10. 20. 30.]
             [40. 50. 60.]
             [70. 80. 90.]])
>>> vecs.scale((1, 10, 100))
VectorArray([[  1.  20. 300.]
             [  4.  50. 600.]
             [  7.  80. 900.]])

By default, scaling returns a new copy of the vector. If you want to perform scaling in place, you can set the copy keyword to False:

>>> vecs
VectorArray([[1. 2. 3.]
             [4. 5. 6.]
             [7. 8. 9.]])
>>> vecs.scale(10)
VectorArray([[10. 20. 30.]
             [40. 50. 60.]
             [70. 80. 90.]])
>>> vecs
VectorArray([[1. 2. 3.]
             [4. 5. 6.]
             [7. 8. 9.]])
>>> vecs.scale(10, copy=False)
VectorArray([[10. 20. 30.]
             [40. 50. 60.]
             [70. 80. 90.]])
>>> vecs
VectorArray([[10. 20. 30.]
             [40. 50. 60.]
             [70. 80. 90.]])

Dot product#

You can calculate the dot product of two vectors using the Vector.dot() and VectorArray.dot() methods:

>>> vec_a = ap.Vector(1, 2, 3)
>>> vec_b = ap.Vector(3, 2, 1)
>>> vec_a.dot(vec_b)
10.0
>>> vecs_a = ap.VectorArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> vecs_b = ap.VectorArray([[7, 8, 9], [4, 5, 6], [1, 2, 3]])
>>> vecs_a.dot(vecs_b)
array([50., 77., 50.])

You can also mix Vector and VectorArray:

>>> vecs_a.dot(vec_a)
array([14., 32., 50.])
>>> vec_b.dot(vecs_b)
array([46., 28., 10.])

Cross product#

You can calculate the dot product of two vectors using the Vector.cross() and VectorArray.cross() methods:

>>> vec_a = ap.Vector(1, 0, 0)
>>> vec_b = ap.Vector(0, 1, 0)
>>> vec_a.cross(vec_b)
Vector(0.0, 0.0, 1.0)
>>> vecs_a = ap.VectorArray([[1, 0, 0], [0, 1, 0]])
>>> vecs_b = ap.VectorArray([[0, 1, 0], [0, 0, 1]])
>>> vecs_a.cross(vecs_b)
VectorArray([[0. 0. 1.]
             [1. 0. 0.]])

Analogously to the dot product, you can mix Vector and VectorArray:

>>> vec_a.cross(vecs_b)
VectorArray([[ 0.  0.  1.]
             [ 0. -1.  0.]])

Magnitude#

You can calculate the magnitude(s) using the Vector.mag() and VectorArray.mag() methods:

>>> vec = ap.Vector(1, 2, 3)
>>> vec.mag()
3.7416573867739413
>>> vecs = ap.VectorArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> vecs.mag()
array([ 3.74165739,  8.77496439, 13.92838828])

Normalizing a vector#

You can obtain a normalized vector using the Vector.norm() and VectorArray.norm() methods.

The normalization is performed by calculating the magiutude, then scaling the vector appropriately.

Angles#

The polar and azimuth angle are in reference to a spherical coordinate system.

\[\begin{split}x &= r\sin\theta\cos\phi\\ y &= r\sin\theta\sin\phi\\ z &= r\cos\theta\end{split}\]

Vector and VectorArray provide methods to calculate \(\theta\), \(\cos\theta\) and \(\phi\):

Furthermore, one can calculate the angle to another vector using Vector.angle_to() or VectorArray.angle_to().