solarviewer 1.0.2__py3-none-any.whl
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.
- solar_radio_image_viewer/__init__.py +12 -0
- solar_radio_image_viewer/assets/add_tab_default.png +0 -0
- solar_radio_image_viewer/assets/add_tab_default_light.png +0 -0
- solar_radio_image_viewer/assets/add_tab_hover.png +0 -0
- solar_radio_image_viewer/assets/add_tab_hover_light.png +0 -0
- solar_radio_image_viewer/assets/browse.png +0 -0
- solar_radio_image_viewer/assets/browse_light.png +0 -0
- solar_radio_image_viewer/assets/close_tab_default.png +0 -0
- solar_radio_image_viewer/assets/close_tab_default_light.png +0 -0
- solar_radio_image_viewer/assets/close_tab_hover.png +0 -0
- solar_radio_image_viewer/assets/close_tab_hover_light.png +0 -0
- solar_radio_image_viewer/assets/ellipse_selection.png +0 -0
- solar_radio_image_viewer/assets/ellipse_selection_light.png +0 -0
- solar_radio_image_viewer/assets/icons8-ellipse-90.png +0 -0
- solar_radio_image_viewer/assets/icons8-ellipse-90_light.png +0 -0
- solar_radio_image_viewer/assets/icons8-info-90.png +0 -0
- solar_radio_image_viewer/assets/icons8-info-90_light.png +0 -0
- solar_radio_image_viewer/assets/profile.png +0 -0
- solar_radio_image_viewer/assets/profile_light.png +0 -0
- solar_radio_image_viewer/assets/rectangle_selection.png +0 -0
- solar_radio_image_viewer/assets/rectangle_selection_light.png +0 -0
- solar_radio_image_viewer/assets/reset.png +0 -0
- solar_radio_image_viewer/assets/reset_light.png +0 -0
- solar_radio_image_viewer/assets/ruler.png +0 -0
- solar_radio_image_viewer/assets/ruler_light.png +0 -0
- solar_radio_image_viewer/assets/search.png +0 -0
- solar_radio_image_viewer/assets/search_light.png +0 -0
- solar_radio_image_viewer/assets/settings.png +0 -0
- solar_radio_image_viewer/assets/settings_light.png +0 -0
- solar_radio_image_viewer/assets/splash.fits +0 -0
- solar_radio_image_viewer/assets/zoom_60arcmin.png +0 -0
- solar_radio_image_viewer/assets/zoom_60arcmin_light.png +0 -0
- solar_radio_image_viewer/assets/zoom_in.png +0 -0
- solar_radio_image_viewer/assets/zoom_in_light.png +0 -0
- solar_radio_image_viewer/assets/zoom_out.png +0 -0
- solar_radio_image_viewer/assets/zoom_out_light.png +0 -0
- solar_radio_image_viewer/create_video.py +1345 -0
- solar_radio_image_viewer/dialogs.py +2665 -0
- solar_radio_image_viewer/from_simpl/__init__.py +184 -0
- solar_radio_image_viewer/from_simpl/caltable_visualizer.py +1001 -0
- solar_radio_image_viewer/from_simpl/dynamic_spectra_dialog.py +332 -0
- solar_radio_image_viewer/from_simpl/make_dynamic_spectra.py +351 -0
- solar_radio_image_viewer/from_simpl/pipeline_logger_gui.py +1232 -0
- solar_radio_image_viewer/from_simpl/simpl_theme.py +352 -0
- solar_radio_image_viewer/from_simpl/utils.py +984 -0
- solar_radio_image_viewer/from_simpl/view_dynamic_spectra_GUI.py +1975 -0
- solar_radio_image_viewer/helioprojective.py +1916 -0
- solar_radio_image_viewer/helioprojective_viewer.py +817 -0
- solar_radio_image_viewer/helioviewer_browser.py +1514 -0
- solar_radio_image_viewer/main.py +148 -0
- solar_radio_image_viewer/move_phasecenter.py +1269 -0
- solar_radio_image_viewer/napari_viewer.py +368 -0
- solar_radio_image_viewer/noaa_events/__init__.py +32 -0
- solar_radio_image_viewer/noaa_events/noaa_events.py +430 -0
- solar_radio_image_viewer/noaa_events/noaa_events_gui.py +1922 -0
- solar_radio_image_viewer/norms.py +293 -0
- solar_radio_image_viewer/radio_data_downloader/__init__.py +25 -0
- solar_radio_image_viewer/radio_data_downloader/radio_data_downloader.py +756 -0
- solar_radio_image_viewer/radio_data_downloader/radio_data_downloader_gui.py +528 -0
- solar_radio_image_viewer/searchable_combobox.py +220 -0
- solar_radio_image_viewer/solar_context/__init__.py +41 -0
- solar_radio_image_viewer/solar_context/active_regions.py +371 -0
- solar_radio_image_viewer/solar_context/cme_alerts.py +234 -0
- solar_radio_image_viewer/solar_context/context_images.py +297 -0
- solar_radio_image_viewer/solar_context/realtime_data.py +528 -0
- solar_radio_image_viewer/solar_data_downloader/__init__.py +35 -0
- solar_radio_image_viewer/solar_data_downloader/solar_data_downloader.py +1667 -0
- solar_radio_image_viewer/solar_data_downloader/solar_data_downloader_cli.py +901 -0
- solar_radio_image_viewer/solar_data_downloader/solar_data_downloader_gui.py +1210 -0
- solar_radio_image_viewer/styles.py +643 -0
- solar_radio_image_viewer/utils/__init__.py +32 -0
- solar_radio_image_viewer/utils/rate_limiter.py +255 -0
- solar_radio_image_viewer/utils.py +952 -0
- solar_radio_image_viewer/video_dialog.py +2629 -0
- solar_radio_image_viewer/video_utils.py +656 -0
- solar_radio_image_viewer/viewer.py +11174 -0
- solarviewer-1.0.2.dist-info/METADATA +343 -0
- solarviewer-1.0.2.dist-info/RECORD +82 -0
- solarviewer-1.0.2.dist-info/WHEEL +5 -0
- solarviewer-1.0.2.dist-info/entry_points.txt +8 -0
- solarviewer-1.0.2.dist-info/licenses/LICENSE +21 -0
- solarviewer-1.0.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,901 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Solar Data Downloader - Interactive tool for downloading solar observatory data.
|
|
4
|
+
|
|
5
|
+
This script provides a user-friendly interface for downloading data from
|
|
6
|
+
various solar observatories using the solar_data_downloader module.
|
|
7
|
+
|
|
8
|
+
Supported observatories:
|
|
9
|
+
- SDO/AIA (Atmospheric Imaging Assembly)
|
|
10
|
+
- SDO/HMI (Helioseismic and Magnetic Imager)
|
|
11
|
+
- IRIS (Interface Region Imaging Spectrograph)
|
|
12
|
+
- SOHO (Solar and Heliospheric Observatory)
|
|
13
|
+
- GOES/SUVI (Solar Ultraviolet Imager)
|
|
14
|
+
- STEREO/SECCHI (Sun Earth Connection)
|
|
15
|
+
- GONG (Global Oscillation Network Group)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
import sys
|
|
20
|
+
import datetime
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
# Try to import the solar_data_downloader module
|
|
24
|
+
try:
|
|
25
|
+
# First try relative import (when used as part of package)
|
|
26
|
+
from . import solar_data_downloader as sdd
|
|
27
|
+
except ImportError:
|
|
28
|
+
try:
|
|
29
|
+
# Then try importing from the same directory (when run as script)
|
|
30
|
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
31
|
+
if script_dir not in sys.path:
|
|
32
|
+
sys.path.append(script_dir)
|
|
33
|
+
import solar_data_downloader as sdd
|
|
34
|
+
except ImportError:
|
|
35
|
+
print("Error: Could not import solar_data_downloader module.")
|
|
36
|
+
print(
|
|
37
|
+
"Make sure solar_data_downloader.py is in the same directory as this script."
|
|
38
|
+
)
|
|
39
|
+
sys.exit(1)
|
|
40
|
+
|
|
41
|
+
# Check if required packages are installed
|
|
42
|
+
try:
|
|
43
|
+
import sunpy
|
|
44
|
+
import drms
|
|
45
|
+
import astropy
|
|
46
|
+
except ImportError as e:
|
|
47
|
+
print(f"Error: Missing required package: {e.name}")
|
|
48
|
+
print("Please install the required packages with:")
|
|
49
|
+
print(" pip install sunpy drms astropy")
|
|
50
|
+
print("For AIA Level 1.5 calibration, also install:")
|
|
51
|
+
print(" pip install aiapy")
|
|
52
|
+
sys.exit(1)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def clear_screen():
|
|
56
|
+
"""Clear the terminal screen."""
|
|
57
|
+
os.system("cls" if os.name == "nt" else "clear")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def print_header():
|
|
61
|
+
"""Print the application header."""
|
|
62
|
+
clear_screen()
|
|
63
|
+
print("=" * 80)
|
|
64
|
+
print(" SOLAR DATA DOWNLOADER ")
|
|
65
|
+
print("=" * 80)
|
|
66
|
+
print("Download and process data from various solar observatories")
|
|
67
|
+
print("=" * 80)
|
|
68
|
+
print()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_date_input(prompt, default=None):
|
|
72
|
+
"""
|
|
73
|
+
Get a date input from the user with validation.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
prompt (str): The prompt to display to the user
|
|
77
|
+
default (str, optional): Default value to use if user presses Enter
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
str: Date in YYYY.MM.DD format
|
|
81
|
+
"""
|
|
82
|
+
while True:
|
|
83
|
+
if default:
|
|
84
|
+
user_input = input(f"{prompt} [default: {default}]: ")
|
|
85
|
+
if not user_input.strip():
|
|
86
|
+
return default
|
|
87
|
+
else:
|
|
88
|
+
user_input = input(f"{prompt} (YYYY.MM.DD): ")
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
# Try to parse the date
|
|
92
|
+
date_obj = datetime.datetime.strptime(user_input, "%Y.%m.%d")
|
|
93
|
+
# Format it back to ensure consistency
|
|
94
|
+
return date_obj.strftime("%Y.%m.%d")
|
|
95
|
+
except ValueError:
|
|
96
|
+
print("Error: Invalid date format. Please use YYYY.MM.DD.")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def get_time_input(prompt, default=None):
|
|
100
|
+
"""
|
|
101
|
+
Get a time input from the user with validation.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
prompt (str): The prompt to display to the user
|
|
105
|
+
default (str, optional): Default value to use if user presses Enter
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
str: Time in HH:MM:SS format
|
|
109
|
+
"""
|
|
110
|
+
while True:
|
|
111
|
+
if default:
|
|
112
|
+
user_input = input(f"{prompt} [default: {default}]: ")
|
|
113
|
+
if not user_input.strip():
|
|
114
|
+
return default
|
|
115
|
+
else:
|
|
116
|
+
user_input = input(f"{prompt} (HH:MM:SS): ")
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
# Try to parse the time
|
|
120
|
+
time_obj = datetime.datetime.strptime(user_input, "%H:%M:%S")
|
|
121
|
+
# Format it back to ensure consistency
|
|
122
|
+
return time_obj.strftime("%H:%M:%S")
|
|
123
|
+
except ValueError:
|
|
124
|
+
print("Error: Invalid time format. Please use HH:MM:SS.")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def get_datetime_range():
|
|
128
|
+
"""
|
|
129
|
+
Get a datetime range from the user.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
tuple: (start_time, end_time) both in 'YYYY.MM.DD HH:MM:SS' format
|
|
133
|
+
"""
|
|
134
|
+
# Get default dates (today)
|
|
135
|
+
today = datetime.datetime.now().strftime("%Y.%m.%d")
|
|
136
|
+
now = datetime.datetime.now().strftime("%H:%M:%S")
|
|
137
|
+
one_hour_later = (datetime.datetime.now() + datetime.timedelta(hours=1)).strftime(
|
|
138
|
+
"%H:%M:%S"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
print("\nPlease specify the time range for data download:")
|
|
142
|
+
print("------------------------------------------------")
|
|
143
|
+
|
|
144
|
+
start_date = get_date_input(" Start date", today)
|
|
145
|
+
start_time = get_time_input(" Start time", now)
|
|
146
|
+
end_date = get_date_input(" End date", start_date)
|
|
147
|
+
|
|
148
|
+
# If end date is same as start date, suggest a time 1 hour after start
|
|
149
|
+
default_end_time = one_hour_later if end_date == start_date else now
|
|
150
|
+
end_time = get_time_input(" End time", default_end_time)
|
|
151
|
+
|
|
152
|
+
# Format the full datetime strings
|
|
153
|
+
start_datetime = f"{start_date} {start_time}"
|
|
154
|
+
end_datetime = f"{end_date} {end_time}"
|
|
155
|
+
|
|
156
|
+
return start_datetime, end_datetime
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def get_output_directory(instrument):
|
|
160
|
+
"""
|
|
161
|
+
Get the output directory from the user.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
instrument (str): The selected instrument
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
str: Path to the output directory
|
|
168
|
+
"""
|
|
169
|
+
default_dir = f"./{instrument.lower()}_data"
|
|
170
|
+
user_input = input(f"\nOutput directory [default: {default_dir}]: ")
|
|
171
|
+
|
|
172
|
+
output_dir = user_input.strip() if user_input.strip() else default_dir
|
|
173
|
+
|
|
174
|
+
# Create the directory if it doesn't exist
|
|
175
|
+
Path(output_dir).mkdir(parents=True, exist_ok=True)
|
|
176
|
+
|
|
177
|
+
return output_dir
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def download_aia_data():
|
|
181
|
+
"""
|
|
182
|
+
Guide the user through downloading AIA data.
|
|
183
|
+
"""
|
|
184
|
+
print_header()
|
|
185
|
+
print("SDO/AIA Data Download")
|
|
186
|
+
print("---------------------")
|
|
187
|
+
|
|
188
|
+
# Get wavelength
|
|
189
|
+
wavelength_options = {
|
|
190
|
+
"1": "94",
|
|
191
|
+
"2": "131",
|
|
192
|
+
"3": "171",
|
|
193
|
+
"4": "193",
|
|
194
|
+
"5": "211",
|
|
195
|
+
"6": "304",
|
|
196
|
+
"7": "335",
|
|
197
|
+
"8": "1600",
|
|
198
|
+
"9": "1700",
|
|
199
|
+
"10": "4500",
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
print("\nAvailable wavelengths:")
|
|
203
|
+
for key, value in wavelength_options.items():
|
|
204
|
+
print(f" {key}: {value} Å")
|
|
205
|
+
|
|
206
|
+
while True:
|
|
207
|
+
wavelength_choice = input("\nSelect wavelength (1-10) [default: 3]: ")
|
|
208
|
+
wavelength_choice = "3" if not wavelength_choice.strip() else wavelength_choice
|
|
209
|
+
|
|
210
|
+
if wavelength_choice in wavelength_options:
|
|
211
|
+
wavelength = wavelength_options[wavelength_choice]
|
|
212
|
+
break
|
|
213
|
+
else:
|
|
214
|
+
print("Invalid choice. Please enter a number between 1 and 10.")
|
|
215
|
+
|
|
216
|
+
# Get time range
|
|
217
|
+
start_time, end_time = get_datetime_range()
|
|
218
|
+
|
|
219
|
+
# Get output directory
|
|
220
|
+
output_dir = get_output_directory("AIA")
|
|
221
|
+
|
|
222
|
+
# Download method - Fido is now default
|
|
223
|
+
print("\nDownload method:")
|
|
224
|
+
print(" 1: Fido client (recommended, no email required)")
|
|
225
|
+
print(" 2: DRMS client (for advanced users)")
|
|
226
|
+
|
|
227
|
+
while True:
|
|
228
|
+
method_choice = input("\nSelect download method (1-2) [default: 1]: ")
|
|
229
|
+
method_choice = "1" if not method_choice.strip() else method_choice
|
|
230
|
+
|
|
231
|
+
if method_choice in ["1", "2"]:
|
|
232
|
+
break
|
|
233
|
+
else:
|
|
234
|
+
print("Invalid choice. Please enter 1 or 2.")
|
|
235
|
+
|
|
236
|
+
# Get email and cadence if using DRMS
|
|
237
|
+
email = None
|
|
238
|
+
cadence = "12s"
|
|
239
|
+
if method_choice == "2":
|
|
240
|
+
print("\nEmail is required for DRMS downloads.")
|
|
241
|
+
email = input("Email address: ")
|
|
242
|
+
if not email.strip():
|
|
243
|
+
print("Warning: No email provided. Download may fail for large requests.")
|
|
244
|
+
email = None
|
|
245
|
+
|
|
246
|
+
# Get cadence for DRMS
|
|
247
|
+
cadence_options = {"1": "12s", "2": "24s", "3": "1h"}
|
|
248
|
+
print("\nAvailable cadences:")
|
|
249
|
+
print(" 1: 12s (for EUV: 94, 131, 171, 193, 211, 304, 335 Å)")
|
|
250
|
+
print(" 2: 24s (for UV: 1600, 1700 Å)")
|
|
251
|
+
print(" 3: 1h (for Visible: 4500 Å)")
|
|
252
|
+
|
|
253
|
+
# Auto-select cadence based on wavelength
|
|
254
|
+
default_cadence = "1"
|
|
255
|
+
if wavelength in ["1600", "1700"]:
|
|
256
|
+
default_cadence = "2"
|
|
257
|
+
elif wavelength in ["4500"]:
|
|
258
|
+
default_cadence = "3"
|
|
259
|
+
|
|
260
|
+
while True:
|
|
261
|
+
cadence_choice = input(f"\nSelect cadence (1-3) [default: {default_cadence}]: ")
|
|
262
|
+
cadence_choice = default_cadence if not cadence_choice.strip() else cadence_choice
|
|
263
|
+
|
|
264
|
+
if cadence_choice in cadence_options:
|
|
265
|
+
cadence = cadence_options[cadence_choice]
|
|
266
|
+
break
|
|
267
|
+
else:
|
|
268
|
+
print("Invalid choice. Please enter a number between 1 and 3.")
|
|
269
|
+
|
|
270
|
+
# Confirm download
|
|
271
|
+
print("\n" + "=" * 50)
|
|
272
|
+
print("Download Summary:")
|
|
273
|
+
print(f" Instrument: SDO/AIA")
|
|
274
|
+
print(f" Wavelength: {wavelength} Å")
|
|
275
|
+
print(f" Time range: {start_time} to {end_time}")
|
|
276
|
+
print(f" Output directory: {output_dir}")
|
|
277
|
+
print(f" Download method: {'Fido' if method_choice == '1' else 'DRMS'}")
|
|
278
|
+
if method_choice == "2":
|
|
279
|
+
print(f" Cadence: {cadence}")
|
|
280
|
+
if email:
|
|
281
|
+
print(f" Email: {email}")
|
|
282
|
+
print("=" * 50)
|
|
283
|
+
|
|
284
|
+
confirm = input("\nProceed with download? (y/n) [default: y]: ")
|
|
285
|
+
if confirm.lower() in ["", "y", "yes"]:
|
|
286
|
+
print("\nDownloading data...")
|
|
287
|
+
try:
|
|
288
|
+
if method_choice == "1":
|
|
289
|
+
# Use Fido method
|
|
290
|
+
files = sdd.download_aia_with_fido(
|
|
291
|
+
wavelength=wavelength,
|
|
292
|
+
start_time=start_time,
|
|
293
|
+
end_time=end_time,
|
|
294
|
+
output_dir=output_dir,
|
|
295
|
+
)
|
|
296
|
+
else:
|
|
297
|
+
# Use DRMS method
|
|
298
|
+
files = sdd.download_aia(
|
|
299
|
+
wavelength=wavelength,
|
|
300
|
+
cadence=cadence,
|
|
301
|
+
start_time=start_time,
|
|
302
|
+
end_time=end_time,
|
|
303
|
+
output_dir=output_dir,
|
|
304
|
+
email=email,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
print(f"\nDownload complete. Downloaded {len(files) if files else 0} files to {output_dir}")
|
|
308
|
+
except Exception as e:
|
|
309
|
+
print(f"\nError during download: {str(e)}")
|
|
310
|
+
else:
|
|
311
|
+
print("\nDownload cancelled.")
|
|
312
|
+
|
|
313
|
+
input("\nPress Enter to return to the main menu...")
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def download_hmi_data():
|
|
317
|
+
"""
|
|
318
|
+
Guide the user through downloading HMI data.
|
|
319
|
+
"""
|
|
320
|
+
print_header()
|
|
321
|
+
print("SDO/HMI Data Download")
|
|
322
|
+
print("---------------------")
|
|
323
|
+
|
|
324
|
+
# Get series - now includes V_ velocity series
|
|
325
|
+
series_options = {
|
|
326
|
+
"1": "45s",
|
|
327
|
+
"2": "720s",
|
|
328
|
+
"3": "B_45s",
|
|
329
|
+
"4": "B_720s",
|
|
330
|
+
"5": "Ic_45s",
|
|
331
|
+
"6": "Ic_720s",
|
|
332
|
+
"7": "V_45s",
|
|
333
|
+
"8": "V_720s",
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
series_descriptions = {
|
|
337
|
+
"1": "LOS magnetogram (45s cadence)",
|
|
338
|
+
"2": "LOS magnetogram (12 min cadence)",
|
|
339
|
+
"3": "LOS magnetogram B (45s cadence)",
|
|
340
|
+
"4": "LOS magnetogram B (12 min cadence)",
|
|
341
|
+
"5": "Continuum intensity (45s cadence)",
|
|
342
|
+
"6": "Continuum intensity (12 min cadence)",
|
|
343
|
+
"7": "LOS velocity (45s cadence)",
|
|
344
|
+
"8": "LOS velocity (12 min cadence)",
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
print("\nAvailable data series:")
|
|
348
|
+
for key, value in series_descriptions.items():
|
|
349
|
+
print(f" {key}: {value}")
|
|
350
|
+
|
|
351
|
+
while True:
|
|
352
|
+
series_choice = input("\nSelect series (1-8) [default: 3]: ")
|
|
353
|
+
series_choice = "3" if not series_choice.strip() else series_choice
|
|
354
|
+
|
|
355
|
+
if series_choice in series_options:
|
|
356
|
+
series = series_options[series_choice]
|
|
357
|
+
break
|
|
358
|
+
else:
|
|
359
|
+
print("Invalid choice. Please enter a number between 1 and 8.")
|
|
360
|
+
|
|
361
|
+
# Get time range
|
|
362
|
+
start_time, end_time = get_datetime_range()
|
|
363
|
+
|
|
364
|
+
# Get output directory
|
|
365
|
+
output_dir = get_output_directory("HMI")
|
|
366
|
+
|
|
367
|
+
# Download method - Fido is now default
|
|
368
|
+
print("\nDownload method:")
|
|
369
|
+
print(" 1: Fido client (recommended, no email required)")
|
|
370
|
+
print(" 2: DRMS client (for advanced users)")
|
|
371
|
+
|
|
372
|
+
while True:
|
|
373
|
+
method_choice = input("\nSelect download method (1-2) [default: 1]: ")
|
|
374
|
+
method_choice = "1" if not method_choice.strip() else method_choice
|
|
375
|
+
|
|
376
|
+
if method_choice in ["1", "2"]:
|
|
377
|
+
break
|
|
378
|
+
else:
|
|
379
|
+
print("Invalid choice. Please enter 1 or 2.")
|
|
380
|
+
|
|
381
|
+
# Get email if using DRMS
|
|
382
|
+
email = None
|
|
383
|
+
if method_choice == "2":
|
|
384
|
+
print("\nEmail is required for DRMS downloads.")
|
|
385
|
+
email = input("Email address: ")
|
|
386
|
+
if not email.strip():
|
|
387
|
+
print("Warning: No email provided. Download may fail for large requests.")
|
|
388
|
+
email = None
|
|
389
|
+
|
|
390
|
+
# Set interval seconds based on series
|
|
391
|
+
interval_seconds = 45.0 if "45s" in series else 720.0
|
|
392
|
+
|
|
393
|
+
# Confirm download
|
|
394
|
+
print("\n" + "=" * 50)
|
|
395
|
+
print("Download Summary:")
|
|
396
|
+
print(f" Instrument: SDO/HMI")
|
|
397
|
+
print(f" Series: {series} ({series_descriptions[series_choice]})")
|
|
398
|
+
print(f" Time range: {start_time} to {end_time}")
|
|
399
|
+
print(f" Output directory: {output_dir}")
|
|
400
|
+
print(f" Download method: {'Fido' if method_choice == '1' else 'DRMS'}")
|
|
401
|
+
if email:
|
|
402
|
+
print(f" Email: {email}")
|
|
403
|
+
print("=" * 50)
|
|
404
|
+
|
|
405
|
+
confirm = input("\nProceed with download? (y/n) [default: y]: ")
|
|
406
|
+
if confirm.lower() in ["", "y", "yes"]:
|
|
407
|
+
print("\nDownloading data...")
|
|
408
|
+
try:
|
|
409
|
+
if method_choice == "1":
|
|
410
|
+
# Use Fido method
|
|
411
|
+
files = sdd.download_hmi_with_fido(
|
|
412
|
+
series=series,
|
|
413
|
+
start_time=start_time,
|
|
414
|
+
end_time=end_time,
|
|
415
|
+
output_dir=output_dir,
|
|
416
|
+
)
|
|
417
|
+
else:
|
|
418
|
+
# Use DRMS method
|
|
419
|
+
files = sdd.download_hmi(
|
|
420
|
+
series=series,
|
|
421
|
+
start_time=start_time,
|
|
422
|
+
end_time=end_time,
|
|
423
|
+
output_dir=output_dir,
|
|
424
|
+
email=email,
|
|
425
|
+
interval_seconds=interval_seconds,
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
print(f"\nDownload complete. Downloaded {len(files) if files else 0} files to {output_dir}")
|
|
429
|
+
except Exception as e:
|
|
430
|
+
print(f"\nError during download: {str(e)}")
|
|
431
|
+
else:
|
|
432
|
+
print("\nDownload cancelled.")
|
|
433
|
+
|
|
434
|
+
input("\nPress Enter to return to the main menu...")
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def download_iris_data():
|
|
438
|
+
"""
|
|
439
|
+
Guide the user through downloading IRIS data.
|
|
440
|
+
"""
|
|
441
|
+
print_header()
|
|
442
|
+
print("IRIS Data Download")
|
|
443
|
+
print("------------------")
|
|
444
|
+
print("Note: IRIS data uses Fido (no email required)")
|
|
445
|
+
|
|
446
|
+
# Get observation type
|
|
447
|
+
obs_type_options = {
|
|
448
|
+
"1": "SJI",
|
|
449
|
+
"2": "raster",
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
print("\nObservation types:")
|
|
453
|
+
print(" 1: SJI (Slit-Jaw Imager)")
|
|
454
|
+
print(" 2: Raster (Spectrograph data)")
|
|
455
|
+
|
|
456
|
+
while True:
|
|
457
|
+
obs_type_choice = input("\nSelect observation type (1-2) [default: 1]: ")
|
|
458
|
+
obs_type_choice = "1" if not obs_type_choice.strip() else obs_type_choice
|
|
459
|
+
|
|
460
|
+
if obs_type_choice in obs_type_options:
|
|
461
|
+
obs_type = obs_type_options[obs_type_choice]
|
|
462
|
+
break
|
|
463
|
+
else:
|
|
464
|
+
print("Invalid choice. Please enter 1 or 2.")
|
|
465
|
+
|
|
466
|
+
# Get wavelength if using SJI
|
|
467
|
+
wavelength = None
|
|
468
|
+
if obs_type == "SJI":
|
|
469
|
+
wavelength_options = {"1": "1330", "2": "1400", "3": "2796", "4": "2832"}
|
|
470
|
+
|
|
471
|
+
print("\nAvailable wavelengths for SJI:")
|
|
472
|
+
print(" 1: 1330 Å (C II, Transition Region)")
|
|
473
|
+
print(" 2: 1400 Å (Si IV, Transition Region)")
|
|
474
|
+
print(" 3: 2796 Å (Mg II k, Chromosphere)")
|
|
475
|
+
print(" 4: 2832 Å (Photosphere)")
|
|
476
|
+
|
|
477
|
+
while True:
|
|
478
|
+
wavelength_choice = input("\nSelect wavelength (1-4) [default: 2]: ")
|
|
479
|
+
wavelength_choice = "2" if not wavelength_choice.strip() else wavelength_choice
|
|
480
|
+
|
|
481
|
+
if wavelength_choice in wavelength_options:
|
|
482
|
+
wavelength = wavelength_options[wavelength_choice]
|
|
483
|
+
break
|
|
484
|
+
else:
|
|
485
|
+
print("Invalid choice. Please enter a number between 1 and 4.")
|
|
486
|
+
|
|
487
|
+
# Get time range
|
|
488
|
+
start_time, end_time = get_datetime_range()
|
|
489
|
+
|
|
490
|
+
# Get output directory
|
|
491
|
+
output_dir = get_output_directory("IRIS")
|
|
492
|
+
|
|
493
|
+
# Confirm download
|
|
494
|
+
print("\n" + "=" * 50)
|
|
495
|
+
print("Download Summary:")
|
|
496
|
+
print(f" Instrument: IRIS")
|
|
497
|
+
print(f" Observation type: {obs_type}")
|
|
498
|
+
if wavelength:
|
|
499
|
+
print(f" Wavelength: {wavelength} Å")
|
|
500
|
+
print(f" Time range: {start_time} to {end_time}")
|
|
501
|
+
print(f" Output directory: {output_dir}")
|
|
502
|
+
print("=" * 50)
|
|
503
|
+
|
|
504
|
+
confirm = input("\nProceed with download? (y/n) [default: y]: ")
|
|
505
|
+
if confirm.lower() in ["", "y", "yes"]:
|
|
506
|
+
print("\nDownloading data...")
|
|
507
|
+
try:
|
|
508
|
+
files = sdd.download_iris(
|
|
509
|
+
start_time=start_time,
|
|
510
|
+
end_time=end_time,
|
|
511
|
+
output_dir=output_dir,
|
|
512
|
+
obs_type=obs_type,
|
|
513
|
+
wavelength=wavelength,
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
print(f"\nDownload complete. Downloaded {len(files) if files else 0} files to {output_dir}")
|
|
517
|
+
except Exception as e:
|
|
518
|
+
print(f"\nError during download: {str(e)}")
|
|
519
|
+
else:
|
|
520
|
+
print("\nDownload cancelled.")
|
|
521
|
+
|
|
522
|
+
input("\nPress Enter to return to the main menu...")
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def download_soho_data():
|
|
526
|
+
"""
|
|
527
|
+
Guide the user through downloading SOHO data.
|
|
528
|
+
"""
|
|
529
|
+
print_header()
|
|
530
|
+
print("SOHO Data Download")
|
|
531
|
+
print("------------------")
|
|
532
|
+
print("Note: SOHO data uses Fido (no email required)")
|
|
533
|
+
|
|
534
|
+
# Get instrument
|
|
535
|
+
instrument_options = {
|
|
536
|
+
"1": "EIT",
|
|
537
|
+
"2": "LASCO",
|
|
538
|
+
"3": "MDI",
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
print("\nAvailable instruments:")
|
|
542
|
+
print(" 1: EIT (Extreme-ultraviolet Imaging Telescope)")
|
|
543
|
+
print(" 2: LASCO (Large Angle and Spectrometric Coronagraph)")
|
|
544
|
+
print(" 3: MDI (Michelson Doppler Imager - pre-2011)")
|
|
545
|
+
|
|
546
|
+
while True:
|
|
547
|
+
instrument_choice = input("\nSelect instrument (1-3) [default: 1]: ")
|
|
548
|
+
instrument_choice = "1" if not instrument_choice.strip() else instrument_choice
|
|
549
|
+
|
|
550
|
+
if instrument_choice in instrument_options:
|
|
551
|
+
instrument = instrument_options[instrument_choice]
|
|
552
|
+
break
|
|
553
|
+
else:
|
|
554
|
+
print("Invalid choice. Please enter a number between 1 and 3.")
|
|
555
|
+
|
|
556
|
+
# Get instrument-specific parameters
|
|
557
|
+
wavelength = None
|
|
558
|
+
detector = None
|
|
559
|
+
|
|
560
|
+
if instrument == "EIT":
|
|
561
|
+
wavelength_options = {"1": "171", "2": "195", "3": "284", "4": "304"}
|
|
562
|
+
|
|
563
|
+
print("\nAvailable wavelengths for EIT:")
|
|
564
|
+
print(" 1: 171 Å (Fe IX/X)")
|
|
565
|
+
print(" 2: 195 Å (Fe XII)")
|
|
566
|
+
print(" 3: 284 Å (Fe XV)")
|
|
567
|
+
print(" 4: 304 Å (He II)")
|
|
568
|
+
|
|
569
|
+
while True:
|
|
570
|
+
wavelength_choice = input("\nSelect wavelength (1-4) [default: 2]: ")
|
|
571
|
+
wavelength_choice = "2" if not wavelength_choice.strip() else wavelength_choice
|
|
572
|
+
|
|
573
|
+
if wavelength_choice in wavelength_options:
|
|
574
|
+
wavelength = wavelength_options[wavelength_choice]
|
|
575
|
+
break
|
|
576
|
+
else:
|
|
577
|
+
print("Invalid choice. Please enter a number between 1 and 4.")
|
|
578
|
+
|
|
579
|
+
elif instrument == "LASCO":
|
|
580
|
+
detector_options = {"1": "C2", "2": "C3"}
|
|
581
|
+
|
|
582
|
+
print("\nAvailable detectors for LASCO:")
|
|
583
|
+
print(" 1: C2 (2-6 solar radii)")
|
|
584
|
+
print(" 2: C3 (3.7-30 solar radii)")
|
|
585
|
+
|
|
586
|
+
while True:
|
|
587
|
+
detector_choice = input("\nSelect detector (1-2) [default: 1]: ")
|
|
588
|
+
detector_choice = "1" if not detector_choice.strip() else detector_choice
|
|
589
|
+
|
|
590
|
+
if detector_choice in detector_options:
|
|
591
|
+
detector = detector_options[detector_choice]
|
|
592
|
+
break
|
|
593
|
+
else:
|
|
594
|
+
print("Invalid choice. Please enter 1 or 2.")
|
|
595
|
+
|
|
596
|
+
# Get time range
|
|
597
|
+
start_time, end_time = get_datetime_range()
|
|
598
|
+
|
|
599
|
+
# Get output directory
|
|
600
|
+
output_dir = get_output_directory(f"SOHO_{instrument}")
|
|
601
|
+
|
|
602
|
+
# Confirm download
|
|
603
|
+
print("\n" + "=" * 50)
|
|
604
|
+
print("Download Summary:")
|
|
605
|
+
print(f" Instrument: SOHO/{instrument}")
|
|
606
|
+
if wavelength:
|
|
607
|
+
print(f" Wavelength: {wavelength} Å")
|
|
608
|
+
if detector:
|
|
609
|
+
print(f" Detector: {detector}")
|
|
610
|
+
print(f" Time range: {start_time} to {end_time}")
|
|
611
|
+
print(f" Output directory: {output_dir}")
|
|
612
|
+
print("=" * 50)
|
|
613
|
+
|
|
614
|
+
confirm = input("\nProceed with download? (y/n) [default: y]: ")
|
|
615
|
+
if confirm.lower() in ["", "y", "yes"]:
|
|
616
|
+
print("\nDownloading data...")
|
|
617
|
+
try:
|
|
618
|
+
files = sdd.download_soho(
|
|
619
|
+
instrument=instrument,
|
|
620
|
+
start_time=start_time,
|
|
621
|
+
end_time=end_time,
|
|
622
|
+
output_dir=output_dir,
|
|
623
|
+
wavelength=wavelength,
|
|
624
|
+
detector=detector,
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
print(f"\nDownload complete. Downloaded {len(files) if files else 0} files to {output_dir}")
|
|
628
|
+
except Exception as e:
|
|
629
|
+
print(f"\nError during download: {str(e)}")
|
|
630
|
+
else:
|
|
631
|
+
print("\nDownload cancelled.")
|
|
632
|
+
|
|
633
|
+
input("\nPress Enter to return to the main menu...")
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
def download_suvi_data():
|
|
637
|
+
"""
|
|
638
|
+
Guide the user through downloading GOES SUVI data.
|
|
639
|
+
"""
|
|
640
|
+
print_header()
|
|
641
|
+
print("GOES/SUVI Data Download")
|
|
642
|
+
print("-----------------------")
|
|
643
|
+
print("Note: SUVI data uses Fido (no email required)")
|
|
644
|
+
|
|
645
|
+
# Get wavelength
|
|
646
|
+
wavelength_options = {
|
|
647
|
+
"1": "94",
|
|
648
|
+
"2": "131",
|
|
649
|
+
"3": "171",
|
|
650
|
+
"4": "195",
|
|
651
|
+
"5": "284",
|
|
652
|
+
"6": "304",
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
print("\nAvailable wavelengths:")
|
|
656
|
+
for key, value in wavelength_options.items():
|
|
657
|
+
print(f" {key}: {value} Å")
|
|
658
|
+
|
|
659
|
+
while True:
|
|
660
|
+
wavelength_choice = input("\nSelect wavelength (1-6) [default: 3]: ")
|
|
661
|
+
wavelength_choice = "3" if not wavelength_choice.strip() else wavelength_choice
|
|
662
|
+
|
|
663
|
+
if wavelength_choice in wavelength_options:
|
|
664
|
+
wavelength = wavelength_options[wavelength_choice]
|
|
665
|
+
break
|
|
666
|
+
else:
|
|
667
|
+
print("Invalid choice. Please enter a number between 1 and 6.")
|
|
668
|
+
|
|
669
|
+
# Get data level
|
|
670
|
+
print("\nData level:")
|
|
671
|
+
print(" 1: Level 2 (calibrated, recommended)")
|
|
672
|
+
print(" 2: Level 1b (raw)")
|
|
673
|
+
|
|
674
|
+
level_choice = input("\nSelect data level (1-2) [default: 1]: ")
|
|
675
|
+
level = "2" if level_choice != "2" else "1b"
|
|
676
|
+
|
|
677
|
+
# Get time range
|
|
678
|
+
start_time, end_time = get_datetime_range()
|
|
679
|
+
|
|
680
|
+
# Get output directory
|
|
681
|
+
output_dir = get_output_directory("SUVI")
|
|
682
|
+
|
|
683
|
+
# Confirm download
|
|
684
|
+
print("\n" + "=" * 50)
|
|
685
|
+
print("Download Summary:")
|
|
686
|
+
print(f" Instrument: GOES/SUVI")
|
|
687
|
+
print(f" Wavelength: {wavelength} Å")
|
|
688
|
+
print(f" Data level: {level}")
|
|
689
|
+
print(f" Time range: {start_time} to {end_time}")
|
|
690
|
+
print(f" Output directory: {output_dir}")
|
|
691
|
+
print("=" * 50)
|
|
692
|
+
|
|
693
|
+
confirm = input("\nProceed with download? (y/n) [default: y]: ")
|
|
694
|
+
if confirm.lower() in ["", "y", "yes"]:
|
|
695
|
+
print("\nDownloading data...")
|
|
696
|
+
try:
|
|
697
|
+
files = sdd.download_goes_suvi(
|
|
698
|
+
start_time=start_time,
|
|
699
|
+
end_time=end_time,
|
|
700
|
+
output_dir=output_dir,
|
|
701
|
+
wavelength=wavelength,
|
|
702
|
+
level=level,
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
print(f"\nDownload complete. Downloaded {len(files) if files else 0} files to {output_dir}")
|
|
706
|
+
except Exception as e:
|
|
707
|
+
print(f"\nError during download: {str(e)}")
|
|
708
|
+
else:
|
|
709
|
+
print("\nDownload cancelled.")
|
|
710
|
+
|
|
711
|
+
input("\nPress Enter to return to the main menu...")
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
def download_stereo_data():
|
|
715
|
+
"""
|
|
716
|
+
Guide the user through downloading STEREO data.
|
|
717
|
+
"""
|
|
718
|
+
print_header()
|
|
719
|
+
print("STEREO/SECCHI Data Download")
|
|
720
|
+
print("---------------------------")
|
|
721
|
+
print("Note: STEREO data uses Fido (no email required)")
|
|
722
|
+
|
|
723
|
+
# Get spacecraft
|
|
724
|
+
print("\nSpacecraft:")
|
|
725
|
+
print(" 1: STEREO-A (currently active)")
|
|
726
|
+
print(" 2: STEREO-B (pre-2014 data only)")
|
|
727
|
+
|
|
728
|
+
sc_choice = input("\nSelect spacecraft (1-2) [default: 1]: ")
|
|
729
|
+
spacecraft = "A" if sc_choice != "2" else "B"
|
|
730
|
+
|
|
731
|
+
# Get instrument
|
|
732
|
+
instrument_options = {
|
|
733
|
+
"1": "EUVI",
|
|
734
|
+
"2": "COR1",
|
|
735
|
+
"3": "COR2",
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
print("\nAvailable instruments:")
|
|
739
|
+
print(" 1: EUVI (Extreme Ultraviolet Imager)")
|
|
740
|
+
print(" 2: COR1 (Inner Coronagraph)")
|
|
741
|
+
print(" 3: COR2 (Outer Coronagraph)")
|
|
742
|
+
|
|
743
|
+
while True:
|
|
744
|
+
inst_choice = input("\nSelect instrument (1-3) [default: 1]: ")
|
|
745
|
+
inst_choice = "1" if not inst_choice.strip() else inst_choice
|
|
746
|
+
|
|
747
|
+
if inst_choice in instrument_options:
|
|
748
|
+
instrument = instrument_options[inst_choice]
|
|
749
|
+
break
|
|
750
|
+
else:
|
|
751
|
+
print("Invalid choice. Please enter a number between 1 and 3.")
|
|
752
|
+
|
|
753
|
+
# Get wavelength if EUVI
|
|
754
|
+
wavelength = None
|
|
755
|
+
if instrument == "EUVI":
|
|
756
|
+
wavelength_options = {"1": "171", "2": "195", "3": "284", "4": "304"}
|
|
757
|
+
|
|
758
|
+
print("\nAvailable wavelengths for EUVI:")
|
|
759
|
+
print(" 1: 171 Å")
|
|
760
|
+
print(" 2: 195 Å")
|
|
761
|
+
print(" 3: 284 Å")
|
|
762
|
+
print(" 4: 304 Å")
|
|
763
|
+
|
|
764
|
+
while True:
|
|
765
|
+
wavelength_choice = input("\nSelect wavelength (1-4) [default: 2]: ")
|
|
766
|
+
wavelength_choice = "2" if not wavelength_choice.strip() else wavelength_choice
|
|
767
|
+
|
|
768
|
+
if wavelength_choice in wavelength_options:
|
|
769
|
+
wavelength = wavelength_options[wavelength_choice]
|
|
770
|
+
break
|
|
771
|
+
else:
|
|
772
|
+
print("Invalid choice. Please enter a number between 1 and 4.")
|
|
773
|
+
|
|
774
|
+
# Get time range
|
|
775
|
+
start_time, end_time = get_datetime_range()
|
|
776
|
+
|
|
777
|
+
# Get output directory
|
|
778
|
+
output_dir = get_output_directory(f"STEREO_{spacecraft}")
|
|
779
|
+
|
|
780
|
+
# Confirm download
|
|
781
|
+
print("\n" + "=" * 50)
|
|
782
|
+
print("Download Summary:")
|
|
783
|
+
print(f" Instrument: STEREO-{spacecraft}/{instrument}")
|
|
784
|
+
if wavelength:
|
|
785
|
+
print(f" Wavelength: {wavelength} Å")
|
|
786
|
+
print(f" Time range: {start_time} to {end_time}")
|
|
787
|
+
print(f" Output directory: {output_dir}")
|
|
788
|
+
print("=" * 50)
|
|
789
|
+
|
|
790
|
+
confirm = input("\nProceed with download? (y/n) [default: y]: ")
|
|
791
|
+
if confirm.lower() in ["", "y", "yes"]:
|
|
792
|
+
print("\nDownloading data...")
|
|
793
|
+
try:
|
|
794
|
+
files = sdd.download_stereo(
|
|
795
|
+
start_time=start_time,
|
|
796
|
+
end_time=end_time,
|
|
797
|
+
output_dir=output_dir,
|
|
798
|
+
spacecraft=spacecraft,
|
|
799
|
+
instrument=instrument,
|
|
800
|
+
wavelength=wavelength,
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
print(f"\nDownload complete. Downloaded {len(files) if files else 0} files to {output_dir}")
|
|
804
|
+
except Exception as e:
|
|
805
|
+
print(f"\nError during download: {str(e)}")
|
|
806
|
+
else:
|
|
807
|
+
print("\nDownload cancelled.")
|
|
808
|
+
|
|
809
|
+
input("\nPress Enter to return to the main menu...")
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
def download_gong_data():
|
|
813
|
+
"""
|
|
814
|
+
Guide the user through downloading GONG data.
|
|
815
|
+
"""
|
|
816
|
+
print_header()
|
|
817
|
+
print("GONG Magnetogram Data Download")
|
|
818
|
+
print("-------------------------------")
|
|
819
|
+
print("Note: GONG data uses Fido (no email required)")
|
|
820
|
+
print("\nGONG provides ground-based magnetogram observations from a global network.")
|
|
821
|
+
|
|
822
|
+
# Get time range
|
|
823
|
+
start_time, end_time = get_datetime_range()
|
|
824
|
+
|
|
825
|
+
# Get output directory
|
|
826
|
+
output_dir = get_output_directory("GONG")
|
|
827
|
+
|
|
828
|
+
# Confirm download
|
|
829
|
+
print("\n" + "=" * 50)
|
|
830
|
+
print("Download Summary:")
|
|
831
|
+
print(f" Instrument: GONG")
|
|
832
|
+
print(f" Data type: LOS Magnetogram")
|
|
833
|
+
print(f" Time range: {start_time} to {end_time}")
|
|
834
|
+
print(f" Output directory: {output_dir}")
|
|
835
|
+
print("=" * 50)
|
|
836
|
+
|
|
837
|
+
confirm = input("\nProceed with download? (y/n) [default: y]: ")
|
|
838
|
+
if confirm.lower() in ["", "y", "yes"]:
|
|
839
|
+
print("\nDownloading data...")
|
|
840
|
+
try:
|
|
841
|
+
files = sdd.download_gong(
|
|
842
|
+
start_time=start_time,
|
|
843
|
+
end_time=end_time,
|
|
844
|
+
output_dir=output_dir,
|
|
845
|
+
)
|
|
846
|
+
|
|
847
|
+
print(f"\nDownload complete. Downloaded {len(files) if files else 0} files to {output_dir}")
|
|
848
|
+
except Exception as e:
|
|
849
|
+
print(f"\nError during download: {str(e)}")
|
|
850
|
+
else:
|
|
851
|
+
print("\nDownload cancelled.")
|
|
852
|
+
|
|
853
|
+
input("\nPress Enter to return to the main menu...")
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
def main_menu():
|
|
857
|
+
"""
|
|
858
|
+
Display the main menu and handle user selection.
|
|
859
|
+
"""
|
|
860
|
+
while True:
|
|
861
|
+
print_header()
|
|
862
|
+
print("Main Menu:")
|
|
863
|
+
print(" 1. Download SDO/AIA Data (Atmospheric Imaging Assembly)")
|
|
864
|
+
print(" 2. Download SDO/HMI Data (Helioseismic and Magnetic Imager)")
|
|
865
|
+
print(" 3. Download IRIS Data (Interface Region Imaging Spectrograph)")
|
|
866
|
+
print(" 4. Download SOHO Data (Solar and Heliospheric Observatory)")
|
|
867
|
+
print(" 5. Download GOES/SUVI Data (Solar Ultraviolet Imager)")
|
|
868
|
+
print(" 6. Download STEREO Data (Sun Earth Connection)")
|
|
869
|
+
print(" 7. Download GONG Data (Global Oscillation Network Group)")
|
|
870
|
+
print(" 8. Exit")
|
|
871
|
+
|
|
872
|
+
choice = input("\nSelect an option (1-8): ")
|
|
873
|
+
|
|
874
|
+
if choice == "1":
|
|
875
|
+
download_aia_data()
|
|
876
|
+
elif choice == "2":
|
|
877
|
+
download_hmi_data()
|
|
878
|
+
elif choice == "3":
|
|
879
|
+
download_iris_data()
|
|
880
|
+
elif choice == "4":
|
|
881
|
+
download_soho_data()
|
|
882
|
+
elif choice == "5":
|
|
883
|
+
download_suvi_data()
|
|
884
|
+
elif choice == "6":
|
|
885
|
+
download_stereo_data()
|
|
886
|
+
elif choice == "7":
|
|
887
|
+
download_gong_data()
|
|
888
|
+
elif choice == "8":
|
|
889
|
+
print("\nExiting Solar Data Downloader CLI. Goodbye!")
|
|
890
|
+
sys.exit(0)
|
|
891
|
+
else:
|
|
892
|
+
print("\nInvalid choice. Please enter a number between 1 and 8.")
|
|
893
|
+
input("\nPress Enter to continue...")
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
if __name__ == "__main__":
|
|
897
|
+
try:
|
|
898
|
+
main_menu()
|
|
899
|
+
except KeyboardInterrupt:
|
|
900
|
+
print("\n\nExiting Solar Data Downloader CLI. Goodbye!")
|
|
901
|
+
sys.exit(0)
|