Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
sec23
korte
pymagglobal
Commits
a986b897
Commit
a986b897
authored
Aug 11, 2021
by
Maximilian Schanner
Browse files
Annotation and minors.
parent
2cd05488
Changes
1
Hide whitespace changes
Inline
Side-by-side
pymagglobal/GUI.py
View file @
a986b897
...
...
@@ -26,7 +26,8 @@ from pathlib import Path
from
PyQt5.QtCore
import
Qt
from
PyQt5.QtWidgets
import
QApplication
,
QWidget
,
QPushButton
,
QLabel
,
\
QLineEdit
,
QVBoxLayout
,
QHBoxLayout
,
QComboBox
,
QFrame
,
QFileDialog
QLineEdit
,
QVBoxLayout
,
QHBoxLayout
,
QComboBox
,
QFrame
,
QFileDialog
,
\
QRadioButton
from
PyQt5.QtGui
import
QDoubleValidator
,
QValidator
import
matplotlib
...
...
@@ -47,9 +48,9 @@ titleStyle = 'font-size: 18pt; font-weight: bold;'
class
MainWindow
(
QWidget
):
def
__init__
(
self
,
parser
):
def
__init__
(
self
):
super
().
__init__
()
self
.
parser
=
parser
self
.
parser
=
argument_
parser
()
self
.
saveWindow
=
SaveWindow
()
self
.
initUI
()
...
...
@@ -113,43 +114,46 @@ class MainWindow(QWidget):
self
.
show
()
def
updateModel
(
self
):
''' updates the model, when the selected model changes '''
model
=
Model
(
self
.
modelSelector
.
currentText
())
# update the range
self
.
epoch
.
min
=
model
.
t_min
self
.
epoch
.
min
=
model
.
t_max
self
.
epoch
.
default
=
int
((
model
.
t_max
+
model
.
t_min
)
/
2
)
self
.
range
.
setText
(
f
'[
{
model
.
t_min
}
,
{
model
.
t_max
}
]'
)
# update the model for saving
self
.
saveWindow
.
model
=
model
def
modelSelect
(
self
):
''' Model selection widget '''
#
T
itle string
#
t
itle string
title
=
QLabel
(
'Select model'
)
title
.
setStyleSheet
(
titleStyle
)
title
.
setAlignment
(
Qt
.
AlignCenter
)
#
D
rop down menu
#
d
rop down menu
self
.
modelSelector
=
QComboBox
()
self
.
modelSelector
.
addItems
(
built_in_models
().
keys
())
self
.
modelSelector
.
currentIndexChanged
.
connect
(
self
.
updateModel
)
self
.
modelSelector
.
currentIndexChanged
.
connect
(
self
.
plotDipole
)
self
.
modelSelector
.
setFixedHeight
(
25
)
# HOTFIX: this fixed scaling issues with the text...
self
.
modelSelector
.
setStyleSheet
(
"QAbstractItemView {"
" selection-background-color:"
" lightgray;"
"}"
)
#
S
how the model range
#
s
how the model range
rangeLabel
=
QLabel
(
'Time range (yrs.):'
)
rangeLabel
.
setAlignment
(
Qt
.
AlignCenter
)
self
.
range
=
QLabel
()
self
.
range
.
setAlignment
(
Qt
.
AlignCenter
)
#
P
ut into widget
#
p
ut into widget
hbox
=
QVBoxLayout
()
hbox
.
addWidget
(
title
)
hbox
.
addWidget
(
self
.
modelSelector
)
hbox
.
addWidget
(
rangeLabel
)
hbox
.
addWidget
(
self
.
range
)
hbox
.
setAlignment
(
Qt
.
AlignTop
)
# return a widget containing the selector
q
=
QWidget
()
q
.
setLayout
(
hbox
)
q
.
setFixedHeight
(
140
)
...
...
@@ -157,11 +161,11 @@ class MainWindow(QWidget):
def
localMenu
(
self
):
''' Local plot widget '''
#
T
itle string
#
t
itle string
title
=
QLabel
(
'Local plots'
)
title
.
setStyleSheet
(
titleStyle
)
title
.
setAlignment
(
Qt
.
AlignCenter
)
#
L
at lon input fields
#
l
at
and
lon input fields
latLonLabel
=
QLabel
(
'Position (lat, lon)'
)
latLonLabel
.
setAlignment
(
Qt
.
AlignCenter
)
...
...
@@ -171,12 +175,26 @@ class MainWindow(QWidget):
self
.
lon
=
QRangeEdit
(
'0'
,
-
180
,
180
)
self
.
lon
.
setFixedWidth
(
50
)
self
.
lon
.
setFixedHeight
(
22
)
# set up a layout (looks nicer than adding the widgets directly)
latLonBox
=
QHBoxLayout
()
latLonBox
.
addWidget
(
self
.
lat
)
latLonBox
.
addWidget
(
self
.
lon
)
latLonWidget
=
QWidget
()
latLonWidget
.
setLayout
(
latLonBox
)
# radio buttons for field type
typeLabel
=
QLabel
(
'Field type'
)
typeLabel
.
setAlignment
(
Qt
.
AlignCenter
)
self
.
locNezButton
=
QRadioButton
(
"NEZ"
)
self
.
locDifButton
=
QRadioButton
(
"DIF"
)
self
.
locDifButton
.
setChecked
(
True
)
# set up a layout
typeBox
=
QHBoxLayout
()
typeBox
.
addWidget
(
self
.
locNezButton
)
typeBox
.
addWidget
(
self
.
locDifButton
)
typeBox
.
setAlignment
(
Qt
.
AlignCenter
)
typeWidget
=
QWidget
()
typeWidget
.
setLayout
(
typeBox
)
# Plot button
sButton
=
QPushButton
(
'Plot local'
)
sButton
.
clicked
.
connect
(
self
.
plotLocal
)
...
...
@@ -185,94 +203,142 @@ class MainWindow(QWidget):
vbox
.
addWidget
(
title
)
vbox
.
addWidget
(
latLonLabel
)
vbox
.
addWidget
(
latLonWidget
)
vbox
.
addWidget
(
typeLabel
)
vbox
.
addWidget
(
typeWidget
)
vbox
.
addWidget
(
sButton
)
vbox
.
setAlignment
(
Qt
.
AlignTop
)
# return a widget containing the local stuff
q
=
QWidget
()
q
.
setLayout
(
vbox
)
q
.
setFixedHeight
(
18
0
)
q
.
setFixedHeight
(
24
0
)
return
q
def
globalMenu
(
self
):
'''
Loc
al plot widget '''
#
T
itle string
'''
Glob
al plot widget '''
#
t
itle string
title
=
QLabel
(
'Global plots'
)
title
.
setStyleSheet
(
titleStyle
)
title
.
setAlignment
(
Qt
.
AlignCenter
)
#
E
poch input field
#
e
poch input field
epochLabel
=
QLabel
(
'Epoch [yrs.]'
)
epochLabel
.
setAlignment
(
Qt
.
AlignCenter
)
self
.
epoch
=
QRangeEdit
(
'1900'
,
-
1000
,
2000
)
self
.
epoch
.
setFixedWidth
(
100
)
self
.
epoch
.
setFixedHeight
(
22
)
# radio buttons for field type
typeLabel
=
QLabel
(
'Field type'
)
typeLabel
.
setAlignment
(
Qt
.
AlignCenter
)
self
.
mapNezButton
=
QRadioButton
(
"NEZ"
)
self
.
mapDifButton
=
QRadioButton
(
"DIF"
)
self
.
mapDifButton
.
setChecked
(
True
)
typeBox
=
QHBoxLayout
()
typeBox
.
addWidget
(
self
.
mapNezButton
)
typeBox
.
addWidget
(
self
.
mapDifButton
)
typeBox
.
setAlignment
(
Qt
.
AlignCenter
)
typeWidget
=
QWidget
()
typeWidget
.
setLayout
(
typeBox
)
# redundant, but looks better as the location selector is in a hbox
epochBox
=
QHBoxLayout
()
epochBox
.
addWidget
(
self
.
epoch
)
epochWidget
=
QWidget
()
epochWidget
.
setLayout
(
epochBox
)
#
B
uttons for map and dipole
#
b
uttons for map and dipole
gButton
=
QPushButton
(
'Plot map'
)
gButton
.
clicked
.
connect
(
self
.
plotMap
)
dButton
=
QPushButton
(
'Plot dipole'
)
dButton
.
clicked
.
connect
(
self
.
plotDipole
)
#
P
ut into widget
#
p
ut into widget
vbox
=
QVBoxLayout
()
vbox
.
addWidget
(
title
)
vbox
.
addWidget
(
epochLabel
)
vbox
.
addWidget
(
epochWidget
)
vbox
.
addWidget
(
typeLabel
)
vbox
.
addWidget
(
typeWidget
)
vbox
.
addWidget
(
gButton
)
vbox
.
addWidget
(
dButton
)
vbox
.
setAlignment
(
Qt
.
AlignTop
)
# return a widget containing the global stuff
q
=
QWidget
()
q
.
setLayout
(
vbox
)
q
.
setFixedHeight
(
2
0
0
)
q
.
setFixedHeight
(
2
7
0
)
return
q
def
saveMenu
(
self
):
''' Save button widget '''
# title string
title
=
QLabel
(
'Model output'
)
title
.
setStyleSheet
(
titleStyle
)
title
.
setAlignment
(
Qt
.
AlignCenter
)
# the button will open another window, which handles the output
gButton
=
QPushButton
(
'Generate'
)
gButton
.
clicked
.
connect
(
self
.
saveWindow
.
show
)
vbox
=
QVBoxLayout
()
vbox
.
addWidget
(
title
)
vbox
.
addWidget
(
gButton
)
# return the save button widget
q
=
QWidget
()
q
.
setLayout
(
vbox
)
q
.
setFixedHeight
(
120
)
return
q
def
plotLocal
(
self
):
''' This will update the plotting section, when the plot local button
is pressed. It basically turns the inputs into arguments for the CLI.
'''
# clear the figure
self
.
fig
.
clf
()
# get the field type
if
self
.
locDifButton
.
isChecked
():
_type
=
'dif'
else
:
_type
=
'nez'
# run the _command with the respective arguments
local_curve
(
self
.
parser
.
parse_args
([
'local'
,
'--type'
,
_type
,
self
.
lat
.
text
(),
self
.
lon
.
text
(),
self
.
modelSelector
.
currentText
()]),
fig
=
self
.
fig
)
# update the plotting canvas
self
.
canvas
.
draw
()
def
plotMap
(
self
):
''' This will update the plotting section, when the plot map button
is pressed. It basically turns the inputs into arguments for the CLI.
'''
# clear the figure
self
.
fig
.
clf
()
# set up and configure grid for the maps
self
.
fig
.
add_subplot
(
221
,
projection
=
ccrs
.
Mollweide
())
self
.
fig
.
add_subplot
(
222
,
projection
=
ccrs
.
Mollweide
())
self
.
fig
.
add_subplot
(
212
,
projection
=
ccrs
.
Mollweide
())
self
.
fig
.
tight_layout
()
self
.
fig
.
subplots_adjust
(
top
=
0.9
,
bottom
=
0.1
,
hspace
=
0.4
)
# get the field type
if
self
.
mapDifButton
.
isChecked
():
_type
=
'dif'
else
:
_type
=
'nez'
# run the _command with the respective arguments
maps
(
self
.
parser
.
parse_args
([
'map'
,
'--type'
,
_type
,
self
.
epoch
.
text
(),
self
.
modelSelector
.
currentText
()]),
fig
=
self
.
fig
)
# update the canvas
self
.
canvas
.
draw
()
def
plotDipole
(
self
):
''' This will update the plotting section, when the plot dipole button
is pressed. It basically turns the inputs into arguments for the CLI.
'''
self
.
fig
.
clf
()
dipole_series
(
self
.
parser
.
parse_args
([
'dipole'
,
self
.
modelSelector
...
...
@@ -284,25 +350,28 @@ class MainWindow(QWidget):
class
SaveWindow
(
QWidget
):
def
__init__
(
self
):
''' This is another window, handling the output '''
super
().
__init__
()
# set up a custom parser
self
.
parser
=
argument_parser
()
# set up an initial model
self
.
model
=
Model
(
'gufm1'
)
# configure the window
self
.
resize
(
300
,
300
)
self
.
setWindowTitle
(
'pymagglobal - output'
)
# set up a dict for the dropdown menu
self
.
selectorDict
=
{
'model coefficients at an epoch'
:
'coeffs-epoch'
,
'field values at a specific location'
:
'local'
}
# drop down menu of what to store
self
.
typeSelector
=
QComboBox
()
self
.
typeSelector
.
addItems
(
self
.
selectorDict
.
keys
())
self
.
typeSelector
.
currentIndexChanged
.
connect
(
self
.
updateInputBox
)
# title string
info
=
QLabel
(
'I want to store'
)
info
.
setAlignment
(
Qt
.
AlignLeft
)
# dummy widget, will be updated according to the dropdown
self
.
inputWidget
=
QLabel
()
# a button for storing
gButton
=
QPushButton
(
'Store'
)
gButton
.
clicked
.
connect
(
self
.
save
)
...
...
@@ -320,28 +389,42 @@ class SaveWindow(QWidget):
self
.
updateInputBox
()
def
save
(
self
):
''' This will assemble the selections and pass them to the
argument_parser '''
# get the type of output
selected
=
self
.
selectorDict
[
self
.
typeSelector
.
currentText
()]
# depending on the type of output, assemble the arguments
if
selected
==
'local'
:
params
=
self
.
lat
.
text
()
+
' '
+
self
.
lon
.
text
()
if
self
.
saveDifButton
.
isChecked
():
_type
=
'dif'
else
:
_type
=
'nez'
params
=
'--type '
+
_type
+
' '
+
self
.
lat
.
text
()
+
' '
\
+
self
.
lon
.
text
()
elif
selected
==
'coeffs-epoch'
:
params
=
self
.
epoch
.
text
()
else
:
params
=
'XXX'
# get an ouput filename
fname
,
_
=
QFileDialog
.
getSaveFileName
(
self
,
'Choose filename'
,
str
(
Path
.
home
()))
# fname will be empty, if the cancel button is pressed or the dialog
# is closed. In this case, go back to the window (do nothing)
# otherwise, pass the arguments to the parser and close
if
fname
!=
''
:
parse
=
selected
+
' --no-show --output '
+
fname
+
' '
+
params
\
+
' '
+
self
.
model
.
name
parse
=
selected
+
' --no-show --output '
+
fname
+
' '
+
params
\
+
' '
+
self
.
model
.
name
args
=
self
.
parser
.
parse_args
(
parse
.
split
())
args
.
func
(
args
)
self
.
close
()
args
=
self
.
parser
.
parse_args
(
parse
.
split
())
args
.
func
(
args
)
self
.
close
()
def
updateInputBox
(
self
):
''' This will update the argument inputs, depending on the dropdown
selection '''
# first clear the widget
self
.
inputWidget
.
deleteLater
()
# get the input
selected
=
self
.
selectorDict
[
self
.
typeSelector
.
currentText
()]
# according to the input, set up a new widget
if
selected
==
'local'
:
self
.
inputWidget
=
self
.
locSelector
()
elif
selected
==
'coeffs-epoch'
:
...
...
@@ -349,11 +432,14 @@ class SaveWindow(QWidget):
else
:
self
.
inputWidget
=
QLabel
(
self
.
selectorDict
[
self
.
typeSelector
.
currentText
()])
# insert the widget after the dropdown (position 3)
self
.
swBox
.
insertWidget
(
3
,
self
.
inputWidget
)
# update
self
.
swBox
.
update
()
self
.
updateGeometry
()
def
locSelector
(
self
):
''' The argument widget for local output '''
latLonLabel
=
QLabel
(
'Position (lat, lon)'
)
latLonLabel
.
setAlignment
(
Qt
.
AlignCenter
)
...
...
@@ -368,10 +454,26 @@ class SaveWindow(QWidget):
latLonWidget
=
QWidget
()
latLonWidget
.
setLayout
(
latLonBox
)
# Radio buttons for field type
typeLabel
=
QLabel
(
'Field type'
)
typeLabel
.
setAlignment
(
Qt
.
AlignCenter
)
self
.
saveNezButton
=
QRadioButton
(
"NEZ"
)
self
.
saveDifButton
=
QRadioButton
(
"DIF"
)
self
.
saveDifButton
.
setChecked
(
True
)
typeBox
=
QHBoxLayout
()
typeBox
.
addWidget
(
self
.
saveNezButton
)
typeBox
.
addWidget
(
self
.
saveDifButton
)
typeBox
.
setAlignment
(
Qt
.
AlignCenter
)
typeWidget
=
QWidget
()
typeWidget
.
setLayout
(
typeBox
)
# Put into widget
vbox
=
QVBoxLayout
()
vbox
.
addWidget
(
latLonLabel
)
vbox
.
addWidget
(
latLonWidget
)
vbox
.
addWidget
(
typeLabel
)
vbox
.
addWidget
(
typeWidget
)
vbox
.
setAlignment
(
Qt
.
AlignTop
)
q
=
QWidget
()
...
...
@@ -379,6 +481,7 @@ class SaveWindow(QWidget):
return
q
def
epochSelector
(
self
):
''' The argument widget for coefficient output '''
epochLabel
=
QLabel
(
'Epoch [yrs.]'
)
epochLabel
.
setAlignment
(
Qt
.
AlignCenter
)
...
...
@@ -415,6 +518,8 @@ class QHLine(QFrame):
class
QRangeEdit
(
QLineEdit
):
''' A line edit that checks for input in a given range. If the input is
outside, a default value will be inserted. '''
def
__init__
(
self
,
init
,
_min
,
_max
,
default
=
0
):
super
().
__init__
(
init
)
self
.
min
=
_min
...
...
@@ -437,9 +542,10 @@ def main():
app
.
setStyleSheet
(
"QLabel{font-size: 16pt;}"
"QComboBox{font-size: 16pt;}"
"QPushButton{font-size: 16pt;}"
"QRadioButton{font-size: 16pt; height: 100px}"
"QLineEdit{font-size: 16pt;}"
)
_
=
MainWindow
(
argument_parser
()
)
_
=
MainWindow
()
sys
.
exit
(
app
.
exec_
())
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment