from .basefuncs import *
[docs]class Coords:
"""Class grouping methods to project basis vectors on other bases.
"""
def __init__(self):
pass
[docs] @classmethod
def cylindrical_basis_vects_in_cart_basis(cls, phi_angles):
"""Projects cylindrical basis vectors on cartesian basis.
Parameters
----------
phi_angles : array_like
(N,) cylindrical phi angles.
Returns
-------
(ndarray, ndarray, ndarray)
(3,N), (3,N), (3,N) ercyl, ephi and ez in cartesian basis.
"""
ercyl = np.array([np.cos(phi_angles), np.sin(phi_angles), np.zeros_like(phi_angles)])
ephi = np.array([-np.sin(phi_angles), np.cos(phi_angles), np.zeros_like(phi_angles)])
ez = np.array([np.zeros_like(phi_angles), np.zeros_like(phi_angles), np.ones_like(phi_angles)])
return ercyl, ephi, ez
[docs] @classmethod
def cartesian_basis_vects_in_cyl_basis(cls, phi_angles):
"""Projects cartesian basis vectors on cylindrical basis.
Parameters
----------
phi_angles : array_like
cylindrical phi angle.
Returns
-------
(ndarray, ndarray, ndarray)
(3,N), (3,N), (3,N) ex, ey and ez in cylindrical basis.
"""
ex = np.array([np.cos(phi_angles), -np.sin(phi_angles), np.zeros_like(phi_angles)])
ey = np.array([np.sin(phi_angles), np.cos(phi_angles), np.zeros_like(phi_angles)])
ez = np.array([np.zeros_like(phi_angles), np.zeros_like(phi_angles), np.ones_like(phi_angles)])
return ex, ey, ez
[docs] @classmethod
def spherical_basis_vects_in_cart_basis(cls, theta_angles, phi_angles):
"""Projects spherical basis vectors on cartesian basis.
Parameters
----------
theta_angles : array_like
spherical theta angle
phi_angles : array_like
cylindrical phi angle.
Returns
-------
(ndarray, ndarray, ndarray)
(3,N), (3,N), (3,N) erspher, ethetaspher and ephi in cartesian basis.
"""
erspher = np.array([np.sin(theta_angles) * np.cos(phi_angles), np.sin(theta_angles) * np.sin(phi_angles),
np.cos(theta_angles)])
ethetaspher = np.array([np.cos(theta_angles) * np.cos(phi_angles), np.cos(theta_angles) * np.sin(phi_angles),
-np.sin(theta_angles)])
ephi = np.array([-np.sin(phi_angles), np.cos(phi_angles), np.zeros_like(phi_angles)])
return erspher, ethetaspher, ephi
[docs] @classmethod
def cartesian_basis_vects_in_spher_basis(cls, theta_angles, phi_angles):
"""Projects cartesian basis vectors on spherical basis.
Parameters
----------
theta_angles : array_like
spherical theta angle
phi_angles : array_like
cylindrical phi angle.
Returns
-------
(ndarray, ndarray, ndarray)
(3,N), (3,N), (3,N) ex, ey and ez in spherical basis.
"""
ex = np.array(
[np.cos(phi_angles) * np.sin(theta_angles), np.cos(phi_angles) * np.cos(theta_angles), -np.sin(phi_angles)])
ey = np.array(
[np.sin(phi_angles) * np.sin(theta_angles), np.sin(phi_angles) * np.cos(theta_angles), np.cos(phi_angles)])
ez = np.array([np.cos(theta_angles), - np.sin(theta_angles), np.zeros_like(theta_angles)])
return ex, ey, ez
[docs] @classmethod
def spherical_basis_vects_in_cyl_basis(cls, theta_angles):
"""Projects spherical basis vectors on cylindrical basis.
Parameters
----------
theta_angles : array_like
spherical theta angle
Returns
-------
(ndarray, ndarray, ndarray)
(3,N), (3,N), (3,N) erspher, ethetaspher and ephi in cylindrical basis.
"""
erspher = np.array([np.sin(theta_angles), np.zeros_like(theta_angles), np.cos(theta_angles)])
ethetaspher = np.array([np.cos(theta_angles), np.zeros_like(theta_angles), -np.sin(theta_angles)])
ephi = np.array([np.zeros_like(theta_angles), np.ones_like(theta_angles), np.zeros_like(theta_angles)])
return erspher, ethetaspher, ephi
[docs] @classmethod
def cylindrical_basis_vects_in_spher_basis(cls, theta_angles):
"""Projects cylindrical basis vectors on spherical basis.
Parameters
----------
theta_angles : array_like
spherical theta angle
Returns
-------
(ndarray, ndarray, ndarray)
(3,N), (3,N), (3,N) ercyl, ephi and ez in spherical basis.
"""
ercyl = np.array([np.sin(theta_angles), np.cos(theta_angles), np.zeros_like(theta_angles)])
ephi = np.array([np.zeros_like(theta_angles), np.zeros_like(theta_angles), np.ones_like(theta_angles)])
ez = np.array([np.cos(theta_angles), - np.sin(theta_angles), np.zeros_like(theta_angles)])
return ercyl, ephi, ez
[docs]class SpatialCoordsFromCart:
"""Performs computations of cylindrical or spherical coordinates and bases from cartesian positions.
Parameters
----------
pos : ndarray
(N,3) Positions x, y and z.
ctre_pos: ndarray, optional
(3,) central position to be removed from all the particles positions, if desired (to compute cylindrical and
spherical coordinates with a different coordinates centre)
"""
def __init__(self, pos, ctre_pos=np.zeros((3))):
CheckArrays.check_poslike_array(pos)
self.pos = pos
self.pos -= ctre_pos
self.nb_parts = np.shape(self.pos)[0]
[docs] def average_pos_coords(self, weights):
"""Returns the (weighted) averaged x, y and z.
Parameters
----------
weights: ndarray, optional
(N,) weights (e.g. masses).
Returns
-------
(float, float, float)
(Weighted) average x, y and z.
"""
av_px = BaseTools.average64_1d(self.pos[:, 0], weights=weights)
av_py = BaseTools.average64_1d(self.pos[:, 1], weights=weights)
av_pz = BaseTools.average64_1d(self.pos[:, 2], weights=weights)
return av_px, av_py, av_pz
[docs] def disp_of_pos(self, weights):
"""Returns the (weighted) dispersions of x, y and z.
Parameters
----------
weights: ndarray, optional
(N,) weights (e.g. masses).
Returns
-------
(float, float, float)
(Weighted) dispersions of x, y and z.
"""
dispx = BaseTools.dispersion64_1d(self.pos[:, 0], weights=weights)
dispy = BaseTools.dispersion64_1d(self.pos[:, 1], weights=weights)
dispz = BaseTools.dispersion64_1d(self.pos[:, 2], weights=weights)
return dispx, dispy, dispz
[docs] def spherical_radius(self):
"""
Returns
-------
ndarray
(N,) Spherical radii.
"""
return np.sqrt(self.pos[:, 0] ** 2 + self.pos[:, 1] ** 2 + self.pos[:, 2] ** 2)
[docs] def spherical_theta(self):
"""
Returns
-------
ndarray
(N,) Theta angles of spherical coordinates.
"""
return np.arccos(self.pos[:, 2] / self.spherical_radius())
[docs] def phi(self):
"""
Returns
-------
ndarray
(N,) Phi angles of both cylindrical and spherical coordinates.
"""
return np.arctan2(self.pos[:, 1], self.pos[:, 0])
[docs] def cylindrical_radius(self):
"""
Returns
-------
ndarray
(N,) Cylindrical radii.
"""
return np.sqrt(self.pos[:, 0] ** 2 + self.pos[:, 1] ** 2)
[docs] def tocyl_pos(self):
"""
Returns
-------
ndarray
(N,3) Cylindrical coordinates array cylpos with cylpos[:,0] the cylindrical radii, cylpos[:,1] the phi
cylindrical coordinates and cylpos[:,2] the z ooordinates.
"""
cylpos = np.zeros_like(self.pos)
cylpos[:, 0] = self.cylindrical_radius()
cylpos[:, 1] = self.phi()
cylpos[:, 2] = self.pos[:, 2]
return cylpos
[docs] def tocyl_sp_object(self):
"""Returns :class:`~galaximview.coords.SpatialCoordsFromCyl` object.
Returns
-------
:class:`~galaximview.coords.SpatialCoordsFromCyl` object.
"""
cylpos = self.tocyl_pos()
return SpatialCoordsFromCyl(cylpos)
[docs] def tospher_pos(self):
"""
Returns
-------
ndarray
(N,3) Spherical coordinates array spherpos with spherpos[:,0] the spherical radii, spherpos[:,1] the theta
spherical angles and spherpos[:,2] the phi spherical angles.
"""
spherpos = np.zeros_like(self.pos)
spherpos[:, 0] = self.spherical_radius()
spherpos[:, 1] = self.spherical_theta()
spherpos[:, 2] = self.phi()
return spherpos
[docs] def tospher_sp_object(self):
"""Returns :class:`~galaximview.coords.SpatialCoordsFromSpher` object.
Returns
-------
:class:`~galaximview.coords.SpatialCoordsFromSpher` object.
"""
spherpos = self.tospher_pos()
return SpatialCoordsFromSpher(spherpos)
[docs] def cylindrical_base_vects_in_cart_base(self):
"""Returns cylindrical basis vectors projected on cartesian basis. """
return Coords.cylindrical_basis_vects_in_cart_basis(self.phi())
[docs] def cartesian_base_vects_in_cyl_base(self):
"""Returns cartesian basis vectors projected on cylindrical basis. """
return Coords.cartesian_basis_vects_in_cyl_basis(self.phi())
[docs] def spherical_base_vects_in_cart_base(self):
"""Returns spherical basis vectors projected on cartesian basis. """
return Coords.spherical_basis_vects_in_cart_basis(self.spherical_theta(), self.phi())
[docs] def cartesian_base_vects_in_spher_base(self):
"""Returns cartesian basis vectors projected on spherical basis."""
return Coords.cartesian_basis_vects_in_spher_basis(self.spherical_theta(), self.phi())
[docs]class SpatialCoordsFromCyl:
"""Performs computations of cartesian or spherical coordinates from cylindrical positions.
Cylindrical positions are cylpos[:,0] = cyl radius, cylpos[:,1] = cyl phi angle and cylpos[:,2] = z position.
Parameters
----------
cylpos : ndarray
(N,3) cylpos[:,0] = cyl radius, cylpos[:,1] = cyl phi angle and cylpos[:,2] = z position.
"""
def __init__(self, cylpos):
CheckArrays.check_cylposlike_array(cylpos)
self.cylpos = cylpos
self.nb_parts = np.shape(self.cylpos)[0]
[docs] def xcart(self):
"""Returns cartesian x."""
return self.cylpos[:, 0] * np.cos(self.cylpos[:, 1])
[docs] def ycart(self):
"""Returns cartesian y."""
return self.cylpos[:, 0] * np.sin(self.cylpos[:, 1])
[docs] def zcart(self):
"""Returns cartesian z."""
return self.cylpos[:, 2]
[docs] def spherical_radius(self):
"""Returns spherical radius."""
return np.sqrt(self.cylpos[:, 0] ** 2 + self.cylpos[:, 2] ** 2)
[docs] def spherical_theta(self):
"""Return spherical theta."""
rads = self.spherical_radius()
return np.arccos(self.cylpos[:, 2] / rads)
[docs] def phi(self):
"""Returns cyindrical or spherical phi."""
return self.cylpos[:, 1]
[docs] def tocart_pos(self):
"""
Returns
-------
ndarray
(N,3) Cartesian positions.
"""
poscart = np.zeros_like(self.cylpos)
poscart[:, 0] = self.xcart()
poscart[:, 1] = self.ycart()
poscart[:, 2] = self.zcart()
return poscart
[docs] def tocart_sp_object(self):
"""Returns :class:`~galaximview.coords.SpatialCoordsFromCart` object.
Returns
-------
:class:`~galaximview.coords.SpatialCoordsFromCart` object.
"""
cartpos = self.tocart_pos()
return SpatialCoordsFromCart(cartpos)
[docs] def tospher_pos(self):
"""
Returns
-------
ndarray
(N,3) Spherical positions.
"""
spherpos = np.zeros_like(self.cylpos)
spherpos[:, 0] = self.spherical_radius()
spherpos[:, 1] = self.spherical_theta()
spherpos[:, 2] = self.phi()
return spherpos
[docs] def tospher_sp_object(self):
"""Returns :class:`~galaximview.coords.SpatialCoordsFromSpher` object.
Returns
-------
:class:`~galaximview.coords.SpatialCoordsFromSpher` object.
"""
spherpos = self.tospher_pos()
return SpatialCoordsFromSpher(spherpos)
[docs] def cartesian_base_vects_in_cyl_base(self):
"""Returns cartesian basis vectors projected on cylindrical basis. """
return Coords.cartesian_basis_vects_in_cyl_basis(self.phi())
[docs] def cylindrical_base_vects_in_cart_base(self):
"""Returns cylindrical basis vectors projected on cartesian basis. """
return Coords.cylindrical_basis_vects_in_cart_basis(self.phi())
[docs] def spherical_base_vects_in_cyl_base(self):
"""Returns spherical basis vectors projected on cylindrical basis. """
return Coords.spherical_basis_vects_in_cyl_basis(self.spherical_theta())
[docs] def cylindrical_base_vects_in_spher_base(self):
"""Returns cylindrical basis vectors projected on spherical basis. """
return Coords.cylindrical_basis_vects_in_spher_basis(self.spherical_theta())
[docs]class SpatialCoordsFromSpher:
"""Performs computations of cartesian or spherical coordinates from spherrical positions
Spherical positions are spherpos[:,0] = spher radius, spherpos[:,1] = spher theta angle and spherpos[:,
2] = phi angle.
Parameters
----------
spherpos : ndarray
(N,3) Positions. pherpos[:,0] = spher radius, spherpos[:,1] = spher theta angle and spherpos[:,
2] = phi angle.
"""
def __init__(self, spherpos):
CheckArrays.check_spherposlike_array(spherpos)
self.spherpos = spherpos
self.nb_parts = np.shape(self.spherpos)[0]
[docs] def xcart(self):
"""Returns cartesian x."""
return self.spherpos[:, 0] * np.sin(self.spherpos[:, 1]) * np.cos(self.spherpos[:, 2])
[docs] def ycart(self):
"""Returns cartesian y."""
return self.spherpos[:, 0] * np.sin(self.spherpos[:, 1]) * np.sin(self.spherpos[:, 2])
[docs] def zcart(self):
"""Returns cartesian z."""
return self.spherpos[:, 0] * np.cos(self.spherpos[:, 1])
[docs] def cylindrical_radius(self):
"""Returns cylindrical radius."""
return self.spherpos[:, 0] * np.sin(self.spherpos[:, 1])
[docs] def phi(self):
"""Returns cylindrical or spherical phi."""
return self.spherpos[:, 2]
[docs] def tocart_pos(self):
"""Returns cartesian positions.
Returns
-------
ndarray
(3,N) Cartesian positions.
"""
poscart = np.zeros_like(self.spherpos)
poscart[:, 0] = self.xcart()
poscart[:, 1] = self.ycart()
poscart[:, 2] = self.zcart()
return poscart
[docs] def tocart_sp_object(self):
"""Returns :class:`~galaximview.coords.SpatialCoordsFromartl` object.
Returns
-------
:class:`~galaximview.coords.SpatialCoordsFromCart` object.
"""
cartpos = self.tocart_pos()
return SpatialCoordsFromCart(cartpos)
[docs] def tocyl_pos(self):
"""Returns cylindrical positions.
Returns
-------
ndarray
(N,3) Cylindrical positions.
"""
cylpos = np.zeros_like(self.spherpos)
cylpos[:, 0] = self.cylindrical_radius()
cylpos[:, 1] = self.phi()
cylpos[:, 2] = self.zcart()
return cylpos
[docs] def tocyl_sp_object(self):
"""Returns :class:`~galaximview.coords.SpatialCoordsFromCyl` object.
Returns
-------
:class:`~galaximview.coords.SpatialCoordsFromCyl` object.
"""
cylpos = self.tocyl_pos()
return SpatialCoordsFromCyl(cylpos)
[docs] def cartesian_base_vects_in_spher_base(self):
"""Returns cartesian basis vectors projected on spherical basis. """
return Coords.cartesian_basis_vects_in_spher_basis(self.spherpos[:, 1], self.phi())
[docs] def spherical_base_vects_in_cart_base(self):
"""Returns spherical basis vectors projected on cartesian basis. """
return Coords.spherical_basis_vects_in_cart_basis(self.spherpos[:, 1], self.phi())
[docs] def cylindrical_base_vects_in_spher_base(self):
"""Returns cylindrical basis vectors projected on spherical basis. """
return Coords.cylindrical_basis_vects_in_spher_basis(self.spherpos[:, 1])
[docs] def spherical_base_vects_in_cyl_base(self):
"""Returns spherical basis vectors projected on cylindrical basis. """
return Coords.spherical_basis_vects_in_cyl_basis(self.spherpos[:, 1])
[docs]class VelCoordsFromCart(SpatialCoordsFromCart):
"""Performs computations of cylindrical or spherical velocity coordinates.
Parameters
----------
pos : ndarray
(N,3) Positions.
vel : ndarray
(N,3) Velocities.
ctre_pos: ndarray, optional
(3,) 3D position to be removed from all the particles positions, if desired (to compute cylindrical and
spherical positions with a different coordinates centre)
ctre_vel: ndarray, optional
(3,) 3D velocity to be removed from all the particles velocitiess, if desired (to compute cylindrical and
spherical coordinates with a different coordinates centre)
"""
def __init__(self, pos, vel, ctre_pos=np.zeros((3)), ctre_vel=np.zeros((3))):
SpatialCoordsFromCart.__init__(self, pos, ctre_pos=ctre_pos)
CheckArrays.check_poslike_array(vel)
self.vel = vel
self.vel -= ctre_vel
[docs] def norm_of_vel(self):
"""Returns norm of velocity."""
return np.sqrt(self.vel[:, 0] ** 2 + self.vel[:, 1] ** 2 + self.vel[:, 2] ** 2)
[docs] def average_vel_coords(self, weights):
"""Returns (weighted) average velocity componants.
Parameters
----------
weights: ndarray, optional
(N,) weights (e.g. masses).
Returns
-------
(float, float, float)
Average velocity componants.
"""
av_vx = BaseTools.average64_1d(self.vel[:, 0], weights=weights)
av_vy = BaseTools.average64_1d(self.vel[:, 1], weights=weights)
av_vz = BaseTools.average64_1d(self.vel[:, 2], weights=weights)
return av_vx, av_vy, av_vz
[docs] def disp_of_vel(self, weights):
"""Returns (weighted) dispersions of velocity componants.
Parameters
----------
weights: ndarray, optional
(N,) weights (e.g. masses).
Returns
-------
(float, float, float)
Average velocity componants.
"""
dispx = BaseTools.dispersion64_1d(self.vel[:, 0], weights=weights)
dispy = BaseTools.dispersion64_1d(self.vel[:, 1], weights=weights)
dispz = BaseTools.dispersion64_1d(self.vel[:, 2], weights=weights)
return dispx, dispy, dispz
[docs] def spherical_radial_vel(self):
"""Returns spherical radial velocity.
Returns
-------
ndarray
(N,) Radial spherical velocity.
"""
erspher, ethetaspher, ephi = self.spherical_base_vects_in_cart_base()
velr = np.zeros((self.nb_parts))
for k in range(0, 3):
velr[:] += self.vel[:, k] * erspher[k, :]
return velr
[docs] def spherical_theta_vel(self):
"""Returns spherical velocity along etheta vector.
Returns
-------
ndarray
(N,) Theta spherical velocity.
"""
erspher, ethetaspher, ephi = self.spherical_base_vects_in_cart_base()
veltheta = np.zeros((self.nb_parts))
for k in range(0, 3):
veltheta[:] += self.vel[:, k] * ethetaspher[k, :]
return veltheta
[docs] def phi_vel(self):
"""Returns velocity projected on phi unit vector of both cylindrical and spherical bases.
Returns
-------
ndarray
(N,) Phi spherical or cylindrical velocity.
"""
erspher, ethetaspher, ephi = self.spherical_base_vects_in_cart_base()
v_phi = np.zeros((self.nb_parts))
for k in range(0, 3):
v_phi[:] += self.vel[:, k] * ephi[k, :]
return v_phi
[docs] def cylindrical_radial_vel(self):
"""Returns cylindrical radial velocity.
Returns
-------
ndarray
(N,) Cylindrical radial velocity.
"""
ercyl, ephi, ez = self.cylindrical_base_vects_in_cart_base()
velr = np.zeros((self.nb_parts))
for k in range(0, 3):
velr[:] += self.vel[:, k] * ercyl[k, :]
return velr
[docs] def tocyl_vel(self):
"""Returns cylindrical velocities.
Returns
-------
ndarray
(N,3) Cylindrical velocities.
"""
cylvel = np.zeros_like(self.vel)
cylvel[:, 0] = self.cylindrical_radial_vel()
cylvel[:, 1] = self.phi_vel()
cylvel[:, 2] = self.vel[:, 2]
return cylvel
[docs] def tocyl_velc_object(self):
"""Returns :class:`~galaximview.coords.VelCoordsFromCyl` object.
Returns
-------
:class:`~galaximview.coords.VelCoordsFromCyl` object.
"""
cylpos = self.tocyl_pos()
cylvel = self.tocyl_vel()
return VelCoordsFromCyl(cylpos, cylvel)
[docs] def tospher_vel(self):
"""Returns spherical velocities.
Returns
-------
ndarray
(N,3) Spherical velocities.
"""
sphervel = np.zeros_like(self.vel)
sphervel[:, 0] = self.spherical_radial_vel()
sphervel[:, 1] = self.spherical_theta_vel()
sphervel[:, 2] = self.phi_vel()
return sphervel
[docs] def tospher_velc_object(self):
"""Returns :class:`~galaximview.coords.VelCoordsFromSpher` object.
Returns
-------
:class:`~galaximview.coords.VelCoordsFromSpher` object.
"""
spherpos = self.tospher_pos()
sphervel = self.tospher_vel()
return VelCoordsFromSpher(spherpos, sphervel)
[docs]class VelCoordsFromCyl(SpatialCoordsFromCyl):
"""Performs computations of cylindrical or spherical velocity coordinates.
Parameters
----------
pos : ndarray
(N,3) Positions.
vel : ndarray
(N,3) Velocities.
"""
def __init__(self, pos, vel):
SpatialCoordsFromCyl.__init__(self, pos)
CheckArrays.check_poslike_array(vel)
self.vel = vel
[docs] def norm_of_vel(self):
"""Returns norm of velocity."""
return np.sqrt(self.vel[:, 0] ** 2 + self.vel[:, 1] ** 2 + self.vel[:, 2] ** 2)
[docs] def average_vel_coords(self, weights):
"""Returns (weighted) average velocity componants.
Parameters
----------
weights: ndarray, optional
(N,) weights (e.g. masses).
Returns
-------
(float, float, float)
Average velocity componants.
"""
av_vx = BaseTools.average64_1d(self.vel[:, 0], weights=weights)
av_vy = BaseTools.average64_1d(self.vel[:, 1], weights=weights)
av_vz = BaseTools.average64_1d(self.vel[:, 2], weights=weights)
return av_vx, av_vy, av_vz
[docs] def disp_of_vel(self, weights):
"""Returns (weighted) dispersions of velocity componants.
Parameters
----------
weights: ndarray, optional
(N,) weights (e.g. masses).
Returns
-------
(float, float, float)
Average velocity componants.
"""
dispx = BaseTools.dispersion64_1d(self.vel[:, 0], weights=weights)
dispy = BaseTools.dispersion64_1d(self.vel[:, 1], weights=weights)
dispz = BaseTools.dispersion64_1d(self.vel[:, 2], weights=weights)
return dispx, dispy, dispz
[docs] def vel_xcart(self):
"""Returns cartesian x velocity."""
ex, ey, ez = self.cartesian_base_vects_in_cyl_base()
velx = np.zeros((self.nb_parts))
for k in range(0, 3):
velx[:] += self.vel[:, k] * ex[k, :]
return velx
[docs] def vel_ycart(self):
"""Returns cartesian y velocity."""
ex, ey, ez = self.cartesian_base_vects_in_cyl_base()
vely = np.zeros((self.nb_parts))
for k in range(0, 3):
vely[:] += self.vel[:, k] * ey[k, :]
return vely
[docs] def spherical_radial_vel(self):
"""Returns spherical radial velocity."""
erspher, ethetaspher, ephi = self.spherical_base_vects_in_cyl_base()
velr = np.zeros((self.nb_parts))
for k in range(0, 3):
velr += self.vel[:, k] * erspher[k, :]
return velr
[docs] def spherical_theta_vel(self):
"""Returns spherical theta velocity."""
erspher, ethetaspher, ephi = self.spherical_base_vects_in_cyl_base()
veltheta = np.zeros((self.nb_parts))
for k in range(0, 3):
veltheta += self.vel[:, k] * ethetaspher[k, :]
return veltheta
[docs] def tocart_vel(self):
"""Returns cartesian velocities.
Returns
-------
ndarray
(3,N) Cartesian velocities.
"""
velcart = np.zeros_like(self.vel)
velcart[:, 0] = self.vel_xcart()
velcart[:, 1] = self.vel_ycart()
velcart[:, 2] = self.vel[:, 2]
return velcart
[docs] def tocart_velc_object(self):
"""Returns :class:`~galaximview.coords.VelCoordsFromCart` object.
Returns
-------
:class:`~galaximview.coords.VelCoordsFromCart` object.
"""
pos = self.tocart_pos()
vel = self.tocart_vel()
return VelCoordsFromCart(pos, vel)
[docs] def tospher_vel(self):
"""Returns spherical velocities.
Returns
-------
ndarray
(3,N) Spherical velocities.
"""
sphervel = np.zeros_like(self.vel)
sphervel[:, 0] = self.spherical_radial_vel()
sphervel[:, 1] = self.spherical_theta_vel()
sphervel[:, 2] = self.vel[:, 1]
return sphervel
[docs] def tospher_velc_object(self):
"""Returns :class:`~galaximview.coords.VelCoordsFromSpher` object.
Returns
-------
:class:`~galaximview.coords.VelCoordsFromSpher` object.
"""
spherpos = self.tospher_pos()
sphervel = self.tospher_vel()
return VelCoordsFromSpher(spherpos, sphervel)
[docs]class VelCoordsFromSpher(SpatialCoordsFromSpher):
"""Performs computations of cylindrical or spherical velocity coordinates.
Parameters
----------
pos : ndarray
(N,3) Positions.
vel : ndarray
(N,3) Velocities.
Returns
-------
Object
VelCoordsFromSpher object.
"""
def __init__(self, pos, vel):
SpatialCoordsFromSpher.__init__(self, pos)
CheckArrays.check_poslike_array(vel)
self.vel = vel
[docs] def norm_of_vel(self):
"""Returns norm of velocity."""
return np.sqrt(self.vel[:, 0] ** 2 + self.vel[:, 1] ** 2 + self.vel[:, 2] ** 2)
[docs] def average_vel_coords(self, weights):
"""Returns (weighted) average velocity componants.
Parameters
----------
weights: ndarray, optional
(N,) weights (e.g. masses).
Returns
-------
(float, float, float)
Average velocity componants.
"""
av_vx = BaseTools.average64_1d(self.vel[:, 0], weights=weights)
av_vy = BaseTools.average64_1d(self.vel[:, 1], weights=weights)
av_vz = BaseTools.average64_1d(self.vel[:, 2], weights=weights)
return av_vx, av_vy, av_vz
[docs] def disp_of_vel(self, weights):
"""Returns (weighted) dispersions of velocity componants.
Parameters
----------
weights: ndarray, optional
(N,) weights (e.g. masses).
Returns
-------
(float, float, float)
Average velocity componants.
"""
dispx = BaseTools.dispersion64_1d(self.vel[:, 0], weights=weights)
dispy = BaseTools.dispersion64_1d(self.vel[:, 1], weights=weights)
dispz = BaseTools.dispersion64_1d(self.vel[:, 2], weights=weights)
return dispx, dispy, dispz
[docs] def vel_xcart(self):
"""Returns cartesian vx. """
ex, ey, ez = self.cartesian_base_vects_in_spher_base()
velx = np.zeros((self.nb_parts))
for k in range(0, 3):
velx[:] += self.vel[:, k] * ex[k, :]
return velx
[docs] def vel_ycart(self):
"""Returns cartesian vy."""
ex, ey, ez = self.cartesian_base_vects_in_spher_base()
vely = np.zeros((self.nb_parts))
for k in range(0, 3):
vely[:] += self.vel[:, k] * ey[k, :]
return vely
[docs] def vel_zcart(self):
"""Returns cartesian vz."""
ex, ey, ez = self.cartesian_base_vects_in_spher_base()
velz = np.zeros((self.nb_parts))
for k in range(0, 3):
velz[:] += self.vel[:, k] * ez[k, :]
return velz
[docs] def cylindrical_radial_vel(self):
"""Returns cylindrical vr."""
ercyl, ephi, ez = self.cylindrical_base_vects_in_spher_base()
velr = np.zeros((self.nb_parts))
for k in range(0, 3):
velr[:] += self.vel[:, k] * ercyl[k, :]
return velr
[docs] def tocart_vel(self):
"""Returns cartesian velocities.
Returns
-------
ndarray
(3,N) Cartesian velocities.
"""
velcart = np.zeros_like(self.vel)
velcart[:, 0] = self.vel_xcart()
velcart[:, 1] = self.vel_ycart()
velcart[:, 2] = self.vel_zcart()
return velcart
[docs] def tocart_velc_object(self):
"""Returns :class:`~galaximview.coords.VelCoordsFromCart` object.
Returns
-------
:class:`~galaximview.coords.VelCoordsFromCart` object.
"""
pos = self.tocart_pos()
vel = self.tocart_vel()
return VelCoordsFromCart(pos, vel)
[docs] def tocyl_vel(self):
"""Returns cylindrical velocities.
Returns
-------
ndarray
(3,N) Cylindrical velocities.
"""
cylvel = np.zeros_like(self.vel)
cylvel[:, 0] = self.cylindrical_radial_vel()
cylvel[:, 1] = self.vel[:, 2]
cylvel[:, 2] = self.vel_zcart()
return cylvel
[docs] def tocyl_velc_object(self):
"""Returns :class:`~galaximview.coords.VelCoordsFromCyl` object.
Returns
-------
:class:`~galaximview.coords.VelCoordsFromCyl` object.
"""
cylpos = self.tocyl_pos()
cylvel = self.tocyl_vel()
return VelCoordsFromCyl(cylpos, cylvel)
[docs]class DynamicsFromCart(VelCoordsFromCart):
"""Performs computations of angular momentum, kinetic and gravitational potential energy of particles.
Initialized with positions, velocities and masses.
Parameters
----------
pos : ndarray
(N,3) Positions.
vel : ndarray
(N,3) Velocities.
mass: ndarray
(N,) Masses.
ctre_pos: ndarray, optional
(3,) 3D position to be removed from all the particles positions, if desired (to compute cylindrical and
spherical positions with a different coordinates centre)
ctre_vel: ndarray, optional
(3,) 3D velocity to be removed from all the particles velocitiess, if desired (to compute cylindrical and
spherical coordinates with a different coordinates centre)
"""
def __init__(self, pos, vel, mass, ctre_pos=np.zeros((3)), ctre_vel=np.zeros((3))):
VelCoordsFromCart.__init__(self, pos, vel, ctre_pos=ctre_pos, ctre_vel=ctre_vel)
self.mass = mass
[docs] def angular_momentum_3d(self):
"""Returns individual angular momenta m r vect v. Overwritten for cylindrical or spherical coordinates.
Returns
-------
ndarray
(N,3) angular momenta.
"""
return np.reshape(self.mass, (-1, 1)) * np.cross(self.pos, self.vel)
[docs] def specific_angular_momentum_3d(self):
"""Returns individual specific angular momenta r vect v. Overwritten for cylindrical or spherical coordinates.
Returns
-------
ndarray
(N,3) specific angular momenta.
"""
return np.cross(self.pos, self.vel)
[docs] def total_angular_momentum_3d(self):
"""Returns total angular momentum."""
jang3d = self.angular_momentum_3d()
total_jang3d = np.sum(jang3d, axis=0, dtype='float64')
return total_jang3d
[docs] def total_specific_angular_momentum_3d(self):
"""Returns total specific angular momentum."""
jang3d = self.specific_angular_momentum_3d()
total_jang3d = np.sum(jang3d, axis=0, dtype='float64')
return total_jang3d
[docs] def spin(self):
"""Returns spin, i.e. angular momentum normalised to unity."""
total_jang3d = self.total_angular_momentum_3d()
return BaseTools.normalise_vector_to_unity(total_jang3d)
[docs] def angular_momentum_norm(self):
"""Returns individual norms of angular momenta m * r vect v."""
jang3d = self.angular_momentum_3d()
jang_norms = np.zeros((np.shape(jang3d)[0]))
for k in range(0, 3):
jang_norms[:] += jang3d[:, k] ** 2
jang_norms = np.sqrt(jang_norms)
return jang_norms
[docs] def specific_angular_momentum_norm(self):
"""Returns individual norms of angular momenta m * r vect v."""
jang3d = self.specific_angular_momentum_3d()
jang_norms = np.zeros((np.shape(jang3d)[0]))
for k in range(0, 3):
jang_norms[:] += jang3d[:, k] ** 2
jang_norms = np.sqrt(jang_norms)
return jang_norms
[docs] def total_angular_momentum_norm(self):
""" """
total_jang3d = self.total_angular_momentum_3d()
total_jang_norm = 0
for k in range(0, 3):
total_jang_norm += total_jang3d[k] ** 2
total_jang_norm = np.sqrt(total_jang_norm)
return total_jang_norm
[docs] def total_specific_angular_momentum_norm(self):
""" """
total_jang3d = self.total_specific_angular_momentum_3d()
total_jang_norm = 0
for k in range(0, 3):
total_jang_norm += total_jang3d[k] ** 2
total_jang_norm = np.sqrt(total_jang_norm)
return total_jang_norm
[docs] def kinetic_energy(self):
""" """
vel2 = 0
for k in range(0, 3):
vel2 += self.vel[:, k] ** 2
return 0.5 * self.mass * vel2
[docs] def gravitational_potential_energy(self, pot):
"""Returns gravitational potential energies.
Parameters
----------
pot : ndarray
(N,) Gravitational potential.
Returns
-------
ndarray
(N,) Gravitational potential energies.
"""
CheckArrays.check_masslike_array(pot)
if np.shape(pot)[0] != np.shape(self.mass)[0]:
raise ValueError("Should be given potential array of shape (N,), same as mass array shape.")
return 0.5 * self.mass * pot
[docs] def inertia_tensor(self):
"""Returns inertia tensor.
Returns
-------
ndarray
(3,3) inertia tensor.
"""
ixx = np.sum(self.mass * (self.pos[:, 1] * self.pos[:, 1] + self.pos[:, 2] * self.pos[:, 2]), dtype=np.float64)
iyy = np.sum(self.mass * (self.pos[:, 0] * self.pos[:, 0] + self.pos[:, 2] * self.pos[:, 2]), dtype=np.float64)
izz = np.sum(self.mass * (self.pos[:, 0] * self.pos[:, 0] + self.pos[:, 1] * self.pos[:, 1]), dtype=np.float64)
ixy = -np.sum(self.mass * (self.pos[:, 0] * self.pos[:, 1]), dtype=np.float64)
ixz = -np.sum(self.mass * (self.pos[:, 0] * self.pos[:, 2]), dtype=np.float64)
iyz = -np.sum(self.mass * (self.pos[:, 1] * self.pos[:, 2]), dtype=np.float64)
itens = np.array([[ixx, ixy, ixz], [ixy, iyy, iyz], [ixz, iyz, izz]])
return itens
[docs] def eigenvalues_of_inertia_tensor(self):
"""Returns eigenvalues and eigenvectors of inertia tensor.
"""
itens = self.inertia_tensor()
w, v = la.eig(itens)
inds_sorted = np.argsort(w)[::-1] # indexes for eigenvalues sorted from larger to smaller
w = w[inds_sorted]
v = v[inds_sorted]
return w, v
[docs] def tocyl_dyn_obj(self):
"""Returns :class:`~galaximview.coords.DynamicsFromCyl` object.
Returns
-------
:class:`~galaximview.coords.DynamicsFromCyl` object.
"""
velc = VelCoordsFromCart(self.pos, self.vel)
velc_cyl = velc.tocyl_velc_object()
return DynamicsFromCyl(velc_cyl.cylpos, velc_cyl.vel, self.mass)
[docs] def tospher_dyn_obj(self):
"""Returns :class:`~galaximview.coords.DynamicsFromSpher` object.
Returns
-------
:class:`~galaximview.coords.DynamicsFromSpher` object.
"""
velc = VelCoordsFromCart(self.pos, self.vel)
velc_spher = velc.tospher_velc_object()
return DynamicsFromSpher(velc_spher.spherpos, velc_spher.vel, self.mass)
[docs]class DynamicsFromCyl(VelCoordsFromCyl):
"""
Parameters
----------
pos : ndarray
(N,3) Positions.
vel : ndarray
(N,3) Velocities.
mass: ndarray
(N,) Masses.
"""
def __init__(self, pos, vel, mass):
VelCoordsFromCyl.__init__(self, pos, vel)
self.mass = mass
self.posrz = np.zeros_like(self.cylpos)
self.posrz[:, 0] = self.cylpos[:, 0]
self.posrz[:, 2] = self.cylpos[:, 2]
[docs] def angular_momentum_3d(self):
"""Returns individual angular momenta m r vect v.
Returns
-------
ndarray
(N,3) angular momenta."""
return np.reshape(self.mass, (-1, 1)) * np.cross(self.posrz, self.vel)
[docs] def specific_angular_momentum_3d(self):
"""Returns individual specific angular momenta r vect v.
Returns
-------
ndarray
(N,3) specific angular momenta."""
return np.cross(self.posrz, self.vel)
[docs] def tocart_dyn_obj(self):
"""Returns :class:`~galaximview.coords.DynamicsFromCart` object.
Returns
-------
:class:`~galaximview.coords.DynamicsFromCart` object.
"""
velc = VelCoordsFromCyl(self.cylpos, self.vel)
velc_cart = velc.tocart_velc_object()
return DynamicsFromCart(velc_cart.pos, velc_cart.vel, self.mass)
[docs] def tospher_dyn_obj(self):
"""Returns :class:`~galaximview.coords.DynamicsFromSpher` object.
Returns
-------
:class:`~galaximview.coords.DynamicsFromSpher` object.
"""
velc = VelCoordsFromCyl(self.cylpos, self.vel)
velc_spher = velc.tospher_velc_object()
return DynamicsFromSpher(velc_spher.spherpos, velc_spher.vel, self.mass)
[docs]class DynamicsFromSpher(VelCoordsFromSpher):
"""
Parameters
----------
pos : ndarray
(N,3) Positions.
vel : ndarray
(N,3) Velocities.
mass: ndarray
(N,) Masses.
"""
def __init__(self, pos, vel, mass):
VelCoordsFromSpher.__init__(self, pos, vel)
self.mass = mass
self.posr = np.zeros_like(self.spherpos)
self.posr[:, 0] = self.spherpos[:, 0]
[docs] def angular_momentum_3d(self):
"""Returns individual angular momenta m r vect v.
Returns
-------
ndarray
(N,3) angular momenta."""
return np.reshape(self.mass, (-1, 1)) * np.cross(self.posr, self.vel)
[docs] def specific_angular_momentum_3d(self):
"""Returns individual specific angular momenta r vect v.
Returns
-------
ndarray
(N,3) specific angular momenta."""
return np.cross(self.posr, self.vel)
[docs] def tocyl_dyn_obj(self):
"""Returns :class:`~galaximview.coords.DynamicsFromCyl` object.
Returns
-------
:class:`~galaximview.coords.DynamicsFromCyl` object.
"""
velc = VelCoordsFromSpher(self.spherpos, self.vel)
velc_cyl = velc.tocyl_velc_object()
return DynamicsFromCyl(velc_cyl.cylpos, velc_cyl.vel, self.mass)
[docs] def tocart_dyn_obj(self):
"""Returns :class:`~galaximview.coords.DynamicsFromCart` object.
Returns
-------
:class:`~galaximview.coords.DynamicsFromCart` object.
"""
velc = VelCoordsFromSpher(self.spherpos, self.vel)
velc_cart = velc.tocart_velc_object()
return DynamicsFromCart(velc_cart.pos, velc_cart.vel, self.mass)