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

https://math.stackexchange.com/questions/3994666/parametric-equation-of-an-ellipse-in-the-3d-space#:~:text=In%20the%20parametric%20equation%20x,a%20point%20with%20minimum%20curvature.

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