SPICE References#
Object references in the SPICE kernels are usually represented either by their name (which is not always unique) or by an internal id
code. Most of the time, the user does not have to know the reference id
and can pass directly its name to the function but it’s not always the case. To provide a simpler access to the SPICE references, the planetary-coverage
provides a SpiceRef
object that will extract the correct information from the SpicePool
.
from planetary_coverage import SpiceRef
For example, for Jupiter barycenter
we have:
Note
If the reference is not known, a spiceypy
error will be thrown with an additional ValueError
:
>>> SpiceRef('FOO')
...
NotFoundError: Spice returns not found for function: bods2c
...
ValueError: Unknown reference: `FOO`
ref = SpiceRef('Jupiter Barycenter')
ref
<SpiceRef> JUPITER BARYCENTER (5)
Generic SpiceRef
properties#
This reference can be used either as a string to get its name
property:
str(ref)
'JUPITER BARYCENTER'
or as an integer to get its id
property:
int(ref)
5
You can compare a SpiceRef
with its string and integer values:
ref == 'JUPITER BARYCENTER'
True
ref == 5
True
If a reference frame is available for this object you can use the .frame
property to query it:
ref.frame
<SpiceFrame> IAU_JUPITER_BARYCENTER (10_005)
Similarly to the SpicePool
, you can query the values from the pool directly on the SpiceRef
object:
Warning
By default, the value is not specific to the SpiceRef
, any value in the SpicePool
is accessible.
ref['BODY599_RADII']
[71492.0, 71492.0, 66854.0]
SpiceBody
properties#
If the SpiceRef
is a planet or a satellite (like for Ganymede
), the SpiceRef
is promoted to a SpiceBody
.
body = SpiceRef('Ganymede')
body
<SpiceBody> GANYMEDE (503)
For a SpiceBody
, you have access to additional attributes. For example, the body radii
values:
body.radii # [km]
[2631.2, 2631.2, 2631.2]
its geometric-mean radius:
body.radius # [km]
2631.2000000000003
or its centered body-fixed frame:
body.frame
<SpiceFrame> IAU_GANYMEDE (10_025)
For a SpiceBody
, the item getter is prefix with BODYXXX_
with XXX
being the body code. Therefore you can do:
body['GM'] # Alias to `BODY503_GM`
9887.834453334144
SpiceSpacecraft
properties#
If you select a spacecraft reference, it will be promoted to a SpiceSpacecraft
:
sc = SpiceRef('JUICE')
sc
<SpiceSpacecraft> JUICE (-28)
SpiceSpacecraft
includes a frame
and boresight
attributes:
sc.frame
<SpiceFrame> JUICE_SPACECRAFT (-28_000)
sc.boresight
array([0, 0, 1])
You can also access the list of the spacecraft instruments available in the SPICE pool:
sc.instruments
[<SpiceInstrument> JUICE_HGA_X (-28_021),
<SpiceInstrument> JUICE_HGA_KA (-28_022),
<SpiceInstrument> JUICE_NAVCAM-1 (-28_051),
<SpiceInstrument> JUICE_NAVCAM-2 (-28_052),
<SpiceInstrument> JUICE_STR-OH1 (-28_061),
<SpiceInstrument> JUICE_STR-OH2 (-28_062),
<SpiceInstrument> JUICE_STR-OH3 (-28_063),
<SpiceInstrument> JUICE_SCHULTE_KA_BAND (-28_075),
<SpiceInstrument> JUICE_SCHULTE_X_BAND (-28_076),
<SpiceInstrument> JUICE_JMC-1 (-28_081),
<SpiceInstrument> JUICE_JMC-2 (-28_082),
<SpiceInstrument> JUICE_GALA_TXL_MAIN (-28_111),
<SpiceInstrument> JUICE_GALA_TXL_RED (-28_112),
<SpiceInstrument> JUICE_GALA_RXT (-28_120),
<SpiceInstrument> JUICE_JANUS (-28_200),
<SpiceInstrument> JUICE_MAJIS_VISNIR (-28_410),
<SpiceInstrument> JUICE_MAJIS_VISNIR_B2 (-28_412),
<SpiceInstrument> JUICE_MAJIS_VISNIR_B4 (-28_414),
<SpiceInstrument> JUICE_MAJIS_IR (-28_420),
<SpiceInstrument> JUICE_MAJIS_IR_B2 (-28_422),
<SpiceInstrument> JUICE_MAJIS_IR_B4 (-28_424),
<SpiceInstrument> JUICE_MAJIS_RAD (-28_430),
<SpiceInstrument> JUICE_MAJIS_ENVELOPE (-28_440),
<SpiceInstrument> JUICE_PEP_JDC (-28_510),
<SpiceInstrument> JUICE_PEP_JNA (-28_520),
<SpiceInstrument> JUICE_PEP_NIM_NEUION_S0 (-28_532),
<SpiceInstrument> JUICE_PEP_NIM_NEUION_S1 (-28_533),
<SpiceInstrument> JUICE_PEP_NIM_NEUION_S2 (-28_534),
<SpiceInstrument> JUICE_PEP_NIM_NEUION_S3 (-28_535),
<SpiceInstrument> JUICE_PEP_NIM_NEUION_S4 (-28_536),
<SpiceInstrument> JUICE_PEP_NIM_NEUION_S5 (-28_537),
<SpiceInstrument> JUICE_PEP_NIM_THERMAL-1 (-28_538),
<SpiceInstrument> JUICE_PEP_NIM_THERMAL-2 (-28_539),
<SpiceInstrument> JUICE_PEP_JEI (-28_540),
<SpiceInstrument> JUICE_PEP_JOEE_S1 (-28_551),
<SpiceInstrument> JUICE_PEP_JOEE_S2 (-28_552),
<SpiceInstrument> JUICE_PEP_JENI (-28_560),
<SpiceInstrument> JUICE_PEP_JENI_PY (-28_561),
<SpiceInstrument> JUICE_PEP_JENI_MY (-28_562),
<SpiceInstrument> JUICE_RIME_BASE (-28_600),
<SpiceInstrument> JUICE_RIME+X (-28_601),
<SpiceInstrument> JUICE_SWI_FULL (-28_800),
<SpiceInstrument> JUICE_SWI_FULL_GCO500 (-28_801),
<SpiceInstrument> JUICE_SWI_CH1 (-28_810),
<SpiceInstrument> JUICE_SWI_CH2 (-28_820),
<SpiceInstrument> JUICE_UVS_AP_HP (-28_860),
<SpiceInstrument> JUICE_UVS_SP (-28_870),
<SpiceInstrument> JUICE_RADEM_ESD (-28_921),
<SpiceInstrument> JUICE_RADEM_PSD (-28_922),
<SpiceInstrument> JUICE_RADEM_HISD (-28_923)]
or select a single one:
inst = sc.instr('JANUS')
inst
<SpiceInstrument> JUICE_JANUS (-28_200)
SpiceInstrument
properties#
When an instrument is selected (as a SpiceInstrument
), you can get its field of view parameters:
inst.boresight
array([0., 0., 1.])
inst.bounds
array([[-0.01500832, 0.01125587, 0.99982401],
[-0.01500832, -0.01125587, 0.99982401],
[ 0.01500832, -0.01125587, 0.99982401],
[ 0.01500832, 0.01125587, 0.99982401]])
inst.shape
'RECTANGLE'
inst.frame
<SpiceFrame> JUICE_JANUS (-28_200)
You can also retrieve the detector size:
inst.ns, inst.nl
(1504, 2000)
or the full field-of-view along the track and cross track:
inst.fov_along_track, inst.fov_cross_track # in radians
(0.022514747350726852, 0.030019663134302467)
Caution
We assume that the sample direction is aligned with the cross-track direction (ie. 1-line acquisition in push-broom mode should be in the direction of flight).
This convention is not strictly enforced in the instrument kernel and the user must be careful and adjust theses values according to the detector orientation relative to the spacecraft motion.
Warning
JUICE_JANUS
instrument in v06
does not follow this convention.
We manually manage this exception for the moment (see
MR !27
for more details).
as well as the pixel instantaneous field-of-view:
inst.ifov_along_track, inst.ifov_cross_track # in radians
(1.4969911802344982e-05, 1.5009831567151233e-05)
For a SpiceInstrument
, the item getter is prefix with INSXXX_
with XXX
being the instrument code. Therefore you can do:
inst['PIXEL_SAMPLES'] # Alias to `INS-28200_PIXEL_SAMPLES`
1504.0
You can display the boresight
, the bounds
vectors and rays
of the field of view contour in the instrument frame:
inst.display();

Or you can represent it in the plane orthogonal to the field of view:
inst.view();

SpiceFrame
properties#
If the SpiceRef
is a SPICE frame, the SpiceRef
is promoted to a SpiceFrame
:
frame = SpiceRef('JUICE_SPACECRAFT_PLAN')
frame
<SpiceFrame> JUICE_SPACECRAFT_PLAN (-28_001)
You can retrieve the type of frame:
frame.class_type
'CK frame'
The frame body center:
frame.center
<SpiceFrame> JUICE_SPACECRAFT (-28_000)
and when available, the associated sclk
and spk
:
frame.sclk
<SpiceFrame> JUPITER_SYSTEM3RH_1965 (-28_999)
frame.spk
<SpiceSpacecraft> JUICE (-28)
Danger
SPICE codes can overlap SPICE frame ids. For example here, both MERCURY_BARYCENTER
and J2000
frame have an id
of 1
. It is recommend to be very carefull with theses cases and use explicit names:
SpiceRef('MERCURY_BARYCENTER')
<SpiceRef> MERCURY BARYCENTER (1)
SpiceRef('J2000')
<SpiceFrame> J2000 (1)
Planetocentric vs. planetocentric coordinates#
Recommended reading: NAIF reference frames and coordinates system
Planetocentric coordinates#
NAIF definition:
For planets and their satellites the +Z
axis (+90
latitude) always points
to the north side of the invariable plane (the plane whose normal vector is
the angular momentum vector of the solar system):
Planetocentric longitude increases positively eastward (-180° to +180°)
Planetocentric latitude increases positively northward (-90° to +90°)

Note
In the planetary-coverage
, the planetocentric longitudes are defined as strictly positive eastward ([0°, 360°[
).
Planetographic coordinates#
NAIF definition:
For planet and satellite planetographic coordinate systems:
Planetographic longitude is usually defined such that the sub-observer longitude increases with time as seen by a distant, fixed observer (0° to 360°)
The Earth, Moon and Sun are exceptions; planetographic longitude is positive east by default (0° to 360°)
Planetographic latitude is planetodetic latitude (-90° to +90°), ie. is tied to a reference ellipsoid and for a point, P, on a reference ellipsoid, the angle measured from the X-Y plane to the surface normal at the point of interest. For points not on the ellipsoid, equals latitude at the nearest point on the reference ellipsoid and increases positively northward.

Planetographic to Planetocentric coordinates.#
Warning
Depending on the body, the output will be either in east or in west longitude.
It is possible to convert planetographic coordinates to planetographic coordinates with the ocentric2ographic()
function:
Note
This calculation requires that a tpc
kernel is loaded into the SPICE pool.
from planetary_coverage.spice import ocentric2ographic
lon_w, lat = ocentric2ographic('MARS', 90, 45) # east longitude, latitude
lon_w, lat # west longitudes for MARS
(270.0, 45.33789641791753)