# Rotation3D

Initial motivation. This class of object is created with the motivation of rotating object quickly to the z-axis. This is reflected by the function rotate_towards_z_axis() and rotate_all_towards_z_axis(). It is important to note that rotating an object to the z-axis can be performed in a number of ways. In this example, rotation is done first against the azimuth angle, then against the polar angle. Many variations exist, including how we might need to rotate all points against centre of mass rather than mean position etc.

```kero.werithmetic.rotation.py

class Rotation3D:
def __init__(self):
self.x_set
self.y_set
self.z_set
self.xrot_set
self.yrot_set
self.zrot_set
self.x0
self.y0
self.z0
def get_spherical_coords(self, x, y, z, smallxy=True, precisionxy=1e-15)
# see example 1
return r, phi, theta
def rotate_towards_z_axis(self, state, current_phi, current_theta):
# see example 2
return out
def rotate_all_towards_z_axis(self):
# see example 3
return

# extrinsic rotations
def rotate_wrt_x(self, state, angle):
return out
def rotate_wrt_y(self, state, angle):
return out
def rotate_wrt_z(self, state, angle):
return out```

 Properties Description x_set, y_set, z_set List of x, y and z position of all particles before rotation, in Cartesian Coordinates. xrot_set, yrot_set, zrot_set List of x, y and z position of all particles after rotation, in Cartesian Coordinates. x0, y0, z0 mean positions of all particles, in Cartesian Coordinates.

Example 1: get_spherical_coords()

 x, y, z Double. Position in Cartesian Coordinates. smallxy Boolean. If true, then the function checks if x and y are both below the value precisionxy. If so, then azimuth angle is set to zero immediately.   This is set to true if we anticipate singularity or some precision issue. If such situation arises, be extra careful or consider different approach. precisionxy Double. Set this to a very small number, and it is defaulted to 1e-15. return r, phi, theta Double. Position in spherical coordinates.
```import kero.werithmetic.rotation as rot

x, y, z = 0.1, 0.1, 10
ro = rot.Rotation3D()
r, phi, theta = ro.get_spherical_coords(x, y, z)
print("r, phi, theta =", r, phi, theta)```

The output is the following, where r is in the same unit as x, y and z, while phi (polar angle), theta (azimuthal angle) are in radian.

`r, phi, theta = 10.000999950005 0.7853981633974483 0.014141192927807654`

Example 2: rotate_towards_z_axis()

 state Numpy matrix, 3 by 1. This is to represent an initial 3D position vector that we want to rotate through, first, azimuth angle, specified by the negative of current_phi, and second, polar angle, specified by the negative of current_theta. current_phi Double. Current azimuth angle of the vector. current_theta Double. Current polar angle of the vector. return out Numpy matrix, 3 by 1. This is the rotated vector, see the description of state.
```import kero.werithmetic.rotation as rot
import numpy as np

ro = rot.Rotation3D()
x, y, z = -0.1, 0.54, 2
state = np.matrix([[x], [y], [z]])
r, phi, theta = ro.get_spherical_coords(x, y, z)
print("BEFORE: r, phi, theta =", r, phi, theta)
current_phi = phi
current_theta = theta
state_after = ro.rotate_towards_z_axis(state, current_phi, current_theta)
# print(state_after)
x1 = state_after.item(0)
y1 = state_after.item(1)
z1 = state_after.item(2)
print("x,y,z = ",x,y,z)
r1, phi1, theta1 = ro.get_spherical_coords(x1, y1, z1)
print("AFTER: r, phi, theta =", r1, phi1, theta1)
print("x,y,z = ",x1, y1, z1)```

The output is the following.

```BEFORE: r, phi, theta = 2.0740298937093455 -1.3876855095324125 0.2679855592098951
x,y,z = -0.1 0.54 2
AFTER: r, phi, theta = 2.074029893709346 0.0 0.5359711184197905
x,y,z = -1.0591577496072508 -2.7755575615628914e-17 1.7831951271374942```

Example 3 is like this example applied to many particles, but the rotation is done through the angles of the mean position of the particles.

Example 3: rotate_all_towards_z_axis()

This function is to be used after x_set, y_set and z_set properties of the object Rotation3D have been set. The function does not take in any arguments. Neither does it returns values. Instead, it sets xrot_set, yrot_set and zrot_set properties of the object, which are the rotated positions.

In this example, we show a number of particles are rotated via rotate_all_towards_z_axis(). This example generates 100 particles whose positions are initiated to x_set, y_set and z_set properties of the object Rotation3D. and compute their mean position. The polar and azimuth angles of the mean position are computed. And then, finally, each particle is first rotated through the negative of the azimuth angle of mean position w.r.t z axis, and then through negative of the polar angle of mean position w.r.t y axis.

```import kero.werithmetic.rotation as rot
import numpy as np

ro = rot.Rotation3D()
no_of_particles = 100
ro.x_set = np.random.normal(loc=1, scale=0.05, size=no_of_particles)
ro.y_set = np.random.normal(loc=1, scale=0.05, size=no_of_particles)
ro.z_set = np.random.normal(loc=1, scale=0.5, size=no_of_particles)
ro.rotate_all_towards_z_axis()
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
print(ro.xrot_set)
print(ro.yrot_set)
print(ro.zrot_set)
fig = plt.figure()
fig.patch.set_facecolor('white')
ax.scatter(ro.x_set, ro.y_set, ro.z_set)
ax.scatter(ro.xrot_set, ro.yrot_set, ro.zrot_set, c='r')
ax.scatter(np.linspace(-2 ,2 ,100), np.zeros(100) , np.zeros(100), c='k', s=1)
ax.scatter( np.zeros(100), np.linspace(-2, 2, 100) ,np.zeros(100), c='k', s=1)
ax.scatter(np.zeros(100), np.zeros(100) ,np.linspace(-2, 2, 100),  c='k', s=1)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
# plt.xlim([-2,2])
# plt.ylim([-2, 2])
ax.set_xlim([-2 ,2])
ax.set_ylim([-2, 2])
ax.set_zlim([-2, 2])
plt.show()```

The example rotation is shown in the left figure, while the right figure shows the two steps done to achieve the said rotation. Example 4: extrinsic rotations

The functions rotate_wrt_x( self, state, angle ),  rotate_wrt_y( self, state, angle ) , rotate_wrt_y( self, state, angle ) perform extrinsic rotations.

Given an initial XYZ coordinates, points or vectors wrt XYZ. For extrinsic rotation, we have an absolute xyz coordinates that initially coincides with XYZ and we always rotate with respect to x/y/z axis of xyz. The coordinates xyz themselves remain unchanged. Note that in this description, points or vectors are constant wrt XYZ, but rotated wrt xyz.

 state Numpy matrix, 3 by 1. Initial 3D position vector. angle Double, the angle of rotation with respect to the absolute x/y/z axis out Numpy matrix, 3 by 1. Final 3D position vector.

In this example, we show one single point (yellow arrow) rotate through almost 360 degrees or 2*pi radians wrt x (blue), y (green) and z (red) axes respectively. kero version: 0.3 and above