Skip to content

Add support for mission events from the SPICE pool

Benoit Seignovert requested to merge pool-mission-events into main

Since January 2023, the Juice mission metakernels contains a fk kernel to host event based fields (see #69 (closed)). This MR implement a wrapper around them to load these events from the SpicePool to allow the user to query event based trajectories without requiring external event files.

  • Load phases and timeline events can be retrieved directly from the TourConfig object:
tour = TourConfig(mk='5.1 150lb_23_1', spacecraft='JUICE', target='Ganymede', version='v422_20230130_002')

tour.phases
event # t_start t_stop
0 Approach and first ellipse - 2031-01-19 2032-02-08
1 All Jupiter phases - 2031-01-19 2034-12-19
2 All mission phases - 2031-01-19 2035-09-29
3 Energy reduction - 2032-02-08 2032-06-25
4 Europa flybys - 2032-06-25 2032-07-24
5 High-latitude - 2032-07-24 2033-08-18
6 Low energy - 2033-08-18 2034-12-19
7 GEOa - 2034-12-19 2035-01-17
8 All Ganymede phases - 2034-12-19 2035-09-29
9 GCO5000 - 2035-01-17 2035-04-16
10 GEOb - 2035-04-16 2035-05-13
11 TGCO - 2035-05-13 2035-05-21
12 GCO500 - 2035-05-21 2035-09-29
tour.timeline
event # t_start t_stop
0 FLYBY_GANYMEDE 12 2031-07-21 2034-11-18
1 PERIJOVE 67 2031-07-21 2034-12-18
2 APOJOVE 66 2031-11-02 2034-12-13
3 FLYBY_CALLISTO 21 2032-06-21 2034-06-24
4 FLYBY_EUROPA 2 2032-07-02 2032-07-16
  • As regular events, they can be filtered by key:
tour.timeline['FLYBY_GANYMEDE']
Crema name event time [utc]
0 1G1 2031-07-21T07:13:28
1 2G2 2032-02-13T23:03:55
2 3G3 2032-04-11T04:14:51
3 4G4 2032-05-09T18:34:53
4 5G5 2032-06-02T21:30:44
5 26G6 2033-11-27T06:22:15
6 27G7 2034-01-14T18:38:56
7 30G8 2034-06-06T06:53:05
8 32G9 2034-07-12T07:50:48
9 33G10 2034-09-07T18:03:38
10 34G11 2034-09-29T06:48:32
11 35G12 2034-11-18T21:58:51
tour.timeline['FLYBY_GANYMEDE']['1G1']
Crema name 1G1
event time [utc] 2031-07-21T07:13:28
tour.timeline['PERIJOVE']['12PJ']
Crema name 12PJ
event time [utc] 2032-09-24T21:33:36
  • You can also query the event(s) with get_event() (recommended method):
tour.get_event('GCO5000')         # EventWindow from the phases
tour.get_event('FLYBY_GANYMEDE')  # EventsList from the timeline
tour.get_event('1G1')             # Event found from the event names in the timeline
  • It no fk is loaded or if the event key is not present, an KeyError will be raised:
>>> tour.get_event('FOO')
KeyError: 'Unknown event `FOO`'
  • It can also be used to query a trajectory based on an Event or an EventWindow:
>>> tour['GCO5000']
<SpacecraftTrajectory> Observer: JUICE | Target: GANYMEDE
 - UTC start time: 2035-01-17T03:00:00.000
 - UTC stop time: 2035-04-16T16:00:00.000
 - Nb of pts: 128,942

By default, the tour.default_time_step is used (1 min), but you can provide your own time_step:

>>> tour['GCO5000':'1 day']
<SpacecraftTrajectory> Observer: JUICE | Target: GANYMEDE
 - UTC start time: 2035-01-17T03:00:00.000
 - UTC stop time: 2035-04-16T16:00:00.000
 - Nb of pts: 91

Note: If you query a list of single events (from an EventsList for example) you will only get these events:

>>> tour['FLYBY_GANYMEDE']
<SpacecraftTrajectory> Observer: JUICE | Target: GANYMEDE
 - UTC start time: 2031-07-21T07:13:28.000
 - UTC stop time: 2034-11-18T21:58:51.000
 - Nb of pts: 12

(see comment below about a proposal to improve the event query pattern).

If you need to get all the flybys for a given target you should use:

>>> tour.flybys
{'1G1': <SpacecraftFlyby> Observer: JUICE | Target: GANYMEDE
  - Altitude at CA: 400.0 km
  - UTC at CA: 2031-07-21T07:08:09
  - Duration: 1 day, 0:00:00
  - Nb of pts: 2,041,
 '2G2': <SpacecraftFlyby> Observer: JUICE | Target: GANYMEDE
  - Altitude at CA: 400.0 km
  - UTC at CA: 2032-02-13T23:03:55
  - Duration: 1 day, 0:00:00
  - Nb of pts: 2,041,
...
 '35G12': <SpacecraftFlyby> Observer: JUICE | Target: GANYMEDE
  - Altitude at CA: 31,796.8 km
  - UTC at CA: 2034-11-18T21:58:52
  - Duration: 1 day, 0:00:00
  - Nb of pts: 2,041}

Note: this method use FLYBY_<TARGET> events list and don't perform a global search. It also return a dict with the flyby names, instead of a regular list (like when no fk is provided).

  • The based min altitude for the flybys search is now increased to 150,000 km (vs. 25,000 km previously). This change is required to include the last Ganymede high altitude flybys (above 100,000 km).

  • You can select a single flyby with its key now:

>>> tour.flyby('1G1')
<SpacecraftFlyby> Observer: JUICE | Target: GANYMEDE
 - Altitude at CA: 400.0 km
 - UTC at CA: 2031-07-21T07:08:09
 - Duration: 1 day, 0:00:00
 - Nb of pts: 2,041
  • As a bonus, you can also inspect the fk event file like this:
TourConfig(kernels='events.tf').timeline
# or
TourConfig(kernels='events.tf').get_event('1G1')

Additional implementations

  • Add wildcard string and character to SPICE pool item getter:
>>> SpicePool['JUICE_MISSION_PHASE_ST%%']
['JUICE_MISSION_PHASE_STOP',
 'JUICE_MISSION_PHASE_STRT']

>>> SpicePool['*_MISSION_*']
['JUICE_MISSION_PHASE_DESC',
 'JUICE_MISSION_PHASE_NAME',
 'JUICE_MISSION_PHASE_STOP',
 'JUICE_MISSION_PHASE_STRT']
  • Fix max elements getter from the SPICE pool (limited to 1,000 previously)

  • Add single time keyword input to Event constructor:

Event('foo', name='bar', time='2023-05-11')
name bar
time 2023-05-11
  • Fix ESA API tag with short name now return the latest tag when multiple tag were available:
>>> get_tag('juice', 'v422')
'v422_20230130_002'  # instead of 'v422_20230130_001' previously
  • Bump documentation and example crema to 5.1 150lb 23.1 at v422_20230130_002.

Closes #69 (closed)

Edited by Benoit Seignovert

Merge request reports