MAJIS OPL reader, exporter and convertor#
from majis import read_opl, save_opl
Juice observation plan files (OPL) come with two flavors, a legacy one in plain text file in CSV format and a new one in JSON format.
The CSV only contains an observation key, the start and end times, the observation name and the name of the instrument:
# obs_key, start, end, bane, instrument
MAJIS_PRIME_OBSERVATION,2032-12-19T07:10:47Z,2032-12-19T07:19:32Z,MAJ_JUP_DISK_SCAN_ORB17_DES0001,MAJIS
MAJIS_PRIME_OBSERVATION,2032-12-19T07:30:36Z,2032-12-19T07:45:00Z,MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001,MAJIS
Note: The OPL CSV header is often missing.
In the case of the JSON format, a JSON schema is defined by the JUICE SOC here. For example:
{
"header": {
"filename": "OPL_example.json",
"creation_date": "2026-01-01T00:00:00Z",
"author": "Majis Operations Toolbox"
},
"timeline": [
{
"name": "MAJ_JUP_DISK_SCAN_ORB17_DES0001",
"instrument": "MAJIS",
"type": "OBSERVATION",
"observation_type": "PRIME",
"start_time": "2032-12-19T07:10:47Z",
"end_time": "2032-12-19T07:19:32Z",
},
{
"name": "MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001",
"instrument": "MAJIS",
"type": "OBSERVATION",
"observation_type": "PRIME",
"start_time": "2032-12-19T07:30:36Z",
"end_time": "2032-12-19T07:45:00Z",
},
],
}
In this package we try to simplify as much as possible the reader, exporter and convertor of these files.
Read a OPL file#
opl_csv = read_opl('OPL_demo.csv')
opl_csv
| event | # | t_start | t_stop | |
|---|---|---|---|---|
| 0 | MAJIS_PRIME_OBSERVATION | 2 | 2032-12-19 | 2032-12-19 |
opl_csv['MAJIS_PRIME_OBSERVATION']
| t_start | t_end | OBS_KEY | INSTRUMENT | OBSERVATION_TYPE | TYPE | |
|---|---|---|---|---|---|---|
| 0 | 2032-12-19T07:10:47Z | 2032-12-19T07:19:32Z | MAJ_JUP_DISK_SCAN_ORB17_DES0001 | MAJIS | PRIME | OBSERVATION |
| 1 | 2032-12-19T07:30:36Z | 2032-12-19T07:45:00Z | MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001 | MAJIS | PRIME | OBSERVATION |
opl_json = read_opl('OPL_demo.json')
opl_json
| event | # | t_start | t_stop | |
|---|---|---|---|---|
| 0 | MAJ_JUP_DISK_SCAN_ORB17_DES0001 | - | 2032-12-19 | 2032-12-19 |
| 1 | MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001 | - | 2032-12-19 | 2032-12-19 |
opl_json['MAJ_JUP_DISK_SCAN_ORB17_DES0001'] # or opl[0]
| OBS_KEY | MAJ_JUP_DISK_SCAN_ORB17_DES0001 |
| OBS_NAME | MAJ_MAJ_JUP_DISK_SCAN_ORB17_DES0001_ORB17_001 |
| INSTRUMENT | MAJIS |
| TYPE | OBSERVATION |
| OBSERVATION_TYPE | PRIME |
| TARGET | planet.jupiter |
| t_start | 2032-12-19T07:10:47Z |
| t_end | 2032-12-19T07:19:32Z |
| POINTING | NADIR_JUPITER |
| POINTING_DESCRIPTION | |
| POINTING_DESIGNER | False |
| DESCRIPTION | |
| SCHEDULING_RULES | |
| INSTRUMENT_AREA | {} |
| PRIME | True |
| OPL | OPL_demo.json |
| COMMENTS |
Note: by default, in the JSON OPL reader, only the MAJIS blocks are considered.
If you need to include other instruments you can add a filter key with the only parameter.
It can be a string, a list of string, 'ALL', False or None value.
events = read_opl('OPL_demo.json', only='ALL')
events
| event | # | t_start | t_stop | |
|---|---|---|---|---|
| 0 | MAJ_JUP_DISK_SCAN_ORB17_DES0001 | - | 2032-12-19 | 2032-12-19 |
| 1 | MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001 | - | 2032-12-19 | 2032-12-19 |
| 2 | GANYMEDE_FLYBY | - | 2033-11-26 | 2033-11-27 |
events['GANYMEDE_FLYBY']
| OBS_KEY | GANYMEDE_FLYBY |
| OBS_NAME | WG1_GANYMEDE_FLYBY_OPP_006 |
| INSTRUMENT | WG1 |
| TYPE | OBSERVATION |
| OBSERVATION_TYPE | RIDER |
| TARGET | satellite.jupiter.ganymede |
| t_start | 2033-11-26T19:30:31Z |
| t_end | 2033-11-27T19:30:31Z |
| POINTING | |
| POINTING_DESCRIPTION | |
| POINTING_DESIGNER | False |
| DESCRIPTION | |
| SCHEDULING_RULES | |
| INSTRUMENT_AREA | {} |
| PRIME | False |
| OPL | OPL_demo.json |
| COMMENTS |
Export an OPL file#
save_opl('OPL_output.csv', opl_json)
MAJIS_PRIME_OBSERVATION,2032-12-19T07:10:47Z,2032-12-19T07:19:32Z,MAJ_JUP_DISK_SCAN_ORB17_DES0001,MAJIS
MAJIS_PRIME_OBSERVATION,2032-12-19T07:30:36Z,2032-12-19T07:45:00Z,MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001,MAJIS
save_opl('OPL_output.json', opl_csv)
{
"header": {
"filename": "OPL_output.json",
"creation_date": "2026-04-29T16:29:56.310Z",
"author": "docs"
},
"timeline": [
{
"name": "MAJ_JUP_DISK_SCAN_ORB17_DES0001",
"start_time": "2032-12-19T07:10:47Z",
"end_time": "2032-12-19T07:19:32Z",
"instrument": "MAJIS",
"observation_type": "PRIME",
"type": "OBSERVATION",
"parameters": {}
},
{
"name": "MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001",
"start_time": "2032-12-19T07:30:36Z",
"end_time": "2032-12-19T07:45:00Z",
"instrument": "MAJIS",
"observation_type": "PRIME",
"type": "OBSERVATION",
"parameters": {}
}
]
}
OPL convertors#
It is also possible to convert an OPL CSV to JSON and an OPL JSON to CSV with the convertor functions:
from majis.opl import csv2json_opl, json2csv_opl
csv2json_opl('OPL_output.csv')
PosixPath('OPL_output.json')
!cat OPL_output.csv
MAJIS_PRIME_OBSERVATION,2032-12-19T07:10:47Z,2032-12-19T07:19:32Z,MAJ_JUP_DISK_SCAN_ORB17_DES0001,MAJIS
MAJIS_PRIME_OBSERVATION,2032-12-19T07:30:36Z,2032-12-19T07:45:00Z,MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001,MAJIS
â ī¸ Be aware that OPL CSV files are very limited and will discard any additional fields present in the JSON input.
json2csv_opl('OPL_output.json')
PosixPath('OPL_output.csv')
!cat OPL_output.json
{
"header": {
"filename": "OPL_output.json",
"creation_date": "2026-04-29T16:29:56.449Z",
"author": "docs"
},
"timeline": [
{
"name": "MAJ_JUP_DISK_SCAN_ORB17_DES0001",
"start_time": "2032-12-19T07:10:47Z",
"end_time": "2032-12-19T07:19:32Z",
"instrument": "MAJIS",
"observation_type": "PRIME",
"type": "OBSERVATION",
"parameters": {}
},
{
"name": "MAJ_JUP_AURORAL_MAPPING_ORB17_DES0001",
"start_time": "2032-12-19T07:30:36Z",
"end_time": "2032-12-19T07:45:00Z",
"instrument": "MAJIS",
"observation_type": "PRIME",
"type": "OBSERVATION",
"parameters": {}
}
]
}
â ī¸ Be aware that OPL CSV files are very limited and only the fields above will be populated (compared with the original OPL_demo.json that contains additional fields).