**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
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 = fig.add_subplot(111, projection='3d') 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*