Rings API¶
- class pylanetary.rings.core.Ring(a, e, w, i, omega, width=1.0, flux=1.0, params_sys=[0.0, 0.0, 0.0])¶
model of a planetary ring
- Parameters:
a (float or Quantity, required.) – semimajor axis. assumes km if not an astropy Quantity
e (float, required.) – eccentricity
w (float or Quantity, required.) – argument of periapsis. assumes degrees if not an astropy Quantity
i (float or Quantity, required.) – inclination. assumes degrees if not an astropy Quantity
omega (float or Quantity, required.) – longitude of ascending node. assumes degrees if not an astropy Quantity
width (float or Quantity, optional. default 1 km (i.e., very thin).) – full width of ring. assumes km if not an astropy Quantity
flux (float or Quantity, optional. default 1.0.) – ring flux density
params_sys (np.array, optional) – shape (3,). [w, i, omega] of ring system plane relative to observer
- same as parameters
Examples
Notes
Passing astropy Quantities is not yet tested
- as_2d_array(shape, pixscale, focus=None, width=None, flux=None, beam=None)¶
make a 2-d array that looks like a mock observation of the ring with optional smearing over a beam
- Parameters:
shape (tuple, required.) – output image shape
pixscale (float or astropy Quantity, required.) – pixel scale of the output image. assumes km/px if not Quantity
focus (tuple, optional, default None.) – pixel location of planet around which ring orbits. if not specified, center of image is assumed
width (float or Quantity, optional. default None.) – non-projected (face-on) full width of ring. if not specified, assumes width of 1 km.
flux (float or Quantity, optional, default None.) – technically not a flux, but a specific intensity! sets specific intensity of ring if not specified, assumes 1 [unit??].
beam (float, 3-element array-like, or 2-d array, optional, default None.) – Gaussian beam with which to convolve the observation see docstring of utils.convolve_with_beam()
- Returns:
beam-convolved ring image
- Return type:
np.array
Examples
- as_azimuthal_wedges(shape, pixscale, focus=None, nwedges=60, width=None, n=1000.0, z=5)¶
return n partial elliptical annulus wedges, e.g. for computing azimuthal profile of ring
- Parameters:
shape (tuple, required.) – shape of image in pixels
focus (tuple, required.) – location of planet (one ellipse focus) in pixels
pixscale (astropy Quantity or float, required) – pixel scale of image. assumes km/px if not Quantity
nwedges (int, optional. default 60.) – number of wedges to compute
width (astropy quantity required)
n (int, optional. default 1000.) – number of points for as_elliptical_annulus to compute. see that docstring for details. should be much larger than nwedges
z (int, optional. default 5) – factor for ndimage.zoom larger makes more accurate wedge areas
- Returns:
np.array – shape (nwedges,). angles in radians from 0 to 2*pi corresponding to lower corner of wedge
list – len nwedges. list of wedge masks
Notes
current implementation removes foreshortening correction “magically” by making the angular width of the wedges in the image plane see ring-system-modeling-tutorial.ipynb for a more detailed explanation and example.
This is computationally expensive! a better implementation would be to make a photutils object for wedges of an ellipse. but this requires Cython and a lot of geometry
- as_elliptical_annulus(focus, pixscale, width=None, n=1000.0, return_params=False)¶
make Astropy aperture photometry elliptical annulus object surrounding the ring
- Parameters:
focus (tuple, required.) – location of planet (one of the foci of the ellipse) in pixels
pixscale (float or Quantity, required.) – pixel scale of observations. assumes km/px if not Quantity
width (float or Quantity, required.) – true (non-projected) full width of ring. assumes km if not Quantity
n (int, optional. default 1000.) – number of data points to rotate and project higher n means more accurate estimation of aperture.EllipticalAnnulus projected a, b, theta values
return_params (bool, optional. default False.) – If True, return model ellipse dict see docstring of project_ellipse_double()
- Returns:
if return_params == True, also returns the dictionary from project_ellipse_double
- Return type:
photutils.EllipticalAnnulus object.
- class pylanetary.rings.core.RingSystemModelObservation(body, location, ringnames=None, fluxes='default')¶
model ring system combining static data from https://pds-rings.seti.org/uranus/uranus_rings_table.html with Planetary Ring Node ephemeris and JPL Horizons ephemeris
- Parameters:
body (pylanetary.utils.Body object, required.) – one of Jupiter, Saturn, Uranus, Neptune
location (str, array-like, or ~astropy.coordinates.EarthLocation, optional.) – If str, named observeratory supported by the ring node, e.g. JWST. If array-like, observer’s location as a 3-element array of Earth longitude, latitude, altitude that istantiates an ~astropy.coordinates.EarthLocation object. Longitude and latitude should be anything that initializes an ~astropy.coordinates.Angle object, and altitude should initialize an ~astropy.units.Quantity object (with units of length). If
None, then the geofocus is used. Unfortunately, it is not presently possible to get location information directly from the Body object, because the JPL Horizons query tool that Body uses requires a Horizons obs code, whereas the Planetary Ring Node query tool requires the format specified here. To prevent weird results, you should ensure that Body.jpl_hor_id matches the location you are inputting here!ringnames (list, optional.) – names of rings to include in the model if no ringnames provided then all rings are assumed. Case-sensitive! Typically capitalized, e.g. “Alpha”
fluxes (list, np.array, or "default", optional. default "default".) – brightnesses associated with rings specified in ringnames. surface brightness units are expected, e.g. brightness temperature if fluxes == ‘default’, optical depths are read in from the static table and exponentiated to more closely resemble surface brightness units so the result is the attenuation, ATT = 1 - exp(ringtable[‘Optical Depth’]) assuming the emittance is small (violated for thermal observations, obviously)
- planetname¶
name of planet
- Type:
str
- rings¶
dictionary of ringmodel.Ring objects, with ring names as keys note ring names are case-sensitive! Typically capitalized, e.g. “Alpha”
- Type:
dict
- ringtable¶
ephemeris data from ring node query tool as well as time-invariant parameters for each ring from static table
- Type:
Astropy table
- systemtable¶
ephemeris data for ring system from ring node query tool
- Type:
Astropy table
- bodytable¶
ephemeris data for satellites from ring node query tool
- Type:
Astropy table
- ephem¶
JPL Horizons ephemeris
- Type:
Astropy table
- np_ang¶
north polar angle
- Type:
float
Examples
Need an example of how to add a custom ring should be possible by just adding a ringmodel.Ring() object into the dict self.ring
Need an example of how to modify ring data should be possible by just changing the ringmodel.Ring() object in the dict self.ring
Notes
Not yet understood why omega must equal 0 for individual rings relative to ring system in order to make argument of periapsis agree with the Planetary Ring Node.
Make this work nicely with utils.Body object
implement default epoch and location
lookup table to avoid needing to specify both location and horizons_loc
- as_2d_array(shape, pixscale, focus=None, beam=None)¶
return a 2-d array that looks like a mock observation optional smearing over Gaussian beam
- Parameters:
shape (tuple, required.) – output image shape in number of pixels
pixscale (float or Quantity, required.) – pixel scale of the output image. if not Quantity, assumes units of km/px
focus (tuple, optional.) – pixel location of planet center if None, assumes center of image.
beam (float, 3-element array-like, or 2-d np.array, optional.) – Gaussian beam with which to convolve the observation see docstring of utils.convolve_with_beam() if no beam is specified, will make infinite-resolution
- Returns:
mock observation image
- Return type:
np.array
- pylanetary.rings.core.b_from_ae(a, e)¶
- Parameters:
a (float, required.) – semimajor axis of ellipse
e (float, required.) – eccentricity of ellipse
- Returns:
semiminor axis of ellipse
- Return type:
float
- pylanetary.rings.core.calc_abtheta(ell)¶
given vectors defining the circumference of an ellipse, find corresponding values of a, b, and theta using the fact that locations of a, b are max, min of ellipse vectors
- Parameters:
ell (np.array, required) – shape (n, 3), vectors along circumference of ring
- Returns:
float – semimajor axis of ellipse
float – semiminor axis of ellipse
float – rotation angle of ellipse in degrees
- pylanetary.rings.core.double_rotate(vec, params_ring, params_sys)¶
rotate system x rotate ring same convention as planetary ring node to agree with planetary ring node, params_sys = [90, B - 90, np_ang] and params_ring = [w, i, 0]
- Parameters:
vec (np.array, required) – shape (n, 3). 3-element [x, y, 0] vectors on the perimeter of the ring i.e. semimajor axis is [a, 0, 0] and semiminor axis is [0, b, 0]
params_ring (np.array, required) – params_ring = [w, i, omega] all in degrees w.r.t the ring plane
params_sys (np.array, required) – params_sys = [w, i, omega] in degrees for the ring plane w.r.t. observer
- Returns:
shape (n, 3), the rotated vectors
- Return type:
np.array
- pylanetary.rings.core.foreshortening(theta, i)¶
corrects for foreshortening of inclined rings
- Parameters:
theta (float, required.) – units radians. azimuth angle along the ring from 0 to 2*pi
i (float, required.) – units degrees. inclination of ring
- Returns:
fraction by which to multiply ring brightness at azimuth angle theta to correct foreshortening.
- Return type:
float
References
de Pater et al 2006, doi:10.1016/j.icarus.2005.08.011
Notes
needs to accept Astropy angles
- pylanetary.rings.core.plane_project(X, Z)¶
projects vectors X into plane normal to vector Z
- Parameters:
X (np.array, required) – shape (n,3). vectors to project
Z (np.array, required) – shape (3,). direction to project in.
- Returns:
shape (3,). the projected vector.
- Return type:
np.array
- pylanetary.rings.core.project_ellipse_double(a, e, params_ring, params_sys, origin=array([0, 0, 0]), n=50, proj_plane=[0, 0, 1])¶
make a projection of an ellipse representing a ring with ring system parameters as Euler angles [w, i, omega] and individual ring parameters relative to the system also as Euler angles [w, i, omega]. The angles params=[w, i, omega] and params_sys=[w_sys, i_sys, omega_sys] represent two sets of Euler angles [gamma, beta, alpha] such that the total rotation is given by (params_sys rotation matrix) x (params rotation matrix) This code builds an ellipse in the x,y plane represented by vectors, applies the double rotation to those vectors, then re-projects the ellipse into the x,y plane. This simulates an observation of a ring.
References
https://en.wikipedia.org/wiki/Euler_angles https://en.wikipedia.org/wiki/Orbital_elements#Euler_angle_transformations
- Parameters:
a (float, required.) – semimajor axis in any distance unit.
e (float, required.) – eccentricity, unitless.
params_ring (np.array, required) – shape (3,). [w, i, omega] of ring relative to ring system.
params_sys (np.array, required) – shape (3,). [w, i, omega] of ring plane relative to observer.
n (int, required.) – number of equally-spaced points in ellipse circumference to compute
origin (np.array, required) – shape (3,). vector pointing to center of the ellipse
proj_plane (np.array, required) – shape (3,). normal vector to plane that you want to re-project back to after rotation typically this will be [0, 0, 1], i.e., re-project to x,y plane
- Returns:
dictionary of projected ellipse parameters with the following keys: a: np.array, shape (3,), projected semimajor axis of ring b: np.array, shape (3,), projected semiminor axis of ring f0: np.array, shape (3,), vector to one focus f1: np.array, shape (3,), vector to the other focus ell: np.array, shape (n,3), vectors along circumference of ring
- Return type:
dict
- pylanetary.rings.core.ring_area(a, e, width, delta_width=0.0, B=90.0)¶
Compute projected area of an eccentric ring at a given opening angle and peri-apo width asymmetry
- Parameters:
a (float, required.) – [distance] semimajor axis
e (float, required.) – eccentricity
width (float, required.) – [distance] average width of ring for an asymmetric ring, use (apoapsis_width + periapsis_width)/2
delta_width (float, optional. default 0.0) – [distance] apoapsis width minus periapsis width
B (float, optional. default 90 (i.e., open)) – [degrees] ring opening angle
- Returns:
projected area in [distance unit]^2
- Return type:
float
References
Molter et al. 2019, doi:10.3847/1538-3881/ab258c
- pylanetary.rings.core.vector_ellipse(u, v, n, origin=array([0, 0, 0]))¶
Vector equation of an ellipse in two dimensions
- Parameters:
u (np.array, required) – shape (3,). vectorized semimajor axis, e.g. [a,0,0]
v (np.array, required) – shape (3,) vectorized semiminor axis, e.g. [0,b,0] should be perpendicular to u
n (int, required) – number of vectors to compute
origin (np.array, required) – shape (3,) vector pointing to the center of the ellipse
- Returns:
shape (n, 3) vectors pointing to the circumference of the ellipse
- Return type:
np.array
References
- pylanetary.rings.core.vector_magnitude(a)¶
magnitude of a vector this is a bit faster than using np.linalg.norm
- Parameters:
a (np.array, required) – shape (n, 3) or (n, 2) corresponding to n vectors
- Returns:
same shape as input, magnitude of input vector a
- Return type:
np.array
- pylanetary.rings.core.vector_normalize(v)¶
returns the original vector if it has length zero
- Parameters:
v (np.array, required) – shape (n, 3) or (n, 2) corresponding to n vectors
- Returns:
same shape as input. the normalized vectors
- Return type:
np.array