Navigation API

class pylanetary.navigation.core.ModelBody(body, pixscale, shape=None)

Wrapper to ModelEllipsoid that permits passing an ephemeris

Parameters:
  • body (pylanetary.utils.Body object, required)

  • pixscale (float or Quantity, required.) – [arcsec/px] pixel scale of the input image

  • shape (tuple, optional.) – shape of output arrays. if None, shape is just larger than diameter / pixscale

body

see parameters

Type:

pylanetary.utils.Body object

name

Name of input body as read from input Body object

Type:

str

ephem

single line of astroquery.horizons ephemeris as read from utils.Body object. must have ‘PDObsLon’, ‘PDObsLat’, ‘delta’, and ‘NPole_ang’ fields. If you want to modify the ephemeris, modify body.ephem

Type:

Astropy QTable.

pixscale_arcsec

[arcsec/px] pixel scale of image; see parameters

Type:

float

pixscale_km

[km/px] pixel scale of image computed from input pixel scale in arcsec and distance from object to body according to body.ephem

Type:

float

all attrs from ModelEllipsoid
class pylanetary.navigation.core.ModelEllipsoid(ob_lon, ob_lat, pixscale_km, np_ang, req, rpol, center=(0.0, 0.0), shape=None, sun_lon=None, sun_lat=None, longitude_convention='w')

Projection of an ellipsoid onto a 2-D array with latitude and longitude grid

Parameters:
  • ob_lon (float, required.) – [deg] sub-observer planetographic longitude

  • ob_lat (float, required.) – [deg] sub-observer planetographic latitude

  • np_ang (float, required.) – [deg] north polar angle see JPL Horizons ephemeris tool for detailed descriptions of ob_lon, ob_lat, np_ang

  • pixscale_km (float, required.) – [km] pixel scale

  • req (float, required.) – [km] equatorial radius

  • rpol (float, required.) – [km] polar radius

  • center (2-element array-like, optional, default (0,0).) – pixel offset of center of planet from center of image

  • shape (2-element tuple, optional.) – shape of output arrays. if None, shape is just larger than diameter / pixscale

  • sun_lon (float, optional, default None) – sub-solar longitude. if None, assume same as ob_lon

  • sun_lat (float, optional, default None) – sub_solar latitude. if None, assume same as ob_lat

  • longitude_convention (str, optional, default 'w') – east or west longitude convention

req

see parameters

Type:

float

rpol

see parameters

Type:

float

ob_lon

see parameters

Type:

float

ob_lat

see parameters

Type:

float

sun_lon

see parameters

Type:

float

sun_lat

see parameters

Type:

float

pixscale_km

see parameters

Type:

float

deg_per_px

approximate size of pixel on planet, in degrees, at sub-observer point

Type:

float

lat_g

shape is roughly 2*max(req, rpol)/pixscale. planetographic latitudes. NaN where off planet disk

Type:

np.array

lon_w

same shape as lat_g. west longitudes. NaN where off planet disk

Type:

np.array

mu

same shape as lat_g. cosines of the emission angle. NaN where off planet disk

Type:

np.array

surf_n

shape (3,x,y) CHECK THIS. Normal vector to the surface of the planet at each pixel. NaN where off planet disk

Type:

np.array

sun_n

shape (3,x,y), solar normal vectors

Type:

np.array

mu0

shape (x,y), cosine of solar incidence angle at each pixel

Type:

np.array

image_grid_km_x

shape (x,y), x-coordinates of image grid in km, where 0 is center of planet

Type:

np.array

image_grid_km_y

shape (x,y), y-coordinates of image grid in km, where 0 is center of planet

Type:

np.array

Examples

see notebooks/planetnav-tutorial.ipynb

ldmodel(tb, a, beam=None, law='exp', mu0=None, psf_mode='gaussian')

Make a limb-darkened model disk convolved with the beam See docstring of limb_darkening() for options

Parameters:
  • tb (float, required.) – [flux] brightness temperature of disk at mu=1

  • a (float or tuple, required.) – [-] limb darkening parameter(s)

  • beam (float or tuple or np.array) – units pixels. see docstring of utils.convolve_with_beam

  • law (str, optional, default "exp") – limb darkening law

  • mu0 (np.array, optional, default None) – cosine of solar incidence angle. if None, code will check if self.mu0 is defined, and use that has no effect unless law==”minnaert”. if self.mu0 undefined, law==”minnaert”, and mu0=None, then code will fail

  • psf_mode (str, optional, default "gaussian") – mode to use for convolve_with_beam(), options “airy”, “gaussian”

zonalmodel(lons, tbs, a=0.0)
class pylanetary.navigation.core.Nav(data, body, pixscale)

Build the model body object, and compare a model ellipsoid with observed 2-d imaging data

Parameters:
  • data (np.array, required.) – 2-D image data

  • body (pylanetary.utils.Body object, required.)

  • pixscale (float or Quantity, required.) – [arcsec] pixel scale of the input image

data

see parameters

Type:

np.array

parent_attrs

all attributes of ModelBody and ModelEllipsoid classes

Examples

see notebooks/nav-tutorial.ipynb

Notes

  • Need to test astropy quantity handling, ensure docstring reflects what really happens

colocate(mode='convolution', diagnostic_plot=True, save_plot=None, **kwargs)

Co-locate the model planet with the observed planet

Parameters:
  • mode (str, optional. Default 'convolution'.) –

    Which method should be used to overlay planet model and data. Choices are:

    • ’canny’: uses the Canny edge detection algorithm.
      kwargs:
      tb:

      float, required. [same flux unit as data] brightness temperature of disk at mu=1

      a:

      float, required. [-] exponential limb darkening param

      law:

      str, optional. default ‘exp’ type of limb darkening model to use

      beam:

      float, tuple, or np.array, optional. default None. units pixels. see utils.convolve_with_beam

      psf_mode:

      str, optional. default “gaussian” what beam shape to use, options “airy”, “gaussian”

      low_thresh:

      float, required. see documentation of skimage.feature.canny

      high_thresh:

      float, required. see documentation of skimage.feature.canny

      sigma:

      int, required. see documentation of skimage.feature.canny

      To find edges of planet disk, typical “good” values are:

      low_thresh : RMS noise in image high_thresh : approximate flux value of background disk (i.e., cloud-free, volcano-free region) sigma : 5

    • ’convolution’: takes the shift that maximizes the convolution of model and planet
      kwargs:
      tb:

      float, required. [same flux unit as data] brightness temperature of disk at mu=1

      a:

      float, required. [-] limb darkening parameter

      law:

      str, optional. default ‘exp’ type of limb darkening model to use

      beam:

      float, tuple, or np.array, optional. default None. units pixels. see utils.convolve_with_beam

      psf_mode:

      str, optional. default “gaussian” what beam shape to use, options “airy”, “gaussian”

      err:

      float per-pixel error in input image

    • ’disk’: same as convolution

  • diagnostic_plot (bool, optional. default True) – do you want the diagnostic plots to be shown

  • save_plot (str, optional. default None.) – file path to save the diagnostic plot. if None, does not save.

Returns:

  • float – dx in pixels. best-fit difference in position between model and data To shift data to center (i.e., colocated with model), apply a shift of -dx, -dy To shift model to data, apply a shift of dx, dy

  • float – dy in pixels

  • float – dxerr in pixels uncertainty in the shift based on the cross-correlation from image_registration.chi2_shift. These should be treated with extreme caution because they were designed to work on identical images corrupted by random noise, and are being used for non-identical images (model and data)

  • float – dyerr in pixels

Examples

need at least one example of each mode here

Notes

  • sometimes dxerr, dyerr give unrealistic or undefined behavior

reproject(projection='equirectangular', shape=None)

Projects the navigated data into the target projection This function only works properly if self.lat_g and self.lon_w are centered with respect to self.data; for instance, if ONE of xy_shift_data or xy_shift_model has been applied using the dx, dy output of colocate()

Parameters:
  • projection (str or cartopy.proj.Projection instance, optional. default 'equirectangular') – string options are [‘equirectangular’, ‘polar’] Equirectangular, AKA rectilinear, projection results in pixels equally spaced in latitude and longitude Polar projection will be applied on whichever pole is closest to the sub-observer latitude any cartopy Projection object is also accepted, but in this case shape must be specified see cartopy projection list.

  • shape (tuple, optional. default None) – shape of output arrays. if None, shape is guessed from pixel scale of input image

Returns:

  • np.array – the projected data

  • np.array – cosine of the emission angle (mu) at each pixel in the projection

write(outstem, header={}, flux_unit='')

Writes navigated data to multi-extension fits

Parameters:
  • outstem (str, required.) – stem of filenames to write

  • header (dict, optional, default {}) – dictionary of header info to put into hdul[0].header

  • flux_unit (str, optional, default "") – unit of flux to put in output fits header

  • Writes

  • ------

  • file (fits)

Notes

hdul[0] contains the header, data is empty hdul[1] contains the data hdul[2] contains latitudes hdul[3] contains longitudes hdul[4] contains emission angles hdul[5] contains solar incidence angles

References

NAV multi-extension fits file format originally pioneered by Mike Wong e.g. https://doi.org/10.3847/1538-4365/ab775f

xy_shift_data(dx, dy)

FFTshift data by a user-defined amount for example, to apply the suggested shift from colocate() it is preferred to use xy_shift_model() instead, which avoids touching the data

Parameters:
  • dx (float, required) – [pixels] shift in x

  • dy (float, required) – [pixels] shift in y

xy_shift_model(dx, dy)

shift model (i.e., lat_g, lon_w, mu, and mu0) by recalculating the model with a different center as defined by user-defined dx, dy shift

Parameters:
  • dx (float, required) – [pixels] shift in x

  • dy (float, required) – [pixels] shift in y

pylanetary.navigation.core.colocate_diagnostic_plot(model, data, mode)

assesses goodness-of-fit of navigation solution from colocate

Parameters:
  • model (np.array, required) – shifted model data

  • data (np.array, required) – observed data

  • mode (str, required) – method of co-location, one of [“canny”, “convolution”, or “disk”]

Returns:

matplotlib figure and axis objects

Return type:

fig, ax

pylanetary.navigation.core.emission_angle(ob_lat, surf_n)

Computes the cosine of the emission angle of surface wrt observer

Parameters:
  • ob_lat (float or np.array, required.) – [deg] sub-observer latitude

  • surf_n (np.array, required.) – [x,y,z] surface normal vector at each ob_lat

Returns:

cosine of emission angle

Return type:

float or np.array

pylanetary.navigation.core.lat_lon(shape, pixscale_km, ob_lon, ob_lat, np_ang, r_e, r_p, dx=0, dy=0, longitude_convention='w')

Computes the planetographic and planetocentric latitudes and west longitudes of an ellipsoidal planet as viewed from a tilted perspective, i.e., on the sky For now, this relies on manually de-rotating the planet and using Cartopy’s orthographic projection, because pyproj TiltedPerspective cannot handle ellipsoidal planets, only spheres.

Parameters:
  • shape (tuple, required) – shape of output arrays

  • pixscale_km (float, required) – [km/px] pixel scale of image

  • ob_lon (float, required) – [deg] sub-observer planetographic longitude

  • ob_lat (float, required) – [deg] sub-observer planetographic latitude

  • np_ang (float, required) – [deg] north polar angle

  • r_e (float, required) – [km] equatorial radius of planet

  • r_p (float, required) – [km] polar radius of planet

  • dx (float, optional, default 0) – [px] offset in x from the center of the image

  • dy (float, optional, default 0) – [px] offset in y from the center of the image

  • longitude_convention (str, optional, default 'w') – east or west longitude convention

Returns:

  • np.array – planetographic latitudes

  • np.array – planetocentric latitudes

  • np.array – West longitudes

  • np.array – x-coordinates of image grid in km, where 0 is center of planet

  • np.array – y-coordinates of image grid in km, where 0 is center of planet

pylanetary.navigation.core.limb_darkening(mu, a, law='exp', mu0=None)
Parameters:
  • mu (float or array-like, required.) – [-] cosine of emission angle

  • a (float or array-like, required.) – [-] limb-darkening parameter(s) if law==”disc”, a is ignored if law==”exp”, “linear”, or “minnaert”, a must have length 1 if law==”quadratic”, “square-root”, a must have length 2 such that [a0, a1] are the free parameters in the first and second terms, respectively.

  • law (str, optional. default "exp".) – what type of limb darkening law to use. options are: disc : no limb darkening applied linear : ld = 1 - a * (1 - mu) exp : ld = mu**a minnaert : ld = mu0**a * mu**(a-1) quadratic : ld = 1 - a[0]*(1-mu) - a[1]*(1-mu)**2 square-root : ld = 1 - a[0]*(1-mu) - a[1]*(1-np.sqrt(mu))

  • mu0 (float or array-like, optional. default None.) – [-] cosine of solar incidence angle. has no effect unless law==”minnaert”, in which case it is required.

Returns:

limb-darkening value at each input mu value

Return type:

float or np.array

References

Overview of published limb darkening laws https://www.astro.keele.ac.uk/jkt/codes/jktld.html

pylanetary.navigation.core.rotate_about_pivot(img, angle, pivot)
Parameters:
  • img (np.array, required) – image to rotate

  • angle (float, required) – [deg] angle to rotate image (counterclockwise)

  • pivot (tuple, required) – [px] (x,y) coordinates of pivot point about which to rotate image

Returns:

rotated image

Return type:

np.array

pylanetary.navigation.core.surface_normal(lat_g, lon_w, ob_lon)

Computes the normal vector to the surface of the planet. Take dot product with sub-obs or sub-sun vector to find cosine of emission angle

Parameters:
  • lat_g (np.array, required) – [deg] planetographic latitude

  • lon_w (np.array, required) – [deg] west longitude

  • ob_lon (float, required) – [deg] sub-observer (or sub-sun) planetographic longitude

Returns:

[x,y,z] normal vector to the surface of the planet

Return type:

np.array