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