juice-spark 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. juice_spark-0.1.1/PKG-INFO +59 -0
  2. juice_spark-0.1.1/README.md +31 -0
  3. juice_spark-0.1.1/pyproject.toml +42 -0
  4. juice_spark-0.1.1/src/juice_spark/.DS_Store +0 -0
  5. juice_spark-0.1.1/src/juice_spark/.idea/.gitignore +5 -0
  6. juice_spark-0.1.1/src/juice_spark/.idea/inspectionProfiles/Project_Default.xml +6 -0
  7. juice_spark-0.1.1/src/juice_spark/.idea/inspectionProfiles/profiles_settings.xml +6 -0
  8. juice_spark-0.1.1/src/juice_spark/.idea/juice_spark.iml +12 -0
  9. juice_spark-0.1.1/src/juice_spark/.idea/misc.xml +7 -0
  10. juice_spark-0.1.1/src/juice_spark/.idea/modules.xml +8 -0
  11. juice_spark-0.1.1/src/juice_spark/.idea/vcs.xml +6 -0
  12. juice_spark-0.1.1/src/juice_spark/__init__.py +0 -0
  13. juice_spark-0.1.1/src/juice_spark/cli/__init__.py +0 -0
  14. juice_spark-0.1.1/src/juice_spark/cli/data/template.json +128 -0
  15. juice_spark-0.1.1/src/juice_spark/cli/execute_spark.py +159 -0
  16. juice_spark-0.1.1/src/juice_spark/cli/sapy.py +56 -0
  17. juice_spark-0.1.1/src/juice_spark/core/sht.py +59 -0
  18. juice_spark-0.1.1/src/juice_spark/plots/.DS_Store +0 -0
  19. juice_spark-0.1.1/src/juice_spark/plots/MTP_periods_SAP_pipeline.py +702 -0
  20. juice_spark-0.1.1/src/juice_spark/plots/PEP_NIM_all_flybys_pipeline.py +314 -0
  21. juice_spark-0.1.1/src/juice_spark/plots/PJ_AJ_Phase_4_pipeline.py +396 -0
  22. juice_spark-0.1.1/src/juice_spark/plots/ROI_inter_gt_flybys_illum_pipeline.py +248 -0
  23. juice_spark-0.1.1/src/juice_spark/plots/ansa_1_2_phase_vs_RJ_pipeline.py +165 -0
  24. juice_spark-0.1.1/src/juice_spark/plots/datas_flybys_csv_pipeline.py +107 -0
  25. juice_spark-0.1.1/src/juice_spark/plots/juice_crema_5_1_150lb_23_1_a3.tm +270 -0
  26. juice_spark-0.1.1/src/juice_spark/plots/juice_dv_per_pass_simplified.py +125 -0
  27. juice_spark-0.1.1/src/juice_spark/plots/juice_tour_flybys.py +168 -0
  28. juice_spark-0.1.1/src/juice_spark/plots/juice_trajectory_summary.py +1145 -0
  29. juice_spark-0.1.1/src/juice_spark/plots/juice_wg4_trajectory_plots.py +598 -0
  30. juice_spark-0.1.1/src/juice_spark/plots/power_during_flybys_pipeline.py +192 -0
  31. juice_spark-0.1.1/src/juice_spark/plots/station_visibility_timeline_pipeline.py +440 -0
  32. juice_spark-0.1.1/src/juice_spark/plots/visibility_during_earth_occ_pipeline.py +490 -0
  33. juice_spark-0.1.1/src/juice_spark/utils/brf.py +125 -0
  34. juice_spark-0.1.1/src/juice_spark/utils/data_rate_mean_values.py +201 -0
  35. juice_spark-0.1.1/src/juice_spark/utils/evf_handler.py +152 -0
  36. juice_spark-0.1.1/src/juice_spark/utils/file_handling.py +135 -0
  37. juice_spark-0.1.1/src/juice_spark/utils/geometry_utils.py +56 -0
  38. juice_spark-0.1.1/src/juice_spark/utils/mission_phases_handler.py +218 -0
  39. juice_spark-0.1.1/src/juice_spark/utils/mission_timeline_event_file_handler.py +253 -0
  40. juice_spark-0.1.1/src/juice_spark/utils/restapi.py +81 -0
  41. juice_spark-0.1.1/src/juice_spark/utils/spice_kernel_utils.py +414 -0
  42. juice_spark-0.1.1/src/juice_spark/utils/utils.py +46 -0
@@ -0,0 +1,59 @@
1
+ Metadata-Version: 2.4
2
+ Name: juice-spark
3
+ Version: 0.1.1
4
+ Summary:
5
+ Author: Pilar Esquej
6
+ Author-email: Pilar.Esquej@ext.esa.int
7
+ Requires-Python: >=3.12,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Requires-Dist: esac-juice-pyutils (>=0.3.2,<0.4.0)
13
+ Requires-Dist: jupitermag (>=1.5.1,<2.0.0)
14
+ Requires-Dist: kaleido (>=1.0.0)
15
+ Requires-Dist: matplotlib (>=3.11.1,<4.0.0)
16
+ Requires-Dist: mplcursors (>=0.7.1,<0.8.0)
17
+ Requires-Dist: mysql-connector-python (>=26.7.0,<27.0.0)
18
+ Requires-Dist: numpy (>=2.5.3,<3.0.0)
19
+ Requires-Dist: pandas (>=3.0.5,<4.0.0)
20
+ Requires-Dist: planetary-coverage (>=1.2.1,<2.0.0)
21
+ Requires-Dist: plotly (>=7.0.0,<8.0.0)
22
+ Requires-Dist: python-dotenv (>=1.2.3,<2.0.0)
23
+ Requires-Dist: soa-report (>=1.2.7,<2.0.0)
24
+ Requires-Dist: spiceypy (>=8.2.0,<9.0.0)
25
+ Requires-Dist: tabulate (>=0.10.0,<0.11.0)
26
+ Requires-Dist: wget (>=3.2,<4.0)
27
+ Description-Content-Type: text/markdown
28
+
29
+ # JUICE SPARK
30
+
31
+ [![Python Version](https://img.shields.io/badge/Python-3.11%2B-blue)](https://www.python.org/downloads/)
32
+
33
+ ## Description
34
+
35
+ JUICE SPARK is a Python project that provides tools and functionalities for visualizing and analyzing data related to the JUICE mission. It aims to facilitate the creation of plots and visualizations for various purposes, such as mission planning, data analysis, and scientific research.
36
+
37
+ ## Installation
38
+
39
+ 1. Clone the repository: `https://gitlab.esa.int/juice-soc/juice-uplink/auxiliary-tools/juice-spark.git`
40
+ 2. Install the dependencies: `poetry install`
41
+
42
+ ## Usage
43
+ ### Command Line Options
44
+
45
+ To run JUICE Plots from the command line, use the following command:
46
+
47
+ ```bash
48
+
49
+ TBD
50
+
51
+ ```
52
+
53
+ #### Example
54
+
55
+ TBD
56
+
57
+ ### Configuration
58
+
59
+ TBD
@@ -0,0 +1,31 @@
1
+ # JUICE SPARK
2
+
3
+ [![Python Version](https://img.shields.io/badge/Python-3.11%2B-blue)](https://www.python.org/downloads/)
4
+
5
+ ## Description
6
+
7
+ JUICE SPARK is a Python project that provides tools and functionalities for visualizing and analyzing data related to the JUICE mission. It aims to facilitate the creation of plots and visualizations for various purposes, such as mission planning, data analysis, and scientific research.
8
+
9
+ ## Installation
10
+
11
+ 1. Clone the repository: `https://gitlab.esa.int/juice-soc/juice-uplink/auxiliary-tools/juice-spark.git`
12
+ 2. Install the dependencies: `poetry install`
13
+
14
+ ## Usage
15
+ ### Command Line Options
16
+
17
+ To run JUICE Plots from the command line, use the following command:
18
+
19
+ ```bash
20
+
21
+ TBD
22
+
23
+ ```
24
+
25
+ #### Example
26
+
27
+ TBD
28
+
29
+ ### Configuration
30
+
31
+ TBD
@@ -0,0 +1,42 @@
1
+ [project]
2
+ name = "juice-spark"
3
+ version = "0.1.1"
4
+ description = ""
5
+ authors = [
6
+ {name = "Pilar Esquej",email = "Pilar.Esquej@ext.esa.int"}
7
+ ]
8
+ readme = "README.md"
9
+ requires-python = ">=3.12,<4.0"
10
+ dependencies = [
11
+ "numpy (>=2.5.3,<3.0.0)",
12
+ "pandas (>=3.0.5,<4.0.0)",
13
+ "spiceypy (>=8.2.0,<9.0.0)",
14
+ "matplotlib (>=3.11.1,<4.0.0)",
15
+ "plotly (>=7.0.0,<8.0.0)",
16
+ "tabulate (>=0.10.0,<0.11.0)",
17
+ "wget (>=3.2,<4.0)",
18
+ "python-dotenv (>=1.2.3,<2.0.0)",
19
+ "kaleido (>=1.0.0)",
20
+ "planetary-coverage (>=1.2.1,<2.0.0)",
21
+ "esac-juice-pyutils (>=0.3.2,<0.4.0)",
22
+ "soa-report (>=1.2.7,<2.0.0)",
23
+ "jupitermag (>=1.5.1,<2.0.0)",
24
+ "mysql-connector-python (>=26.7.0,<27.0.0)",
25
+ "mplcursors (>=0.7.1,<0.8.0)"
26
+ ]
27
+
28
+ [tool.poetry]
29
+ packages = [{include = "juice_spark", from = "src"}]
30
+
31
+ [build-system]
32
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
33
+ build-backend = "poetry.core.masonry.api"
34
+
35
+ [dependency-groups]
36
+ dev = [
37
+ "jupyter (>=1.1.1,<2.0.0)",
38
+ "nbconvert (>=7.17.1,<8.0.0)"
39
+ ]
40
+
41
+ [tool.poetry.scripts]
42
+ juice-spark = "juice_spark.cli.execute_spark:main"
@@ -0,0 +1,5 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
+ </profile>
6
+ </component>
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="USE_PROJECT_PROFILE" value="false" />
4
+ <version value="1.0" />
5
+ </settings>
6
+ </component>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$" />
5
+ <orderEntry type="jdk" jdkName="Python 3.14" jdkType="Python SDK" />
6
+ <orderEntry type="sourceFolder" forTests="false" />
7
+ </component>
8
+ <component name="PyDocumentationSettings">
9
+ <option name="format" value="PLAIN" />
10
+ <option name="myDocStringFormat" value="Plain" />
11
+ </component>
12
+ </module>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Black">
4
+ <option name="sdkName" value="Python 3.14" />
5
+ </component>
6
+ <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.14" project-jdk-type="Python SDK" />
7
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/juice_spark.iml" filepath="$PROJECT_DIR$/.idea/juice_spark.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
5
+ </component>
6
+ </project>
File without changes
File without changes
@@ -0,0 +1,128 @@
1
+ {
2
+ "trajectory": "G_CREMA_5_2",
3
+ "api_url": "http://juiuldock01.evsp.lan:8080/rest_api",
4
+ "crema_name": "crema_5_2",
5
+ "mysql_host": "${HOST}",
6
+ "mysql_port": "${PORT}",
7
+ "mysql_db": "${MYSQL_DB_NAME}",
8
+ "mysql_user": "${MYSQL_DB_USER}",
9
+ "mysql_pass": "${MYSQL_PASS}",
10
+ "main_target": "Jupiter",
11
+ "input_conf_path": "${CONF_REPO}/internal",
12
+ "output_path": "${CONF_REPO}/internal/juice_spark/sap",
13
+ "plots": [
14
+ {
15
+ "plot_type": "dual_series_plot",
16
+ "left_data_source": {
17
+ "type": "restapi",
18
+ "location": "G_CREMA_5_2",
19
+ "series": "ssc_alt"
20
+ },
21
+ "right_data_source": {
22
+ "type": "restapi",
23
+ "location": "G_CREMA_5_2",
24
+ "series": "ssc_phase"
25
+ },
26
+ "title": "Spacecraft Altitude vs Phase",
27
+ "plot_id": "alt_vs_phase",
28
+ "background_ranges": [
29
+ {
30
+ "label": "Science Blackout",
31
+ "start": "2035-03-23T01:00:00",
32
+ "end": "2035-04-01T13:00:00",
33
+ "color": "#000000"
34
+ }
35
+ ]
36
+ },
37
+
38
+ {
39
+ "plot_type": "event_duration_plot",
40
+ "title": "Sun Occultations",
41
+ "plot_id": "sun_occ",
42
+ "events": [
43
+ "SUN_OCC_BY_JUPITER",
44
+ "SUN_OCC_BY_GANYMEDE"
45
+ ]
46
+ },
47
+ {
48
+ "plot_type": "event_duration_plot",
49
+ "events": [
50
+ "OCC_EARTH_000"
51
+ ],
52
+ "background_events": ["SUN_CONJUNCTION_SUP"],
53
+ "title": "Earth Occultations",
54
+ "plot_id": "earth_occ"
55
+ },
56
+ {
57
+ "plot_type": "dual_series_plot",
58
+ "left_data_source": {
59
+ "type": "brf",
60
+ "location": "/Users/randres/temp/juice-plots/tests/datasources/data/BRF_MLG_SGICD_2_2_300101_351005.brf",
61
+ "series": "HGAKA20"
62
+ },
63
+ "right_data_source": {
64
+ "type": "brf",
65
+ "location": "/Users/randres/temp/juice-plots/tests/datasources/data/BRF_MLG_SGICD_2_2_300101_351005.brf",
66
+ "series": "HGAX",
67
+ "dual": false
68
+ },
69
+ "title": "HGA Downlink data rates",
70
+ "y_left_title": "bits/s",
71
+ "plot_id": "bitrate",
72
+ "background_ranges": [
73
+ {
74
+ "label": "Science Blackout",
75
+ "start": "2035-03-23T01:00:00",
76
+ "end": "2035-04-01T13:00:00",
77
+ "color": "#000000"
78
+ }
79
+ ]
80
+ },
81
+ {
82
+ "plot_type": "dual_series_plot",
83
+ "left_data_source": {
84
+ "type": "osve",
85
+ "location": "/Users/randres/temp/juice-plots/sandbox/GAN_5_2_341030_351011/OUTPUT/osve_datapack.csv",
86
+ "series": "EPS_SA_AVAIL_POWER"
87
+ },
88
+ "right_data_source": {
89
+ "type": "osve",
90
+ "location": "/Users/randres/temp/juice-plots/sandbox/GAN_5_2_341030_351011/OUTPUT/osve_datapack.csv",
91
+ "series": "EPS_SA_ANGLE"
92
+ },
93
+ "background_ranges": [
94
+ {
95
+ "label": "Science Blackout",
96
+ "start": "2035-03-23T01:00:00",
97
+ "end": "2035-04-01T13:00:00",
98
+ "color": "#000000"
99
+ }
100
+ ],
101
+ "title": "Solar Array Available Power",
102
+ "y_left_title": "Available power (W)",
103
+ "y_right_title": "Solar Array Angle (deg)",
104
+ "y_left_range": [1320, 1370],
105
+ "plot_id": "power"
106
+ },
107
+ {
108
+ "plot_type": "dw_plot",
109
+ "left_data_source": {
110
+ "type": "brf",
111
+ "location": "/Users/randres/temp/juice-plots/tests/datasources/data/BRF_MLG_SGICD_2_2_300101_351005.brf",
112
+ "series": "HGAKA20"
113
+ },
114
+ "title": "Science Downlink Capacity Band-Ka HGAKA20",
115
+ "plot_id": "dw_hga_ka"
116
+ },
117
+ {
118
+ "plot_type": "dw_plot",
119
+ "left_data_source": {
120
+ "type": "brf",
121
+ "location": "/Users/randres/temp/juice-plots/tests/datasources/data/BRF_MLG_SGICD_2_2_300101_351005.brf",
122
+ "series": "HGAX"
123
+ },
124
+ "title": "Science Downlink Capacity Band-X HGAX",
125
+ "plot_id": "dw_hga_x"
126
+ }
127
+ ]
128
+ }
@@ -0,0 +1,159 @@
1
+ import json
2
+ import os
3
+ import argparse
4
+ from pathlib import Path
5
+ from dotenv import load_dotenv
6
+
7
+ from juice_spark.plots.PJ_AJ_Phase_4_pipeline import plot_PJ_AJ_Phase_4
8
+ from juice_spark.plots.ROI_inter_gt_flybys_illum_pipeline import plot_ROI_inter_gt_flybys_illum
9
+ from juice_spark.plots.PEP_NIM_all_flybys_pipeline import plot_PEP_NIM_all_flybys
10
+ from juice_spark.plots.MTP_periods_SAP_pipeline import table_mtp_periods
11
+ from juice_spark.plots.ansa_1_2_phase_vs_RJ_pipeline import plot_ansa_1_2_phase_vs_dist
12
+ from juice_spark.plots.datas_flybys_csv_pipeline import table_datas_flybys
13
+ from juice_spark.plots.visibility_during_earth_occ_pipeline import plot_visibility_during_earth_occ
14
+ from juice_spark.plots.station_visibility_timeline_pipeline import plot_station_visibility_timeline
15
+ from juice_spark.plots.power_during_flybys_pipeline import plot_power_during_flybys
16
+
17
+ from juice_spark.plots.juice_tour_flybys import tour_flybys
18
+ from juice_spark.plots.juice_trajectory_summary import perijove_plots, trajectory_summary, trajectory_plots
19
+ from juice_spark.plots.juice_wg4_trajectory_plots import wg4_plots
20
+ from juice_spark.plots.juice_dv_per_pass_simplified import dv_per_pass
21
+
22
+
23
+ def load_config(config_file):
24
+ load_dotenv()
25
+
26
+ with open(config_file) as f:
27
+ config = json.load(f)
28
+
29
+ return _expand_environment_variables(config)
30
+
31
+
32
+ def _expand_environment_variables(value):
33
+ if isinstance(value, dict):
34
+ return {
35
+ key: _expand_environment_variables(item)
36
+ for key, item in value.items()
37
+ }
38
+
39
+ if isinstance(value, list):
40
+ return [_expand_environment_variables(item) for item in value]
41
+
42
+ if isinstance(value, str):
43
+ return os.path.expandvars(value)
44
+
45
+ return value
46
+
47
+
48
+ def run_reports(config, report=None):
49
+
50
+ crema_name = config["crema_name"]
51
+ main_target = config["main_target"]
52
+ target = main_target.lower()
53
+ #mission_timeline = config["mission_timeline"]
54
+ _, crema_num = crema_name.split("_", 1)
55
+ if target == "ganymede":
56
+ mission_timeline_file = f"mission_timeline_event_file_{target.lower()}_phase_{crema_num}.csv"
57
+ elif target == "jupiter" or target is None:
58
+ mission_timeline_file = f"mission_timeline_event_file_{crema_num}.csv"
59
+
60
+ meta_kernel = f"juice_{crema_name}_local.tm"
61
+ sql_earth_occs_by_jupiter = f"Juice_earth_occs_by_jupiter_{crema_name}"
62
+ sql_table_segments_opp = f"Juice_segments_opportunities_{crema_name}"
63
+ sql_table_flybys_science = f"juice_flybys_science_phase_{crema_name}"
64
+
65
+ mission_phases = (
66
+ Path(config["input_conf_path"])
67
+ / "geopipeline"
68
+ / "output"
69
+ / config["crema_name"]
70
+ / "Mission_Phases.csv"
71
+ )
72
+
73
+ mission_timeline = (
74
+ Path(config["input_conf_path"])
75
+ / "geopipeline"
76
+ / "output"
77
+ / config["crema_name"]
78
+ / mission_timeline_file
79
+ )
80
+
81
+ output_geopipeline = (
82
+ Path(config["input_conf_path"])
83
+ / "geopipeline"
84
+ / "output"
85
+ )
86
+
87
+ output_figures = (
88
+ Path(config["output_path"])
89
+ / config["crema_name"]
90
+ / "figures"
91
+ )
92
+
93
+ output_tables = (
94
+ Path(config["output_path"])
95
+ / config["crema_name"]
96
+ / "tables"
97
+ )
98
+
99
+ config_sql = {
100
+ 'user': config["mysql_user"],
101
+ 'password': config["mysql_pass"],
102
+ 'host': config["mysql_host"],
103
+ 'port': config["mysql_port"],
104
+ 'database': config["mysql_db"],
105
+ 'raise_on_warnings': True
106
+ }
107
+
108
+
109
+ reports = {
110
+ "pj-aj": (plot_PJ_AJ_Phase_4, (meta_kernel, crema_name, mission_timeline, mission_phases, output_figures / "mission/jupiter")),
111
+ "mtp-periods": (
112
+ table_mtp_periods,
113
+ (meta_kernel, crema_name, mission_timeline, mission_phases, output_tables / "mission", config_sql,
114
+ sql_earth_occs_by_jupiter),
115
+ ),
116
+ "power_flybys": (plot_power_during_flybys,
117
+ (config_sql, sql_table_flybys_science, output_figures / "mission/power")),
118
+ "roi": (plot_ROI_inter_gt_flybys_illum, (meta_kernel, output_figures / "opportunities/flybys")),
119
+ "pep-nim": (plot_PEP_NIM_all_flybys, (meta_kernel, output_figures / "opportunities/flybys")),
120
+ "ansa": (plot_ansa_1_2_phase_vs_dist, (config_sql, meta_kernel, sql_table_segments_opp, output_figures / "opportunities/rings-and-moons")),
121
+ "vis_earth": (
122
+ plot_visibility_during_earth_occ,
123
+ (meta_kernel, config_sql, sql_earth_occs_by_jupiter, sql_table_segments_opp,
124
+ output_figures / "opportunities/jupiter"),
125
+ ),
126
+ "vis_flybys": (plot_station_visibility_timeline, (meta_kernel, output_figures / "appendix/visibilities")),
127
+ "table_flybys": (table_datas_flybys, (config_sql, meta_kernel, sql_table_flybys_science, output_tables / "appendix")),
128
+ "tour_flybys": (tour_flybys, (meta_kernel, mission_phases, output_figures / "mission/flybys")),
129
+ "jupiter_pj": (perijove_plots, (crema_name, output_figures / "mission/jupiter")),
130
+ #"summary": (trajectory_summary, (crema_name, output_figures / "mission/jupiter")),
131
+ "trajectory": (trajectory_plots, (meta_kernel, mission_timeline, mission_phases, output_figures / "mission/jupiter")),
132
+ "wg4_plots": (wg4_plots, (crema_name, meta_kernel, mission_timeline, mission_phases, output_figures / "mission/jupiter")),
133
+ "dv_pass": (dv_per_pass, (crema_name, meta_kernel, mission_phases, output_geopipeline, output_figures / "mission/downlink")),
134
+ }
135
+
136
+ if report is None:
137
+ for name, (function, args) in reports.items():
138
+ print(f"Running report: {name}")
139
+ function(*args)
140
+ else:
141
+ try:
142
+ function, args = reports[report]
143
+ except KeyError:
144
+ raise ValueError(f"Unknown report: {report}")
145
+
146
+ print(f"Running report: {report}")
147
+ function(*args)
148
+
149
+
150
+ def main():
151
+ parser = argparse.ArgumentParser(description="Generate JUICE reporting products.")
152
+ parser.add_argument("config", help="Path to the configuration JSON file.")
153
+ parser.add_argument("--report", help="Run only the specified report.")
154
+
155
+ args = parser.parse_args()
156
+ run_reports(load_config(args.config), args.report)
157
+
158
+ if __name__ == "__main__":
159
+ main()
@@ -0,0 +1,56 @@
1
+ from importlib import resources
2
+ import logging
3
+ import sys
4
+ import json
5
+ import argparse
6
+
7
+ from juice_plots.sap_plotter import SapProcessor
8
+
9
+ logging.getLogger("kaleido").setLevel(logging.WARNING)
10
+ logging.getLogger("choreographer").setLevel(logging.WARNING)
11
+
12
+ logging.basicConfig(
13
+ level=logging.INFO,
14
+ format="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
15
+ stream=sys.stdout,
16
+ )
17
+
18
+
19
+ def dump_template():
20
+ logging.basicConfig(level=logging.INFO, format="%(message)s", stream=sys.stdout)
21
+ template = resources.files(__package__) / "data" / "template.json"
22
+ logging.info(template.read_text())
23
+
24
+ def main():
25
+
26
+ parser = argparse.ArgumentParser()
27
+ parser.add_argument("configuration", type=argparse.FileType("r"), help="json configuration file", nargs='?')
28
+ parser.add_argument("-d", "--debug", action="store_true", help="enable debug logging")
29
+ parser.add_argument("-t", "--template", action="store_true", help="dump template configuration")
30
+ args = parser.parse_args()
31
+
32
+ logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO)
33
+
34
+ if args.template:
35
+ dump_template()
36
+ sys.exit(0)
37
+
38
+ if args.configuration is None:
39
+ logging.error("No configuration file provided")
40
+ sys.exit(1)
41
+
42
+ try:
43
+ conf = json.load(args.configuration)
44
+ except json.JSONDecodeError as e:
45
+ logging.error(f"Error parsing configuration file: {e}")
46
+ sys.exit(1)
47
+
48
+ trajectory_id = conf.get("trajectory")
49
+ api_url = conf.get("api_url")
50
+
51
+ jp = SapProcessor(api_url, trajectory_id)
52
+ jp.plot_configuration(conf.get("plots"))
53
+
54
+
55
+ if __name__ == "__main__":
56
+ main()
@@ -0,0 +1,59 @@
1
+ from pathlib import Path
2
+
3
+ import requests
4
+
5
+ REQUEST_TIMEOUT = 120
6
+
7
+
8
+ def get_trajectory_ptr(crema_id, output_folder):
9
+ """Downloads the PTR associated to the trajectory and stores it in the
10
+ output folder
11
+
12
+ Args:
13
+ crema_id (str): _description_
14
+ output_folder (str | path): target folder
15
+
16
+ Returns:
17
+ str: file path of the PTR associated to the trajectory
18
+ """
19
+ response = requests.get(
20
+ f"https://juicesoc.esac.esa.int/rest_api/trajectory/{crema_id}/ptr",
21
+ timeout=REQUEST_TIMEOUT)
22
+ if response.status_code == requests.codes.ok:
23
+ ptr_url = response.json().get("ptr_file")
24
+ download = requests.get(ptr_url, timeout=REQUEST_TIMEOUT)
25
+ if download.status_code == requests.codes.ok:
26
+ ptr_path = Path(output_folder, f"{crema_id}.ptx")
27
+ with ptr_path.open("wb") as file:
28
+ file.write(download.content)
29
+ return ptr_path
30
+ return None
31
+
32
+ def get_trajectory_phases(crema_id):
33
+ response = requests.get(f"https://juicesoc.esac.esa.int/rest_api/trajectory/{crema_id}/", timeout=REQUEST_TIMEOUT)
34
+ trajectory = response.json()
35
+ return trajectory.get("phases")
36
+
37
+
38
+ def __get_sht_config():
39
+ response = requests.get("https://juicesoc.esac.esa.int/rest_api/config/", timeout=REQUEST_TIMEOUT)
40
+ return response.json()
41
+
42
+ def get_targets():
43
+ """Returns the target mnemonics available in SHT
44
+
45
+ Returns:
46
+ list of str: list of targets
47
+ """
48
+ config = __get_sht_config()
49
+ return [item.get("mnemonic") for item in config.get("targets")]
50
+
51
+
52
+ def get_instrument_types():
53
+ """Returns the instrument types mnemonics available in SHT
54
+
55
+ Returns:
56
+ list of str: list of instrument types
57
+ """
58
+ config = __get_sht_config()
59
+ return [item.get("mnemonic") for item in config.get("instrument_types")]