Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
H
HEV - High Energy Ventilator
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
5
Issues
5
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
HEV - High Energy Ventilator
Commits
944d3d5f
Commit
944d3d5f
authored
Apr 19, 2021
by
Benjamin Mummery
💻
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ui_dev' of
https://ohwr.org/project/hev
into ui_dev
parents
8b4110b1
0a7f7ac2
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
353 additions
and
111 deletions
+353
-111
NativeUI.py
NativeUI/NativeUI.py
+90
-24
test_NativeUI.py
NativeUI/tests/unittests/test_NativeUI.py
+30
-21
ui_layout.py
NativeUI/ui_layout.py
+22
-2
ui_widgets.py
NativeUI/ui_widgets.py
+21
-14
chart_buttons_widget.py
NativeUI/widget_library/chart_buttons_widget.py
+91
-0
history_buttons_widget.py
NativeUI/widget_library/history_buttons_widget.py
+1
-1
measurements_widget.py
NativeUI/widget_library/measurements_widget.py
+6
-8
plot_widget.py
NativeUI/widget_library/plot_widget.py
+92
-13
tab_charts.py
NativeUI/widget_library/tab_charts.py
+0
-28
No files found.
NativeUI/NativeUI.py
View file @
944d3d5f
...
...
@@ -18,26 +18,23 @@ __email__ = "benjamin.mummery@stfc.ac.uk"
__status__
=
"Prototype"
import
argparse
import
git
import
json
import
logging
import
sys
import
os
from
PySide2
import
QtCore
import
re
import
sys
from
threading
import
Lock
import
git
import
numpy
as
np
from
global_widgets.global_send_popup
import
confirmPopup
from
hevclient
import
HEVClient
from
ui_layout
import
Layout
from
ui_widgets
import
Widgets
from
threading
import
Lock
from
PySide2
import
QtCore
from
PySide2.QtCore
import
Signal
,
Slot
from
PySide2.QtGui
import
QColor
,
QFont
,
QPalette
from
PySide2.QtWidgets
import
QApplication
,
QMainWindow
,
QWidget
from
ui_layout
import
Layout
from
ui_widgets
import
Widgets
logging
.
basicConfig
(
level
=
logging
.
WARNING
,
format
=
"
%(asctime)
s -
%(levelname)
s -
%(message)
s"
...
...
@@ -47,7 +44,9 @@ logging.basicConfig(
class
NativeUI
(
HEVClient
,
QMainWindow
):
"""Main application with client logic"""
battery_signal
=
Signal
()
BatterySignal
=
Signal
(
dict
)
PlotSignal
=
Signal
(
dict
)
MeasurementSignal
=
Signal
(
dict
,
dict
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
NativeUI
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
...
...
@@ -173,35 +172,102 @@ class NativeUI(HEVClient, QMainWindow):
self
.
__define_connections
()
@
Slot
(
str
)
def
change_page
(
self
,
page_to_show
:
str
):
def
change_page
(
self
,
page_to_show
:
str
)
->
int
:
"""
Change the page shown in page_stack.
"""
self
.
widgets
.
page_stack
.
setCurrentWidget
(
getattr
(
self
.
widgets
,
page_to_show
))
return
0
def
__define_connections
(
self
):
def
__define_connections
(
self
)
->
int
:
"""
Connect the signals and slots necessary for the UI to function.
Connections defined here:
BatterySignal -> battery_display
BatterySignal is emitted in get_updates() in response to a battery payload.
HistoryButtonPressed -> normal_plots, detailed_plots
History buttons control the amount of time shown on the x axes of the
value-time plots on the main page. HistoryButtonPressed is emitted by the
history button when pressed.
PageButtonPressed -> change_page
Page buttons control which page is shown in the page_stack.
PageButtonPressed is emitted by the page button when pressed.
ToggleButtonPressed -> charts_widget.show_line
ToggleButtonPressed -> charts_widget.hide_line
Lines in the charts_widget are shown or hidden depending on whether the
relevent toggle button is in the checked or unchecked state.
ToggleButtonPressed is emitted by the toggle button when pressed.
PlotSignal -> normal_plots, detailed_plots, charts_widget
Data plotted in the normal, detailed, and charts plots is updated in
response to PlotSignal. PlotSignal is emitted in __emit_plots_signal() which
is triggered at timer.timeout.
MeasurementSignal -> normal_measurements, detailed_measurements
Data shown in the normal and detailed measurments widgets is updated in
response to MeasurementSignal. MeasurementSignal is emitted in
__emit_measurements_signal() which is triggered at timer.timeout.
"""
# Battery Display should update when we get battery info
self
.
battery_s
ignal
.
connect
(
self
.
widgets
.
battery_display
.
update_value
)
self
.
BatteryS
ignal
.
connect
(
self
.
widgets
.
battery_display
.
update_value
)
# Plots should update when we press the history buttons
for
button
in
self
.
widgets
.
history_buttons
.
buttons
:
for
widget
in
[
self
.
widgets
.
normal_plots
,
self
.
widgets
.
detailed_plots
]:
button
.
HistoryButtonPressed
.
connect
(
widget
.
update_plot_time_range
)
# The shown page should change when we press the page buttons
for
button
in
self
.
widgets
.
page_buttons
.
buttons
:
button
.
PageButtonPressed
.
connect
(
self
.
change_page
)
# Plot data should update on a timer
# TODO: make this actually grab the data and send it to the plots, rather than
# having the plots reach to NativeUI for the data.
# Lines displayed on the charts page should update when the corresponding
# buttons are toggled.
for
button
in
self
.
widgets
.
chart_buttons_widget
.
buttons
:
button
.
ToggleButtonPressed
.
connect
(
self
.
widgets
.
charts_widget
.
show_line
)
button
.
ToggleButtonReleased
.
connect
(
self
.
widgets
.
charts_widget
.
hide_line
)
button
.
on_press
()
# Ensure states of the plots match states of buttons.
button
.
toggle
()
# Plot data and measurements should update on a timer
self
.
timer
=
QtCore
.
QTimer
()
self
.
timer
.
setInterval
(
16
)
# just faster than 60Hz
self
.
timer
.
timeout
.
connect
(
self
.
widgets
.
normal_plots
.
update_plot_data
)
self
.
timer
.
timeout
.
connect
(
self
.
widgets
.
detailed_plots
.
update_plot_data
)
self
.
timer
.
timeout
.
connect
(
self
.
widgets
.
normal_measurements
.
update_value
)
self
.
timer
.
timeout
.
connect
(
self
.
widgets
.
detailed_measurements
.
update_value
)
self
.
timer
.
timeout
.
connect
(
self
.
__emit_plots_signal
)
self
.
timer
.
timeout
.
connect
(
self
.
__emit_measurements_signal
)
self
.
timer
.
timeout
.
connect
(
self
.
widgets
.
alarm_tab
.
update_alarms
)
self
.
timer
.
start
()
def
get_db
(
self
,
database_name
:
str
):
# When plot data is updated, plots should update
self
.
PlotSignal
.
connect
(
self
.
widgets
.
normal_plots
.
update_plot_data
)
self
.
PlotSignal
.
connect
(
self
.
widgets
.
detailed_plots
.
update_plot_data
)
self
.
PlotSignal
.
connect
(
self
.
widgets
.
charts_widget
.
update_plot_data
)
# When measurement data is updated, measurement widgets shouldupdate
self
.
MeasurementSignal
.
connect
(
self
.
widgets
.
normal_measurements
.
update_value
)
self
.
MeasurementSignal
.
connect
(
self
.
widgets
.
detailed_measurements
.
update_value
)
return
0
def
__emit_plots_signal
(
self
)
->
int
:
"""
Get the current status of the 'plots' db and emit the plot_signal signal.
"""
self
.
PlotSignal
.
emit
(
self
.
get_db
(
"plots"
))
return
0
def
__emit_measurements_signal
(
self
)
->
int
:
"""
Get the current status of the 'cycle' and 'readback' dbs and emit the
measurements_signal signal.
"""
self
.
MeasurementSignal
.
emit
(
self
.
get_db
(
"cycle"
),
self
.
get_db
(
"readback"
))
return
0
def
get_db
(
self
,
database_name
:
str
)
->
str
:
"""
Return the contents of the specified database dict, assuming that it is present
in __database_list.
...
...
@@ -370,8 +436,8 @@ class NativeUI(HEVClient, QMainWindow):
self
.
set_plots_db
(
payload
[
"DATA"
])
self
.
ongoingAlarms
=
payload
[
"alarms"
]
if
payload
[
"type"
]
==
"BATTERY"
:
self
.
set_battery_db
(
payload
[
"BATTERY"
])
self
.
battery_signal
.
emit
(
)
self
.
__set_db
(
"battery"
,
payload
[
"BATTERY"
])
self
.
BatterySignal
.
emit
(
self
.
get_db
(
"battery"
)
)
if
payload
[
"type"
]
==
"ALARM"
:
self
.
set_alarms_db
(
payload
[
"ALARM"
])
if
payload
[
"type"
]
==
"TARGET"
:
...
...
NativeUI/tests/unittests/test_NativeUI.py
View file @
944d3d5f
#! /usr/bin/env python3
import
pytest
import
sys
"""
Unit tests for NativeUI
"""
import
json
from
PySide2.QtWidgets
import
QApplication
import
sys
import
hevclient
import
numpy
as
np
import
pytest
from
PySide2.QtWidgets
import
QApplication
sys
.
path
.
append
(
"../.."
)
from
NativeUI
import
NativeUI
import
hevclient
hevclient
.
mmFileName
=
"/home/pi/hev/NativeUI/tests/integration/fixtures/HEVClient_lastData.mmap"
sys
.
path
.
append
(
"../.."
)
hevclient
.
mmFileName
=
(
"/home/pi/hev/NativeUI/tests/integration/fixtures/HEVClient_lastData.mmap"
)
@
pytest
.
fixture
(
scope
=
"session"
,
autouse
=
True
)
def
widget
():
app
=
QApplication
(
sys
.
argv
)
widget
=
NativeUI
()
return
widget
return
NativeUI
()
# Test default values of databases(no set method involved)
...
...
@@ -63,7 +69,7 @@ def test_must_return_correct_db_item_from_get_db_plots(widget):
def
test_must_return_correct_db_item_from_get_db_alarms
(
widget
):
assert
widget
.
get_db
(
"__alarms"
)
==
[]
and
widget
.
get_db
(
"alarms"
)
==
[]
assert
widget
.
get_db
(
"__alarms"
)
==
{}
and
widget
.
get_db
(
"alarms"
)
==
{}
def
test_must_return_correct_db_item_from_get_db_targets
(
widget
):
...
...
@@ -78,44 +84,46 @@ def test_must_return_correct_db_item_from_get_db_personal(widget):
def
test_must_return_0_for_set_data_db
(
widget
):
with
open
(
"/home/pi/hev/samples/dataSample.json"
,
"r"
)
as
f
:
data_payload
=
json
.
load
(
f
)
assert
widget
.
set_data_db
(
data_payload
)
==
0
assert
widget
.
__set_db
(
"data"
,
data_payload
)
==
0
def
test_must_return_0_for_set_targets_db
(
widget
):
with
open
(
"/home/pi/hev/samples/targetSample.json"
,
"r"
)
as
g
:
target_payload
=
json
.
load
(
g
)
assert
widget
.
set_targets_db
(
target_payload
)
==
0
assert
widget
.
__set_db
(
"targets"
,
target_payload
)
==
0
def
test_must_return_0_for_set_readback_db
(
widget
):
with
open
(
"/home/pi/hev/samples/readbackSample.json"
,
"r"
)
as
f
:
readback_payload
=
json
.
load
(
f
)
assert
widget
.
set_readback_db
(
readback_payload
)
==
0
assert
widget
.
__set_db
(
"readback"
,
readback_payload
)
==
0
def
test_must_return_0_for_set_cycle_db
(
widget
):
with
open
(
"/home/pi/hev/NativeUI/tests/unittests/fixtures/cycleSample.json"
,
"r"
)
as
f
:
with
open
(
"/home/pi/hev/NativeUI/tests/unittests/fixtures/cycleSample.json"
,
"r"
)
as
f
:
cycle_payload
=
json
.
load
(
f
)
assert
widget
.
set_cycle_db
(
cycle_payload
)
==
0
assert
widget
.
__set_db
(
"cycle"
,
cycle_payload
)
==
0
def
test_must_return_0_for_set_battery_db
(
widget
):
with
open
(
"/home/pi/hev/samples/batterySample.json"
,
"r"
)
as
f
:
battery_payload
=
json
.
load
(
f
)
assert
widget
.
set_battery_db
(
battery_payload
)
==
0
assert
widget
.
__set_db
(
"battery"
,
battery_payload
)
==
0
def
test_must_return_0_for_set_plots_db
(
widget
):
with
open
(
"/home/pi/hev/samples/dataSample.json"
,
"r"
)
as
f
:
data_payload
=
json
.
load
(
f
)
assert
widget
.
set_plots_db
(
data_payload
)
==
0
assert
widget
.
__
set_plots_db
(
data_payload
)
==
0
def
test_must_return_error_if_not_data_is_sent_as_payload_for_set_plots_db
(
widget
):
with
open
(
"/home/pi/hev/samples/batterySample.json"
,
"r"
)
as
f
:
battery_payload
=
json
.
load
(
f
)
with
pytest
.
raises
(
KeyError
):
widget
.
set_plots_db
(
battery_payload
)
widget
.
__
set_plots_db
(
battery_payload
)
def
test_must_return_0_when__update_plot_ranges_correctly
(
widget
):
...
...
@@ -125,13 +133,15 @@ def test_must_return_0_when__update_plot_ranges_correctly(widget):
def
test_must_return_0_for_set_alarms_db
(
widget
):
with
open
(
"/home/pi/hev/samples/alarmSample.json"
,
"r"
)
as
f
:
alarm_payload
=
json
.
load
(
f
)
assert
widget
.
set_alarms_db
(
alarm_payload
)
==
0
assert
widget
.
__set_db
(
"alarms"
,
alarm_payload
)
==
0
def
test_must_return_0_for_set_personal_db
(
widget
):
with
open
(
"/home/pi/hev/NativeUI/tests/unittests/fixtures/personalSample.json"
,
"r"
)
as
f
:
with
open
(
"/home/pi/hev/NativeUI/tests/unittests/fixtures/personalSample.json"
,
"r"
)
as
f
:
personal_payload
=
json
.
load
(
f
)
assert
widget
.
set_personal_db
(
personal_payload
)
==
0
assert
widget
.
__set_db
(
"personal"
,
personal_payload
)
==
0
# Asyncio can handle event loops, but we need to add more interaction i think
...
...
@@ -183,4 +193,3 @@ def test_must_return_0_when__find_icons_svg_directory(widget):
def
test_must_return_0_when_cannot__find_icons_directory
(
widget
):
with
pytest
.
raises
(
FileNotFoundError
):
widget
.
__find_icons
(
"images"
)
NativeUI/ui_layout.py
View file @
944d3d5f
...
...
@@ -190,7 +190,11 @@ class Layout:
"""
page_alarms
=
SwitchableStackWidget
(
self
.
NativeUI
,
[
self
.
widgets
.
alarm_tab
,
self
.
widgets
.
alarm_table_tab
,
self
.
widgets
.
clinical_tab
],
[
self
.
widgets
.
alarm_tab
,
self
.
widgets
.
alarm_table_tab
,
self
.
widgets
.
clinical_tab
,
],
[
"List of Alarms"
,
"Alarm Table"
,
"Clinical Limits"
],
)
page_alarms
.
setFont
(
self
.
NativeUI
.
text_font
)
...
...
@@ -200,9 +204,17 @@ class Layout:
"""
Layout for the settings page.
"""
# Create the Charts tab
tab_charts
=
self
.
layout_tab_charts
(
[
self
.
widgets
.
charts_widget
,
self
.
widgets
.
chart_buttons_widget
]
)
self
.
widgets
.
chart_buttons_widget
.
setFont
(
self
.
NativeUI
.
text_font
)
self
.
widgets
.
chart_buttons_widget
.
set_size
(
self
.
left_bar_width
,
None
)
# Create the stack
page_settings
=
SwitchableStackWidget
(
self
.
NativeUI
,
[
self
.
widgets
.
settings_expert_tab
,
self
.
widgets
.
settings_chart_tab
],
[
self
.
widgets
.
settings_expert_tab
,
tab_charts
],
[
"Expert"
,
"Charts"
],
)
page_settings
.
setFont
(
self
.
NativeUI
.
text_font
)
...
...
@@ -279,6 +291,14 @@ class Layout:
tab_main_detailed
.
setLayout
(
tab_main_detailed_layout
)
return
tab_main_detailed
def
layout_tab_charts
(
self
,
widgets
:
list
)
->
QtWidgets
.
QWidget
:
tab_charts
=
QtWidgets
.
QWidget
()
tab_charts_layout
=
QtWidgets
.
QHBoxLayout
(
tab_charts
)
for
widget
in
widgets
:
tab_charts_layout
.
addWidget
(
widget
)
tab_charts
.
setLayout
(
tab_charts_layout
)
return
tab_charts
def
__make_stack
(
self
,
widgets
):
"""
Make a stack of widgets
...
...
NativeUI/ui_widgets.py
View file @
944d3d5f
...
...
@@ -13,29 +13,34 @@ __maintainer__ = "Benjamin Mummery"
__email__
=
"benjamin.mummery@stfc.ac.uk"
__status__
=
"Prototype"
from
PySide2.QtWidgets
import
QWidget
from
alarm_widgets.tab_alarm_table
import
TabAlarmTable
from
alarm_widgets.tab_alarms
import
TabAlarm
from
alarm_widgets.tab_clinical
import
TabClinical
from
global_widgets.tab_modeswitch_button
import
TabModeswitchButton
from
mode_widgets.tab_modes
import
TabModes
from
mode_widgets.tab_personal
import
TabPersonal
from
PySide2.QtWidgets
import
QWidget
from
widget_library.battery_display_widget
import
BatteryDisplayWidget
# from widget_library.tab_charts import TabChart
from
widget_library.chart_buttons_widget
import
ChartButtonsWidget
from
widget_library.history_buttons_widget
import
HistoryButtonsWidget
from
widget_library.measurements_widget
import
(
NormalMeasurementsBlockWidget
,
ExpertMeasurementsBloackWidget
,
NormalMeasurementsBlockWidget
,
)
from
widget_library.plot_widget
import
TimePlotsWidget
,
CirclePlotsWidget
from
widget_library.spin_buttons_widget
import
SpinButtonsWidget
from
widget_library.page_buttons_widget
import
PageButtonsWidget
from
widget_library.personal_display_widget
import
PersonalDisplayWidget
from
widget_library.battery_display_widget
import
BatteryDisplayWidget
from
widget_library.plot_widget
import
(
ChartsPlotWidget
,
CirclePlotsWidget
,
TimePlotsWidget
,
)
from
widget_library.spin_buttons_widget
import
SpinButtonsWidget
from
widget_library.tab_expert
import
TabExpert
from
widget_library.ventilator_start_stop_buttons_widget
import
(
VentilatorStartStopButtonsWidget
,
)
from
widget_library.tab_expert
import
TabExpert
from
widget_library.tab_charts
import
TabChart
from
mode_widgets.tab_modes
import
TabModes
from
mode_widgets.tab_personal
import
TabPersonal
from
alarm_widgets.tab_alarms
import
TabAlarm
from
alarm_widgets.tab_alarm_table
import
TabAlarmTable
from
alarm_widgets.tab_clinical
import
TabClinical
class
Widgets
:
...
...
@@ -75,7 +80,9 @@ class Widgets:
# Settings Page Widgets
self
.
settings_expert_tab
=
TabExpert
(
NativeUI
)
self
.
settings_chart_tab
=
TabChart
(
NativeUI
)
self
.
charts_widget
=
ChartsPlotWidget
(
colors
=
NativeUI
.
colors
)
self
.
chart_buttons_widget
=
ChartButtonsWidget
(
colors
=
NativeUI
.
colors
)
# self.settings_chart_tab = TabChart(NativeUI)
# Modes Page Widgets
self
.
mode_settings_tab
=
TabModes
(
NativeUI
)
...
...
NativeUI/widget_library/chart_buttons_widget.py
0 → 100644
View file @
944d3d5f
#!/usr/bin/env python3
"""
chart_buttons_widget.py
"""
__author__
=
[
"Benjamin Mummery"
,
"Tiago Sarmento"
]
__credits__
=
[
"Benjamin Mummery"
,
"Dónal Murray"
,
"Tim Powell"
,
"Tiago Sarmento"
]
__license__
=
"GPL"
__version__
=
"0.0.1"
__maintainer__
=
"Benjamin Mummery"
__email__
=
"benjamin.mummery@stfc.ac.uk"
__status__
=
"Development"
from
PySide2
import
QtGui
,
QtWidgets
from
PySide2.QtCore
import
QSize
,
Signal
,
Slot
class
ChartButtonsWidget
(
QtWidgets
.
QWidget
):
def
__init__
(
self
,
*
args
,
colors
:
dict
=
{},
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
buttons
=
[
ToggleButtonWidget
(
"Pressure"
,
signal_value
=
"pressure"
),
ToggleButtonWidget
(
"Flow"
,
signal_value
=
"flow"
),
]
stylesheet
=
(
"QPushButton{"
" background-color:"
+
colors
[
"button_background_enabled"
]
.
name
()
+
";"
" color:"
+
colors
[
"button_foreground_enabled"
]
.
name
()
+
";"
" border: none"
"}"
"QPushButton:checked{"
" background-color:"
+
colors
[
"button_background_disabled"
]
.
name
()
+
";"
" color:"
+
colors
[
"button_foreground_enabled"
]
.
name
()
+
";"
" border: none"
"}"
)
for
button
in
self
.
buttons
:
button
.
setStyleSheet
(
stylesheet
)
# Layout buttons block
grid
=
QtWidgets
.
QGridLayout
()
i_row
=
0
i_col
=
0
for
widget
in
self
.
buttons
:
grid
.
addWidget
(
widget
,
i_row
,
i_col
)
i_row
+=
1
self
.
setLayout
(
grid
)
def
set_size
(
self
,
x
:
int
,
y
:
int
,
spacing
:
int
=
10
)
->
int
:
"""
Set the size of the widget and its subwidgets.
"""
pass
def
setFont
(
self
,
font
:
QtGui
.
QFont
)
->
int
:
"""
Overrides the existing setFont method in order to propogate the change to
subwidgets.
"""
for
button
in
self
.
buttons
:
button
.
setFont
(
font
)
return
0
class
ToggleButtonWidget
(
QtWidgets
.
QPushButton
):
"""
Variant of the QPushButton that emits a signal containing a string (signal_value)
"""
ToggleButtonPressed
=
Signal
(
str
)
ToggleButtonReleased
=
Signal
(
str
)
def
__init__
(
self
,
*
args
,
signal_value
:
str
=
None
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
__signal_value
=
signal_value
self
.
setCheckable
(
True
)
self
.
pressed
.
connect
(
self
.
on_press
)
def
on_press
(
self
)
->
int
:
"""
When the button is pressed, emit the either the ToggleButtonPressed or
ToggleButtonReleased signal depending on whether the button was in the checked
or unchacked state.
"""
if
self
.
isChecked
():
# active -> inactive
self
.
ToggleButtonReleased
.
emit
(
self
.
__signal_value
)
else
:
# inactive -> active
self
.
ToggleButtonPressed
.
emit
(
self
.
__signal_value
)
return
0
NativeUI/widget_library/history_buttons_widget.py
View file @
944d3d5f
...
...
@@ -144,7 +144,7 @@ class HistoryButton(QtWidgets.QPushButton):
HistoryButtonPressed
=
Signal
(
int
)
def
__init__
(
self
,
*
args
,
signal_value
=
None
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
signal_value
:
int
=
None
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
__signal_value
=
signal_value
self
.
pressed
.
connect
(
self
.
on_press
)
...
...
NativeUI/widget_library/measurements_widget.py
View file @
944d3d5f
...
...
@@ -158,10 +158,10 @@ class MeasurementsBlockWidget(QtWidgets.QWidget):
widget
.
value_display
.
setFont
(
font
)
return
0
@
QtCore
.
Slot
()
def
update_value
(
self
)
->
int
:
@
QtCore
.
Slot
(
dict
,
dict
)
def
update_value
(
self
,
cycle
:
dict
,
readback
:
dict
)
->
int
:
for
widget
in
self
.
widget_list
:
widget
.
update_value
()
widget
.
update_value
(
{
"cycle"
:
cycle
,
"readback"
:
readback
}
)
class
MeasurementWidget
(
QtWidgets
.
QWidget
):
...
...
@@ -231,7 +231,7 @@ class MeasurementWidget(QtWidgets.QWidget):
layout
.
setSpacing
(
0
)
self
.
setLayout
(
layout
)
def
update_value
(
self
)
->
int
:
def
update_value
(
self
,
db
:
dict
)
->
int
:
"""
Poll the database in NativeUI and update the displayed value.
"""
...
...
@@ -239,14 +239,12 @@ class MeasurementWidget(QtWidgets.QWidget):
self
.
value_display
.
setText
(
"-"
)
return
0
data
=
self
.
NativeUI
.
get_db
(
self
.
keydir
)
data
=
db
[
self
.
keydir
]
if
len
(
data
)
==
0
:
# means that the db hasn't been populated yet
self
.
value_display
.
setText
(
"-"
)
return
0
self
.
value_display
.
setText
(
self
.
__format_value
(
self
.
NativeUI
.
get_db
(
self
.
keydir
)[
self
.
key
])
)
self
.
value_display
.
setText
(
self
.
__format_value
(
data
[
self
.
key
]))
return
0
def
__format_value
(
self
,
number
):
...
...
NativeUI/widget_library/plot_widget.py
View file @
944d3d5f
...
...
@@ -19,7 +19,7 @@ import logging
import
numpy
as
np
import
pyqtgraph
as
pg
from
pyqtgraph
import
mkColor
from
PySide2
import
QtCore
,
QtWidgets
from
PySide2
import
QtCore
,
Qt
Gui
,
Qt
Widgets
class
TimePlotsWidget
(
QtWidgets
.
QWidget
):
...
...
@@ -96,17 +96,16 @@ class TimePlotsWidget(QtWidgets.QWidget):
self
.
setLayout
(
layout
)
self
.
update_plot_data
()
def
plot
(
self
,
canvas
,
x
,
y
,
plotname
,
color
):
pen
=
pg
.
mkPen
(
color
=
color
,
width
=
3
)
return
canvas
.
plot
(
x
,
y
,
name
=
plotname
,
pen
=
pen
)
def
update_plot_data
(
self
):
@
QtCore
.
Slot
(
dict
)
def
update_plot_data
(
self
,
plots
:
dict
):
"""
Get the current plots database and update the plots to match
"""
plots
=
self
.
NativeUI
.
get_db
(
"plots"
)
#
plots = self.NativeUI.get_db("plots")
# Extend the non-time scales if we need to
self
.
pressure_plot
.
setYRange
(
*
plots
[
"pressure_axis_range"
])
...
...
@@ -209,22 +208,21 @@ class CirclePlotsWidget(QtWidgets.QWidget):
self
.
setLayout
(
layout
)
self
.
timer
=
QtCore
.
QTimer
()
self
.
timer
.
setInterval
(
16
)
# just faster than 60Hz
self
.
timer
.
timeout
.
connect
(
self
.
update_plot_data
)
self
.
timer
.
start
()
self
.
update_plot_data
()
# self.timer = QtCore.QTimer()
# self.timer.setInterval(16) # just faster than 60Hz
# self.timer.timeout.connect(self.update_plot_data)
# self.timer.start()
def
plot
(
self
,
canvas
,
x
,
y
,
plotname
,
color
):
pen
=
pg
.
mkPen
(
color
=
color
,
width
=
3
)
return
canvas
.
plot
(
x
,
y
,
name
=
plotname
,
pen
=
pen
)
def
update_plot_data
(
self
):
@
QtCore
.
Slot
(
dict
)
def
update_plot_data
(
self
,
plots
:
dict
):
"""
Get the current plots database and update the plots to match
"""
plots
=
self
.
NativeUI
.
get_db
(
"plots"
)
#
plots = self.NativeUI.get_db("plots")
# Extend the non-time scales if we need to
self
.
pressure_flow_plot
.
setXRange
(
*
plots
[
"flow_axis_range"
])
...
...
@@ -247,3 +245,84 @@ class CirclePlotsWidget(QtWidgets.QWidget):
plot
.
setXRange
(
self
.
time_range
*
(
-
1
),
0
,
padding
=
0
)
plot
.
enableAutoRange
(
"y"
,
True
)
return
0
class
ChartsPlotWidget
(
QtWidgets
.
QWidget
):
def
__init__
(
self
,
port
=
54322
,
*
args
,
colors
:
dict
=
{},
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
port
=
port
layout
=
QtWidgets
.
QHBoxLayout
()
# Set up the graph widget
self
.
graph_widget
=
pg
.
GraphicsLayoutWidget
()
layout
.
addWidget
(
self
.
graph_widget
)
# Add the plot axes to the graph widget
self
.
display_plot
=
self
.
graph_widget
.
addPlot
(
labels
=
{
"left"
:
"????"
,
"bottom"
:
"????"
}
)
self
.
graph_widget
.
nextRow
()
# Store plots in a list in case we need to add additional axes in the future.
plots
=
[
self
.
display_plot
]
# Create lines
self
.
lines
=
{
"pressure"
:
self
.
plot
(
self
.
display_plot
,
[
0
,
10
],
[
5
,
-
5
],
"pressure"
,
(
0
,
0
,
0
,
0
)
),
"flow"
:
self
.
plot
(
self
.
display_plot
,
[
0
,
2
,
4
,
6
,
8
,
10
],
[
3
,
1
,
4
,
1
,
5
,
9
],
"flow"
,
(
0
,
0
,
0
,
0
),
),
}
# Store the colors of the lines
self
.
colors
=
{
"pressure"
:
colors
[
"pressure_plot"
],
"flow"
:
colors
[
"flow_plot"
]}
self
.
graph_widget
.
setContentsMargins
(
0.0
,
0.0
,
0.0
,
0.0
)
self
.
graph_widget
.
setBackground
(
colors
[
"page_background"
])
self
.
legends
=
[]
for
plot
in
plots
:
plot
.
showGrid
(
x
=
True
,
y
=
True
)
plot
.
hideButtons
()
plot
.
setMouseEnabled
(
x
=
False
,
y
=
False
)
self
.
legends
.
append
(
plot
.
addLegend
(
offset
=
(
-
1
,
1
)))
self
.
setLayout
(
layout
)
self
.
hide_line
(
"pressure"
)
self
.
show_line
(
"pressure"
)
def
setFont
(
self
,
font
:
QtGui
.
QFont
)
->
int
:
for
l
in
self
.
legends
:
l
.
setFont
(
font
)
return
0
def
update_plot_data
(
self
):
pass
def
plot
(
self
,
canvas
,
x
,
y
,
plotname
,
color
):
pen
=
pg
.
mkPen
(
color
=
color
,
width
=
3
)
return
canvas
.
plot
(
x
,
y
,
name
=
plotname
,
pen
=
pen
)
@
QtCore
.
Slot
(
str
)
def
show_line
(
self
,
key
:
str
)
->
int
:
"""
Show the specified line
"""
self
.
lines
[
key
]
.
setPen
(
pg
.
mkPen
(
color
=
self
.
colors
[
key
],
width
=
3
))
return
0
@
QtCore
.
Slot
(
str
)
def
hide_line
(
self
,
key
:
str
)
->
int
:
"""
Hide the specified line
"""
self
.
lines
[
key
]
.
setPen
(
pg
.
mkPen
(
color
=
(
0
,
0
,
0
,
0
),
width
=
0
))
return
0
NativeUI/widget_library/tab_charts.py
deleted
100644 → 0
View file @
8b4110b1
#!/usr/bin/env python3
"""
tab_charts.py
"""
__author__
=
[
"Benjamin Mummery"
,
"Tiago Sarmento"
]
__credits__
=
[
"Benjamin Mummery"
,
"Dónal Murray"
,
"Tim Powell"
,
"Tiago Sarmento"
]
__license__
=
"GPL"
__version__
=
"0.0.1"
__maintainer__
=
"Tiago Sarmento"
__email__
=
"tiago.sarmento@stfc.ac.uk"
__status__
=
"Development"
from
PySide2
import
QtWidgets
,
QtGui
,
QtCore
import
sys
class
TabChart
(
QtWidgets
.
QWidget
):
# chose QWidget over QDialog family because easier to modify
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
TabChart
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
label
=
QtWidgets
.
QLabel
(
"charting"
)
vlayout
=
QtWidgets
.
QVBoxLayout
()
vlayout
.
addWidget
(
label
)
self
.
setLayout
(
vlayout
)
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