• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

spedas / pyspedas / 5158344230

pending completion
5158344230

push

github-actions

web-flow
Merge pull request #507 from nickssl/master

Now using logging instead of print

5 of 5 new or added lines in 1 file covered. (100.0%)

20810 of 31522 relevant lines covered (66.02%)

0.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pyspedas/cdagui/cdagui.py
1
"""
2
GUI for CDAWeb.
3

4
A GUI that can download data files from CDAWeb
5
and load them into pytplot variables.
6

7
Requires cdasws, PyQt5.
8

9
PyQt5 is no longer included in the general pyspedas requirements,
10
and if it is not installed an error message will be printed.
11
To install PyQt5, please use:
12
pip install pyqt5
13

14
To open the GUI window:
15
    from pyspedas.cdagui.cdagui import cdagui
16
    x = cdagui()
17

18
For cdasws documentation, see:
19
    https://pypi.org/project/cdasws/
20
    https://cdaweb.gsfc.nasa.gov/WebServices/REST/py/cdasws/index.html
21

22
To start the gui from the command line, use:
23
    python pyspedas/cdagui/cdagui.py
24
"""
25
import sys
×
26
import logging
×
27
import datetime
×
28
from cdaweb import CDAWeb
×
29
from config import CONFIG
×
30

31

32
try:
×
33
    from PyQt5.QtCore import Qt, QDate, QCoreApplication
×
34
    from PyQt5.QtWidgets import (QApplication, QWidget, QMainWindow,
×
35
                                 QGridLayout, QPushButton, QListWidget,
36
                                 QGroupBox, QCheckBox, QMessageBox,
37
                                 QVBoxLayout, QLabel, QLineEdit,
38
                                 QFileDialog, QCalendarWidget, QDialog)
39
    appx = QApplication(sys.argv)
×
40
except ImportError:
×
41
    logging.error("PyQt5 library must be installed to use this module.")
×
42
    logging.error("Please install it using: pip install pyqt5")
×
43
    logging.error("Original python error follows...")
×
44
    # sys.exit()
45

46

47
def show_my_message(self, title, msg):
×
48
    """Show a message."""
49
    alert = QMessageBox(self)
×
50
    alert.setWindowTitle(title)
×
51
    alert.setText(msg)
×
52
    alert.setIcon(2)
×
53
    alert.show()
×
54
    return alert
×
55

56

57
class cdagui(QMainWindow):
×
58
    """Main CDAWeb Window."""
59

60
    def __init__(self, parent=None):
×
61
        """Inilitalize."""
62
        super().__init__()
×
63

64
        self.main_widget = GUIWidget(self)
×
65
        self.setCentralWidget(self.main_widget)
×
66
        self.init_UI()
×
67

68
    def init_UI(self):
×
69
        """Start GUI."""
70
        self.setWindowTitle('CDAWeb Data Downloader')
×
71
        self.statusbar = self.statusBar()
×
72
        self.statusbar.showMessage('Status: Ready')
×
73
        self.showMaximized()
×
74

75

76
class GUIWidget(QWidget):
×
77
    """Main GUI class."""
78

79
    def __init__(self, parent):
×
80
        """Initialize widget."""
81
        super(GUIWidget, self).__init__(parent)
×
82
        self.parent = parent
×
83
        self.cda = CDAWeb()
×
84
        self.title_css = "background-color:#AFEEEE;\
×
85
            font-family:Verdana;font-size:14px;"
86
        self.button_css = "background-color:#AFEEAF;font-family:Verdana;"
×
87
        self.clear_css = "background-color:#E9967A;font-family:Verdana;"
×
88
        self.initUI()
×
89

90
    def createMissionGroupBox(self):
×
91
        """1. Missions and instruments group of GUI."""
92

93
        def button1_find_datasets():
×
94
            title = "Find Datasets"
×
95
            self.dataset_box.clear()
×
96
            self.file_box.clear()
×
97
            mission_list = [item.text() for item in
×
98
                            self.mission_box.selectedItems()]
99
            instrument_list = [item.text() for item in
×
100
                               self.instrument_box.selectedItems()]
101
            if len(mission_list) < 1 or len(instrument_list) < 1:
×
102
                msg = "Please select at least one mission and one instrument."
×
103
                aaa = show_my_message(self.parent, title, msg)
×
104
                return 0
×
105
            datasets = self.cda.get_datasets(mission_list, instrument_list)
×
106
            datalen = len(datasets)
×
107
            if datalen < 1:
×
108
                msg = "No datasets were found with these parameters."
×
109
                aaa = show_my_message(self.parent, title, msg)
×
110
                return 0
×
111
            elif datalen > 50:
×
112
                msg = "Number of datasets found: " + str(datalen)
×
113
                msg += "\nOnly 50 will be shown."
×
114
                aaa = show_my_message(self.parent, title, msg)
×
115
            self.mission_selected.setText(str(mission_list))
×
116
            self.instrument_selected.setText(str(instrument_list))
×
117
            self.dataset_box.addItems(datasets[:50])
×
118

119
        # Missions group GUI elements
120
        self.missionGroupBox = QGroupBox("Missions and Instruments")
×
121

122
        label1 = QLabel("Mission Groups:")
×
123
        list1 = QListWidget(self)
×
124
        list1.setSelectionMode(QListWidget.MultiSelection)
×
125
        list1.setMinimumHeight(50)
×
126
        list1.setMinimumWidth(400)
×
127
        list1.addItems(self.cda.get_observatories())
×
128
        self.mission_box = list1
×
129

130
        label2 = QLabel("Instrument Types:")
×
131
        list2 = QListWidget(self)
×
132
        list2.setSelectionMode(QListWidget.MultiSelection)
×
133
        list2.setMinimumHeight(50)
×
134
        list2.setMinimumWidth(400)
×
135
        list2.addItems(self.cda.get_instruments())
×
136
        self.instrument_box = list2
×
137

138
        label3 = QLabel("Select one or more Mission Group(s) and one"
×
139
                        + " or more Instrument Type(s) and press:")
140
        button1 = QPushButton("1. Find Datasets")
×
141
        button1.setStyleSheet(self.button_css)
×
142
        button1.clicked.connect(button1_find_datasets)
×
143

144
        # Create the layout and add GUI elements
145
        # row, column, rowSpan, columnSpan
146
        layout = QGridLayout()
×
147
        layout.addWidget(label1, 0, 0)
×
148
        layout.addWidget(label2, 0, 1)
×
149
        layout.addWidget(list1, 1, 0)
×
150
        layout.addWidget(list2, 1, 1)
×
151
        layout.addWidget(label3, 2, 0, 1, 1)
×
152
        layout.addWidget(button1, 2, 1, 1, 1)
×
153

154
        self.missionGroupBox.setLayout(layout)
×
155

156
    def createDatasetBox(self):
×
157
        """2. Dataset group of GUI."""
158
        # Datasets group GUI elements
159
        self.datasetGroupBox = QGroupBox("Datasets")
×
160

161
        label1 = QLabel("Selected Mission Groups:")
×
162
        ans1 = QLabel("   ")
×
163
        self.mission_selected = ans1
×
164
        ans1.setWordWrap(True)
×
165

166
        label2 = QLabel("Selected Instruments:")
×
167
        ans2 = QLabel("   ")
×
168
        self.instrument_selected = ans2
×
169
        ans2.setWordWrap(True)
×
170

171
        list1 = QListWidget(self)
×
172
        self.dataset_box = list1
×
173
        list1.setMinimumHeight(50)
×
174
        list1.setMinimumWidth(400)
×
175
        list1.setSelectionMode(QListWidget.MultiSelection)
×
176

177
        layout = QGridLayout()
×
178
        layout.addWidget(label1, 0, 0, 1, 1)
×
179
        layout.addWidget(ans1, 0, 1, 1, 15)
×
180
        layout.addWidget(label2, 1, 0, 1, 1)
×
181
        layout.addWidget(ans2, 1, 1, 1, 15)
×
182
        layout.addWidget(list1, 2, 0, 1, 16)
×
183

184
        self.datasetGroupBox.setLayout(layout)
×
185

186
    def createTimeGroupBox(self):
×
187
        """3. Date and time group of GUI."""
188

189
        def button2_get_file_list():
×
190
            title = "Get File List"
×
191
            self.file_box.clear()
×
192
            dataset_list = [item.text() for item in
×
193
                            self.dataset_box.selectedItems()]
194
            t0 = self.time_start_box.text()
×
195
            t1 = self.time_end_box.text()
×
196
            if len(dataset_list) < 1 or len(t0) < 9 or len(t1) < 9:
×
197
                msg = "Please select at least one dataset and start-end times."
×
198
                aaa = show_my_message(self.parent, title, msg)
×
199
                return 0
×
200
            file_list = self.cda.get_filenames(dataset_list, t0, t1)
×
201
            filelen = len(file_list)
×
202
            if filelen < 1:
×
203
                msg = "No datasets were found with these parameters."
×
204
                aaa = show_my_message(self.parent, title, msg)
×
205
                return 0
×
206
            elif filelen > 50:
×
207
                msg = "Number of files found: " + str(filelen)
×
208
                msg += "\nOnly 50 will be shown."
×
209
                aaa = show_my_message(self.parent, title, msg)
×
210
            self.file_box.addItems(file_list[:50])
×
211

212
        def pick_time(start_or_end):
×
213
            """Date picker."""
214
            dlg = QDialog(self)
×
215
            gridc = QVBoxLayout()
×
216
            dlg.setLayout(gridc)
×
217
            if (start_or_end == "start"):
×
218
                title_str = "Start date"
×
219
            else:
220
                title_str = "End date"
×
221
            titlelabel = QLabel(title_str)
×
222
            gridc.addWidget(titlelabel)
×
223

224
            my_calendar = QCalendarWidget()
×
225
            my_calendar.setGridVisible(True)
×
226
            my_calendar.move(10, 20)
×
227
            gridc.addWidget(my_calendar)
×
228

229
            labeldate = QLabel("")
×
230
            gridc.addWidget(labeldate)
×
231

232
            def dial_exit():
×
233
                dlg.done(1)
×
234

235
            buttonc = QPushButton("Close")
×
236
            buttonc.clicked.connect(dial_exit)
×
237
            gridc.addWidget(buttonc)
×
238

239
            def show_date():
×
240
                date = my_calendar.selectedDate()
×
241
                date_string = date.toString('yyyy-MM-dd')
×
242
                if (start_or_end == "start"):
×
243
                    self.time_start_box.setText(date_string + " 00:00:01")
×
244
                else:
245
                    self.time_end_box.setText(date_string + " 23:59:59")
×
246
                labeldate.setText(date_string)
×
247

248
            my_calendar.clicked[QDate].connect(show_date)
×
249

250
            dlg.setWindowTitle("Calendar")
×
251
            dlg.exec_()
×
252

253
        # Date and Time group GUI elements
254
        self.timeGroupBox = QGroupBox("Date and Time")
×
255

256
        # By default show 7 days behind to ensure that there is data
257
        label1 = QLabel("Start Time:")
×
258
        t0 = datetime.datetime.strftime(datetime.datetime.now()
×
259
                                        - datetime.timedelta(7), '%Y-%m-%d')
260
        time1 = QLineEdit(str(t0) + " 00:00:01")
×
261
        self.time_start_box = time1
×
262
        button1 = QPushButton("Select")
×
263
        button1.clicked.connect(lambda: pick_time("start"))
×
264

265
        label2 = QLabel("End Time:")
×
266
        time2 = QLineEdit(str(t0) + " 23:59:59")
×
267
        self.time_end_box = time2
×
268
        button2 = QPushButton("Select")
×
269
        button2.clicked.connect(lambda: pick_time("end"))
×
270

271
        label3 = QLabel("Date and time format: YYYY-MM-DD[ HH:MM:SS]")
×
272
        button3 = QPushButton("2. Get File List")
×
273
        button3.setStyleSheet(self.button_css)
×
274
        button3.clicked.connect(button2_get_file_list)
×
275

276
        layout = QGridLayout()
×
277
        layout.addWidget(label1, 0, 0)
×
278
        layout.addWidget(time1, 0, 1)
×
279
        layout.addWidget(button1, 0, 2)
×
280
        layout.addWidget(label2, 0, 3)
×
281
        layout.addWidget(time2, 0, 4)
×
282
        layout.addWidget(button2, 0, 5)
×
283
        layout.addWidget(label3, 1, 0, 1, 3)
×
284
        layout.addWidget(button3, 1, 3, 1, 3)
×
285

286
        self.timeGroupBox.setLayout(layout)
×
287

288
    def createDownloadGroupBox(self):
×
289
        """4. Download group of GUI."""
290

291
        def button3_get_data():
×
292
            """Get data button."""
293
            title = "Download Files"
×
294
            file_list = [item.text() for item in self.file_box.selectedItems()]
×
295
            if len(file_list) < 1:
×
296
                msg = "Please select at least one file to download."
×
297
                aaa = show_my_message(self.parent, title, msg)
×
298
                return 0
×
299
            local_dir = self.dir_box.text()
×
300
            if len(local_dir) < 1:
×
301
                msg = "Please select a local directory."
×
302
                aaa = show_my_message(self.parent, title, msg)
×
303
                return 0
×
304
            download_only = False
×
305
            if check1.isChecked():
×
306
                download_only = True
×
307

308
            # The following can be slow, especially if there are multiple files
309
            self.parent.statusbar.showMessage('Status: Downloading, \
×
310
                                              please wait...')
311
            QApplication.setOverrideCursor(Qt.WaitCursor)
×
312
            QApplication.processEvents()
×
313
            result = self.cda.cda_download(file_list, local_dir, download_only)
×
314
            QApplication.restoreOverrideCursor()
×
315
            self.parent.statusbar.showMessage('Status: Ready')
×
316

317
            filelen = len(result)
×
318
            if filelen < 1:
×
319
                msg = "No files were downloaded."
×
320
                aaa = show_my_message(self.parent, title, msg)
×
321
                return 0
×
322
            else:
323
                count_no_downloads = 0
×
324
                count_tplot_problem = 0
×
325
                count_tplot = 0
×
326
                for item in result:
×
327
                    if item[2] == -1:
×
328
                        count_no_downloads += 1
×
329
                    elif item[2] == 0 and not download_only:
×
330
                        count_tplot_problem += 1
×
331
                    elif item[2] == 1:
×
332
                        count_tplot += 1
×
333
                msg = "Results:"
×
334
                msg += "\n"
×
335
                msg += "\nFiles to download: " + str(filelen)
×
336
                msg += ("\nFiles that could not be downloaded: "
×
337
                        + str(count_no_downloads))
338
                if not download_only:
×
339
                    msg += "\n"
×
340
                    msg += ("\nFiles loaded to pytplot: " + str(count_tplot))
×
341
                    msg += ("\nFiles that could not be loaded to pytplot: "
×
342
                            + str(count_tplot_problem))
343
                aaa = show_my_message(self.parent, title, msg)
×
344

345
        def select_dir():
×
346
            """Select directory."""
347
            file = str(QFileDialog.getExistingDirectory(self,
×
348
                                                        "Select Directory"))
349
            if file:
×
350
                self.local_dir = file
×
351
                self.dir_box.setText(self.local_dir)
×
352

353
        def clear_all():
×
354
            """Clear all boxes."""
355
            self.mission_box.clearSelection()
×
356
            self.instrument_box.clearSelection()
×
357
            self.instrument_selected.setText('')
×
358
            self.mission_selected.setText('')
×
359
            self.dataset_box.clear()
×
360
            self.file_box.clear()
×
361
            self.parent.statusbar.showMessage('Status: Ready')
×
362

363
        def exit_all():
×
364
            self.parent.close()
×
365

366
        # Download Files GUI elements
367
        self.dirGroupBox = QGroupBox("Remote Files and Download")
×
368

369
        list1 = QListWidget(self)
×
370
        list1.setMinimumHeight(50)
×
371
        list1.setMinimumWidth(400)
×
372
        list1.setSelectionMode(QListWidget.MultiSelection)
×
373
        self.file_box = list1
×
374

375
        label1 = QLabel("Download Directory:")
×
376
        dir1 = QLineEdit()
×
377
        self.local_dir = CONFIG['local_data_dir']
×
378
        dir1.setText(self.local_dir)
×
379
        self.dir_box = dir1
×
380
        button1 = QPushButton("Change Directory")
×
381
        button1.clicked.connect(select_dir)
×
382

383
        msg2 = ("If checked, then the files will"
×
384
                + " only be downloaded. If unchecked, then they will also"
385
                + " be read and loaded into pytplot variables.")
386
        check1 = QCheckBox("Download Only")
×
387
        check1.setToolTip(msg2)
×
388
        check1.setChecked(True)
×
389
        buttondown = QPushButton("3. Get Data")
×
390
        buttondown.setStyleSheet(self.button_css)
×
391
        buttondown.clicked.connect(button3_get_data)
×
392

393
        buttonclear = QPushButton("Clear")
×
394
        buttonclear.setStyleSheet(self.clear_css)
×
395
        buttonclear.clicked.connect(clear_all)
×
396

397
        buttonexit = QPushButton("Exit")
×
398
        buttonexit.setStyleSheet(self.clear_css)
×
399
        buttonexit.clicked.connect(exit_all)
×
400

401
        layout = QGridLayout()
×
402
        layout.addWidget(list1, 0, 0, 1, 6)
×
403
        layout.addWidget(label1, 1, 0, 1, 1)
×
404
        layout.addWidget(dir1, 1, 1, 1, 4)
×
405
        layout.addWidget(button1, 1, 5, 1, 1)
×
406
        layout.addWidget(check1, 2, 0, 1, 2)
×
407
        layout.addWidget(buttondown, 2, 2, 1, 2)
×
408
        layout.addWidget(buttonclear, 2, 4, 1, 1)
×
409
        layout.addWidget(buttonexit, 2, 5, 1, 1)
×
410

411
        # Button1 action
412

413
        self.dirGroupBox.setLayout(layout)
×
414

415
    def initUI(self):
×
416
        """Create GUI."""
417
        # Main layout is vertical
418
        grid = QVBoxLayout()
×
419
        self.setLayout(grid)
×
420

421
        # Top label
422
        label1 = QLabel("Download Data from CDAWeb")
×
423
        label1.setStyleSheet(self.title_css)
×
424
        label1.setAlignment(Qt.AlignCenter)
×
425
        label1.setMaximumHeight(20)
×
426
        grid.addWidget(label1)
×
427

428
        # 1. Create missions and instruments group
429
        self.createMissionGroupBox()
×
430
        grid.addWidget(self.missionGroupBox)
×
431

432
        # 2. Create dataset group
433
        self.createDatasetBox()
×
434
        grid.addWidget(self.datasetGroupBox)
×
435

436
        # 3. Create datetime group
437
        self.createTimeGroupBox()
×
438
        grid.addWidget(self.timeGroupBox)
×
439

440
        # 4. Create download group
441
        self.createDownloadGroupBox()
×
442
        grid.addWidget(self.dirGroupBox)
×
443

444
        self.showMaximized()
×
445

446

447
if __name__ == '__main__':
×
448

449
    app = QCoreApplication.instance()
×
450
    if app is None:
×
451
        app = QApplication(sys.argv)
×
452

453
    cdagui = cdagui()
×
454
    sys.exit(app.exec_())
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc