Improve SPICE pool, tour, trajectory and toolbox
Closes #15 (closed), #17 (closed), #35 (closed), #55 (closed), #66 (closed), #72 (closed), #73 (closed) and #74 (closed).
Add
- New HTML representation of
SpicePool
andMetaKernel
objects:
SpicePool.add(['naif0012.tls', 'pck00010.tpc'], purge=True)
SpicePool
Kernels | Type | Size |
---|---|---|
naif0012.tls |
|
5 kB |
pck00010.tpc | 🪐 PCK | 123 kB |
mk = Metakernel('juice_plan.tm', kernels='my_kernels/')
mk
📚 Meta-kernel for JUICE Dataset v423 -- Planning 20230309_001
This meta-kernel lists the JUICE Planning SPICE kernels
that provide information for the Planning scenario.
The kernels listed in this meta-kernel and the order in which
they are listed are picked to provide the best data available and
the most complete coverage for the JUICE Planning scenario.
This meta-kernel was generated with the Auxiliary Data Conversion
System version: ADCSng v3.6.7.
-------------------------------------------------------------------
Location:
../kernels/Juice/mk/juice_plan_v423_20230309_001.tm
SKD version:
v423_20230309_001
MK identifier:
juice_plan_v423_20230309_001
$KERNELS
../kernels/Juice/
Kernels | Type | Size |
---|---|---|
$KERNELS/ck/juice_sc_crema_5_1_150lb_23_1_default_v01.bc |
|
9 MB |
$KERNELS/ck/juice_sc_crema_5_1_150lb_23_1_comms_v01.bc |
|
2 MB |
... | ... | ... |
$KERNELS/spk/juice_orbc_000010_230414_310721_v03.bsp |
|
597 kB |
- New
.summary
and.details
properties ofSpicePool
andMetaKernel
objects:
SpicePool.summary
Types | Count | Size |
---|---|---|
|
1 | 5 kB |
🪐 PCK | 1 | 123 kB |
Total | 2 | 128 kB |
SpicePool.details # same as _repr_html_
Kernels | Type | Size |
---|---|---|
naif0012.tls |
|
5 kB |
pck00010.tpc | 🪐 PCK | 123 kB |
mk.summary
Types | Count | Size |
---|---|---|
|
12 | 95 MB |
|
10 | 1 MB |
|
35 | 212 MB |
|
14 | 540 kB |
|
1 | 5 kB |
🪐 PCK | 6 | 6 MB |
|
2 | 12 kB |
|
15 | 259 MB |
Total | 95 | 574 MB |
mk.details
Kernels | Type | Size |
---|---|---|
$KERNELS/ck/juice_sc_crema_5_1_150lb_23_1_default_v01.bc |
|
9 MB |
$KERNELS/ck/juice_sc_crema_5_1_150lb_23_1_comms_v01.bc |
|
2 MB |
... | ... | ... |
$KERNELS/spk/juice_orbc_000010_230414_310721_v03.bsp |
|
597 kB |
- New
file_size()
miscellaneous helper:
>>> from planetary_coverage.misc import file_size
>>> file_size('ck/juice_sc_crema_5_1_150lb_23_1_default_v01.bc')
'9 MB'
- Add new
SpiceFrame
reference object (created bySpiceRef
promotion):
>>> SpiceRef('J2000')
<SpiceFrame> J2000 (1)
>>> SpiceRef('IAU_GANYMEDE')
<SpiceFrame> IAU_GANYMEDE (10_025)
>>> SpiceRef('JUICE_SPACECRAFT')
<SpiceFrame> JUICE_SPACECRAFT (-28_000)
-
SpiceRef
object can now be hashed and return the hash of the SPICE name:
>>> hash(SpiceRef('GANYMEDE'))
8488306870234993416
>>> hash('GAMYMEDE')
8488306870234993416
They can be now be used as dict
keys and query with the name of the reference:
>>> ref = SpiceRef('GANYMEDE')
>>> data = {ref: 123}
>>> data['GANYMEDE']
data
-
SpicePool
now have a.brief()
method to list the temporal coverage of all the bodies in the pool (similar to NAIFbrief
utility):
>>> SpicePool.brief(fmt='TDB')
{
<SpiceSpacecraft> JUICE (-28): ('2023-04-05 12:41:33.336 TDB', '2035-10-05 01:58:58.683 TDB'),
<SpiceFrame> JUICE_SPACECRAFT (-28_000): ('2022-06-01 00:00:00.000 TDB', '2050-01-01 00:00:00.000 TDB'),
...
}
-
SpicePool
now have a.gaps()
method to list the coverage gaps intervals (#55 (closed)):
>>> SpicePool.gaps('JUICE_SPACECRAFT_PLAN', fmt='TDB')
[
['2023-11-21 01:29:11.998 TDB', '2024-10-31 02:29:45.998 TDB'],
['2024-08-21 08:19:33.998 TDB', '2026-09-27 23:49:02.998 TDB'],
['2024-11-04 08:34:55.998 TDB', '2027-11-20 19:56:45.998 TDB'],
...,
['2035-10-01 10:55:35.998 TDB', '2035-10-02 02:50:52.998 TDB'],
['2035-10-02 10:50:52.998 TDB', '2035-10-03 02:46:15.998 TDB'],
['2035-10-03 10:46:15.998 TDB', '2035-10-04 02:41:58.998 TDB']
]
The gaps are sorted by increasing start time. Multiple references can be provided at once.
- Add
.gaps()
method toTourConfig
object:
tour.gaps('JUICE_SPACECRAFT_PLAN', fmt='TDB')
t_start | t_end | |
---|---|---|
0 | 2023-11-21T01:28:02.816 | 2024-10-31T02:28:36.816 |
1 | 2024-08-21T08:18:24.816 | 2026-09-27T23:47:53.816 |
2 | 2024-11-04T08:33:46.816 | 2027-11-20T19:55:36.816 |
3 | 2026-09-28T23:47:53.816 | 2029-01-17T06:19:53.816 |
... | ... | ... |
Contrary to SpicePool
the result is an EventsList
. This allow the user the use theses gaps to filter any Trajectory object:
>>> traj ^ gaps
<MaskedSpacecraftTrajectory> Observer: JUICE | Target: JUPITER
- First UTC start time: 2023-06-01T00:00:00.000
- Last UTC stop time: 2025-01-01T00:00:00.000
- Nb of pts: 236 (+345 masked)
- Nb of segments: 2
- New
Trajectory.new_traj()
andTourConfig.new_tour()
methods to changespacecraft
,instrument
or/andtarget
(#74 (closed)):
new_traj = traj.new_traj(spacecraft=..., instrument=..., target=...)
new_tour = tour.new_tour(spacecraft=..., instrument=..., target=...)
This will ensure that these change are explicit and avoid name collisions.
Note: the Flyby
object can not change their target name.
- New
quaternions()
function in the SPICE toolbox:
>>> from planetary_coverage.spice import quaternions
>>> quaternions([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) # attitude matrix (3, 3) or (3, 3, N)
[1, 0, 0, 0]
- New
Trajectory.quaternions
property:
>>> traj.quaternions
- New
position_of()
anddistance_to()
methods toTrajectory
objects computed withtarget_position()
from SPICE toolbox based onspkpos
(#15 (closed)):
>>> traj.position_of('JUPITER')
>>> traj.distance_to('JUPITER')
>>> from planetary_coverage.spice.toolbox import target_position
>>> target_position('2032-01-01', 'JUICE', 'GANYMEDE')
- New
target_size
property andangular_size()
method toTrajectory
objects andangular_size()
method to SPICE toolbox (#15 (closed)):
>>> traj.target_size # Ganymede angular size (degrees) seen from Juice (main target)
>>> traj.angular_size('CALLISTO') # Callisto angular size (degrees) seen from Juice
>>> from planetary_coverage.spice.toolbox import angular_size
>>> angular_size('2033-01-01', 'JUICE', 'CALLISTO')
- New
ets_at()
andutc_at()
methods toTrajectory
objects to compute times at target with light-time correction:
>>> traj.ets_at('GANYMEDE')
>>> traj.utc_at('GANYMEDE')
- New
angle_between()
method toTrajectory
objects (see #15 (closed)):
>>> traj.angle_between('+Z', 'JUPITER') # Separation angle between the spacecraft +Z axis and JUPITER
- New
target_separation()
method toTrajectory
objects and SPICE toolbox based ontrgsep
(see #17 (closed)):
>>> traj.target_separation('CALLISTO') # Separation between the main trajectory target and Callisto
# or
>>> traj.target_separation('CALLISTO', 'IO') # Separation between the Callisto and Io
>>> from planetary_coverage.spice.toolbox import target_separation
>>> target_separation('2032-01-01', 'JUICE', 'GANYMEDE', 'CALLISTO', shape_1='SPHERE', shape_2='SPHERE')
- New
azel()
method to SPICE toolbox to convert vector in a reference frame into azimuth and elevation angles:
>>> from planetary_coverage.spice.toolbox import azel
>>> azel([[0, 0, 1, 1], [0, 1, 0, 1], [0, 0, 1, 1]])
[[0, 270, 0, 315], [0, 0, 45, 35.26]]
- New
station_azel()
method toTrajectory
objects and SPICE toolbox to compute the azimuth and elevation of a body in a tracking station reference frame (see #17 (closed)):
>>> traj.station_azel('MALARGUE') # Separation between the main trajectory target and Callisto
>>> from planetary_coverage.spice.toolbox import station_azel
>>> station_azel('2032-01-01', 'MALARGUE', 'JUICE')
- New
jd()
decimal Julian Date function to the SPICE module:
>>> from planetary_coverage.spice import jd
>>> jd('2023-08-10 00:05:09')
2_460_166.503_576
Changes
-
SpicePool.windows()
now returns the kernels temporal windows in adict
to keep track of the references and the kernels (#72 (closed)):
>>> SpicePool.windows('JUICE', fmt='TDB')
{
<SpiceSpacecraft> JUICE (-28): {
'spk/juice_crema_5_1_150lb_23_1_v01.bsp': [
['2023-04-05 12:41:33.336 TDB', '2035-10-05 01:58:58.683 TDB']
],
'spk/juice_orbc_000010_230414_310721_v03.bsp': [
['2023-04-14 12:41:15.336 TDB', '2031-07-21 22:52:32.230 TDB']
]
}
}
>>> SpicePool.windows('JUICE', 'GANYMEDE', fmt='UTC')
{
<SpiceSpacecraft> JUICE (-28): {
'spk/juice_crema_5_1_150lb_23_1_v01.bsp': array([
['2023-04-05T12:40:24.151', '2035-10-05T01:57:49.501']
], dtype='datetime64[ms]'),
'spk/juice_orbc_000010_230414_310721_v03.bsp': array([
['2023-04-14T12:40:06.151', '2031-07-21T22:51:23.047']
], dtype='datetime64[ms]'),
},
<SpiceBody> GANYMEDE (503): {
'spk/jup365_19900101_20500101.bsp': array([
['1990-01-01T00:00:00.000', '2050-01-01T06:00:00.000']
], dtype='datetime64[ms]'),
'spk/noe-5-2017-gal-a-reduced_20200101_20380902.bsp': array([
['2020-01-01T00:00:00.000', '2038-09-02T06:00:00.000']
], dtype='datetime64[ms]'),
},
}
-
SpicePool.coverage()
is now computed per reference and not globally (#72 (closed)):
>>> SpicePool.coverage('JUICE', 'GANYMEDE', fmt='TDB')
('2023-04-05 12:41:33.336 TDB', '2035-10-05 01:58:58.683 TDB')
instead of
('2023-04-14 12:41:15.337 TDB', '2031-07-21 22:52:32.230 TDB')
with the previous method. This is now consistent with NAIF to be consistent with NAIF brief
utility:
brief juice_plan.tm -t -a
BRIEF -- Version 4.1.0, September 17, 2021 -- Toolkit Version N0067
Summary for all files.
Bodies Start of Interval (ET) End of Interval (ET)
------- ----------------------------- -----------------------------
-28 JUICE 2023 APR 05 12:41:33.336 2035 OCT 05 01:58:58.683
- SPICE
attitude()
now returns the C-matrix and not the transpose of the C-matrix:
from planetary_coverage.spice import attitude
attitude(et, 'JUICE_SPACECRAFT')
It also correspond to matrix rotation from J2000 reference frame to the spacecraft or instrument frame.
-
Trajectory.attitude
property also reflect this change. -
SpiceBody
,SpiceSpacecraft
andSpiceInstrument
now returns aSpiceFrame
instead of astr
:
>>> SpiceBody('GANYMEDE').frame
<SpiceFrame> IAU_GANYMEDE (10_025)
-
SpiceRef
object don't displayID:
in their representation:
>>> repr(SpiceRef('JUICE'))
JUICE (-28) # instead of `JUICE (ID: -28)` before
to be consistent with NAIF brief representation.
-
Simplify
tdb()
method on iterable and add explicitdtype
. -
Refactor SPICE toolbox iterative method to improve performance by 4 to 40%:
Fixed
-
Groundtrack velocity formula:
np.sqrt(r**2 * ((vlon * np.cos(lat)) ** 2 + vlat**2))
instead ofnp.sqrt(r**2 * ((vlon * np.cos(lat)) ** 2 + vlat**2) + vr**2)
(#35 (closed)) -
Fix
ax.twin_colorbar()
representation issue:
-
Trajectory
object now clears its cache properties if thetarget
or theobserver
is changes (#74 (closed)):
>>> traj.target
'GANYMEDE'
>>> traj.dist
[1, 2, 3, ...]
>>> traj.target = 'Europa'
>>> traj.target
'EUROPA'
>>> traj.dist
[4, 5, 6, ...]
Depreciated
-
Trajectory.sc_attitude
property is depreciated in favor ofTrajectory.attitude
. - Deprecate
traj['SPACECRAFT']
,traj['INSTRUMENT']
andtraj['TARGET']
syntax in favor oftraj.new_traj()
. - Deprecate
traj['SUN']
andtraj['SS']
syntax in favor oftraj.ss
ortraj.sun_pos
.
Removed
- Remove
limb_ip_pt()
method in favor of SPICE nativetangpt
inintersect_pt()
method (#17 (closed)). -
__getitem()__
method toMaskedTrajectory
andSegmentedTrajectory
objects (#29) to avoid to changetarget
orobserver
properties without clearing the properties cache. AReferenceError
is now raises to encourage the user to edit the parent trajectory properties directly:
>>> mask_traj['MAJIS_IR']
ReferenceError: 'Change of target or observer should be performed on the original trajectory not on the masked trajectory.'