Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions exptool/analysis/centering.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ def compute_rotation_to_vec(self, vec, r_max=np.inf):
L = np.array([Lxtot, Lytot, Lztot])
L /= np.linalg.norm(L)

# in case of diagnostic checking
self.prerotation_lvec = L

vec /= np.linalg.norm(vec)

axis = np.cross(L, vec)
Expand Down
87 changes: 63 additions & 24 deletions exptool/observables/velocity.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,73 @@



def measured_rotation(infile,comp,rmax=0.06,nsamp=256):
def measured_rotation(infile, comp, rmax=0.06, nsamp=256):
'''
velocity.measured_rotation
measure rotation velocity from particles
Calculate the measured rotation velocity from particle data.

inputs
---------------
infile
comp
rmax
nsamp

outputs
--------------
This function computes the rotational velocity profile based on particle positions
and velocities within a specified radial extent (rmax). A 2D Kernel Density Estimation (KDE)
is performed on the radial and angular coordinates, both weighted and unweighted by
rotational contributions, to derive the rotation profile.

Parameters
----------
infile : str
Path to the input file containing particle data.
comp : str
Component of the data to be analyzed (e.g., "disk", "bulge").
rmax : float, optional
Maximum radial distance to consider for the rotation measurement, in the same units
as particle positions. Default is 0.06.
nsamp : int, optional
Number of sampling points for the KDE grid along each dimension. Default is 256.

Returns
-------
rbins : ndarray
Array of radial bin edges from 0 to rmax.
rotation_profile : ndarray
Array representing the rotation velocity profile as a function of radius.
Comment thread
michael-petersen marked this conversation as resolved.
'''
O = particle.Input(infile,comp=comp)
extent = rmax
nsamp = 256
kde_weight = (O.xpos*O.yvel - O.ypos*O.xvel)/( (O.xpos*O.xpos + O.ypos*O.ypos)**0.5)
#
rvals = ( (O.xpos*O.xpos + O.ypos*O.ypos)**0.5)
tvals = np.arctan2( O.ypos,O.xpos)
w = np.where( (abs(rvals) < rmax))[0]
vv = kde_3d.fast_kde_two(rvals[w],tvals[w], gridsize=(nsamp,nsamp), extents=(0.,rmax,-np.pi,np.pi), nocorrelation=False, weights=kde_weight[w])
tt = kde_3d.fast_kde_two(rvals[w],tvals[w], gridsize=(nsamp,nsamp), extents=(0.,rmax,-np.pi,np.pi), nocorrelation=False, weights=None)
rbins = np.linspace(0.0,rmax,nsamp)
return rbins,vv/tt

# Load particle data from file and component type specified
O = particle.Input(infile, comp=comp)

# Set the extent and number of KDE samples

# Compute rotation-weighted KDE weight as (x*yvel - y*xvel) / sqrt(x^2 + y^2)
# This approximates the tangential (rotational) velocity component in 2D
kde_weight = (O.xpos * O.yvel - O.ypos * O.xvel) / ((O.xpos**2 + O.ypos**2)**0.5)

# Calculate radial distances and angular coordinates of particles
rvals = (O.xpos**2 + O.ypos**2)**0.5 # Radial distance from origin
tvals = np.arctan2(O.ypos, O.xpos) # Angular position in radians

# Filter particles within the specified radial limit (rmax)
w = np.where(abs(rvals) < rmax)[0]

# Perform KDE on (rvals, tvals) with weights (kde_weight) for rotation-weighted density
vv = kde_3d.fast_kde_two(
rvals[w], tvals[w],
gridsize=(nsamp, nsamp),
extents=(0., rmax, -np.pi, np.pi),
nocorrelation=False,
weights=kde_weight[w]
)

# Perform KDE on (rvals, tvals) without weights for unweighted particle density
tt = kde_3d.fast_kde_two(
rvals[w], tvals[w],
gridsize=(nsamp, nsamp),
extents=(0., rmax, -np.pi, np.pi),
nocorrelation=False,
weights=None
)

# Generate radial bins from 0 to rmax for the resulting profile
rbins = np.linspace(0.0, rmax, nsamp)

# Compute rotation velocity profile by normalizing weighted density by unweighted density
rotation_profile = vv / tt

return rbins, rotation_profile