Skip to content

Commit

Permalink
Merge pull request #330 from jnsebgosselin/sync_brf_period_daterange
Browse files Browse the repository at this point in the history
PR: Add an option to imports the parameters used to compute the BRF currently shown in the viewer into the manager.
  • Loading branch information
jnsebgosselin committed Sep 26, 2020
2 parents 44a6cfa + 6b9ff44 commit 0743a1b
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 50 deletions.
7 changes: 7 additions & 0 deletions gwhat/HydroCalc2.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,13 @@ def close(self):
self.brf_eval_widget.close()
super().close()

def showEvent(self, event):
"""Extend Qt method"""
# This is required to make sure the BRF is plotted correctly on
# restart.
self.plot_brfperiod()
super().showEvent(event)

# ---- MRC handlers
def btn_show_mrc_isclicked(self):
"""Handle when the button to draw of hide the mrc is clicked."""
Expand Down
125 changes: 82 additions & 43 deletions gwhat/brf_mod/kgs_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
from PyQt5.QtWidgets import (
QLabel, QDateTimeEdit, QCheckBox, QPushButton, QApplication, QSpinBox,
QAbstractSpinBox, QGridLayout, QDoubleSpinBox, QFrame, QWidget,
QMessageBox, QFileDialog, QComboBox, QLayout, QDialog,
QGroupBox, QToolButton)
QMessageBox, QFileDialog, QComboBox, QDialog, QGroupBox, QToolButton,
QToolBar)

from xlrd.xldate import xldate_from_datetime_tuple, xldate_as_datetime
import numpy as np
Expand All @@ -40,6 +40,7 @@
from gwhat.utils import icons
from gwhat.utils.icons import QToolButtonNormal, get_icon
from gwhat.utils.dates import qdatetime_from_xldate
from gwhat.utils.qthelpers import create_toolbar_stretcher
from gwhat import brf_mod as bm
from gwhat.brf_mod import __install_dir__
from gwhat.brf_mod.kgs_plot import BRFFigure
Expand Down Expand Up @@ -123,7 +124,7 @@ def install_kgsbrf(self):


class BRFManager(myqt.QFrameLayout):
sig_brfperiod_changed = QSignal(list)
sig_brfperiod_changed = QSignal(tuple)
sig_select_brfperiod_requested = QSignal(bool)

def __init__(self, wldset=None, parent=None):
Expand All @@ -136,6 +137,8 @@ def __init__(self, wldset=None, parent=None):
CONF.get('brf', 'graphs_labels_language'))
if CONF.get('brf', 'graph_opt_panel_is_visible', False):
self.viewer.toggle_graphpannel()
self.viewer.sig_import_params_in_manager_request.connect(
self.import_current_viewer_brf_parameters)

self.kgs_brf_installer = None
self.__initGUI__()
Expand Down Expand Up @@ -308,8 +311,12 @@ def correct_waterlevels(self):

def get_brfperiod(self):
"""
Get the period over which the BRF would be evaluated as a list of
two numerical Excel date values.
Get the period over which the BRF would be evaluated.
Returns
-------
brfperiod
A list of two numerical Excel date values.
"""
year, month, day = self.date_start_edit.date().getDate()
hour = self.date_start_edit.time().hour()
Expand All @@ -330,6 +337,11 @@ def set_brfperiod(self, period):
Set the value of the date_start_edit and date_end_edit widgets used to
define the period over which the BRF is evaluated. Also save the
period to the waterlevel dataset.
Parameters
----------
daterange : 2-length tuple of int
A list of two numerical Excel date values.
"""
period = np.sort(period).tolist()
widgets = (self.date_start_edit, self.date_end_edit)
Expand Down Expand Up @@ -357,8 +369,13 @@ def set_wldset(self, wldset):

def set_daterange(self, daterange):
"""
Set the minimum and maximum value of date_start_edit and date_end_edit
widgets from the specified list of Excel numeric dates.
Set the minimum and maximum value of the date_start_edit and
date_end_edit widgets from the specified Excel numeric dates.
Parameters
----------
daterange : 2-length tuple of int
A list of two numerical Excel date values.
"""
for widget in (self.date_start_edit, self.date_end_edit):
widget.blockSignals(True)
Expand Down Expand Up @@ -391,6 +408,38 @@ def toggle_link_bp_and_et_lags(self, toggle):
if toggle is True:
self._handle_lag_value_changed(self.baro_spinbox)

def import_current_viewer_brf_parameters(self):
"""
Setup the BRF parameters to reflect those saved in the provided
BRF results dataset.
"""
if self.wldset is None or self.wldset.brf_count() == 0:
return
brfdata = self.wldset.get_brf(
self.wldset.get_brfname_at(self.viewer.current_brf.value() - 1))

# Setup the lags.
nlag_bp = len(brfdata.loc[:, 'A'].dropna()) - 1
nlag_et = len(brfdata.loc[:, 'B'].dropna()) - 1

self.earthtides_cbox.setChecked(nlag_et != -1)
if nlag_bp != nlag_et and nlag_et != -1:
self.toggle_link_bp_and_et_lags(False)
self.baro_spinbox.setValue(nlag_bp)
if nlag_et != -1:
self.earthtides_spinbox.setValue(nlag_et)

# Setup the detrending paramenter.
self.detrend_waterlevels_cbox.setChecked(brfdata.detrending == 'Yes')

# Setup the BRF period.
xls_date_start = xldate_from_datetime_tuple(
brfdata.date_start.timetuple()[:6], 0)
xls_date_end = xldate_from_datetime_tuple(
brfdata.date_end.timetuple()[:6], 0)
self.set_brfperiod((xls_date_start, xls_date_end))
self.sig_brfperiod_changed.emit((xls_date_start, xls_date_end))

def _handle_lag_value_changed(self, sender):
"""
Handle when the value of either the barometric pressure
Expand Down Expand Up @@ -504,6 +553,7 @@ class BRFViewer(QDialog):
Window that is used to show all the results produced with for the
currently selected water level dataset.
"""
sig_import_params_in_manager_request = QSignal()

def __init__(self, wldset=None, parent=None):
super(BRFViewer, self).__init__(parent)
Expand All @@ -520,9 +570,7 @@ def __init__(self, wldset=None, parent=None):
self.set_wldset(wldset)

def __initGUI__(self):

# ---- Navigator

# Setup the navigation buttons and widgets.
self.btn_prev = QToolButtonNormal(icons.get_icon('go_previous'))
self.btn_prev.clicked.connect(self.navigate_brf)

Expand All @@ -547,10 +595,7 @@ def __initGUI__(self):
self.btn_language.sig_lang_changed.connect(self.plot_brf)
self.btn_language.setIconSize(icons.get_iconsize('normal'))

# ---- Toolbar

# Generate the buttons :

# Generate the toolbar buttons.
self.btn_del = QToolButtonNormal(icons.get_icon('delete_data'))
self.btn_del.setToolTip('Delete current BRF results')
self.btn_del.clicked.connect(self.del_brf)
Expand All @@ -576,38 +621,38 @@ def __initGUI__(self):
self.btn_setp.setToolTip('Show graph layout parameters...')
self.btn_setp.clicked.connect(self.toggle_graphpannel)

# Generate the layout :

self.tbar = myqt.QFrameLayout()
self.import_params_in_manager_btn = QToolButtonNormal(
icons.get_icon('content_duplicate'))
self.import_params_in_manager_btn.clicked.connect(
lambda _: self.sig_import_params_in_manager_request.emit())

# Setup the toolbar.
self.toolbar = QToolBar()
self.toolbar.setStyleSheet("QToolBar {border: 0px; spacing:1px;}")
buttons = [btn_save, self.btn_copy, self.btn_export, self.btn_del,
self.btn_del_all, VSep(), self.btn_prev, self.current_brf,
self.total_brf, self.btn_next, VSep(), self.btn_setp,
self.btn_language]

for btn in buttons:
if isinstance(btn, QLayout):
self.tbar.addLayout(btn, 1, self.tbar.columnCount())
self.btn_del_all, None, self.btn_prev, self.current_brf,
self.total_brf, self.btn_next, None,
self.import_params_in_manager_btn, self.btn_language]
for button in buttons:
if button is None:
self.toolbar.addSeparator()
else:
self.tbar.addWidget(btn, 1, self.tbar.columnCount())

row = self.tbar.columnCount()
self.tbar.addWidget(HSep(), 0, 0, 1, row+1)
self.tbar.setColumnStretch(row, 100)
self.tbar.setContentsMargins(10, 0, 10, 10) # (l, t, r, b)
self.toolbar.addWidget(button)
self.toolbar.addWidget(create_toolbar_stretcher())
self.toolbar.addWidget(self.btn_setp)

# Setup the graph canvas.
self.brf_canvas = FigureCanvasQTAgg(BRFFigure())

self.fig_frame = QFrame()
self.fig_frame.setFrameStyle(StyleDB().frame)
self.fig_frame.setObjectName("figframe")
self.fig_frame.setStyleSheet("#figframe {background-color:white;}")

self.brf_canvas = FigureCanvasQTAgg(BRFFigure())

fflay = QGridLayout(self.fig_frame)
fflay.setContentsMargins(0, 0, 0, 0) # (left, top, right, bottom)
fflay.addWidget(self.tbar, 1, 0)
fflay.addWidget(self.brf_canvas, 0, 0)
fig_frame_layout = QGridLayout(self.fig_frame)
fig_frame_layout.addWidget(self.brf_canvas, 0, 0)
fig_frame_layout.addWidget(HSep(), 1, 0)
fig_frame_layout.addWidget(self.toolbar, 2, 0)

# Setup the graph options panel.
self.graph_opt_panel = BRFOptionsPanel()
Expand Down Expand Up @@ -693,7 +738,7 @@ def update_brfnavigate_state(self):
self.current_brf.setMaximum(count)
curnt = self.current_brf.value()

self.tbar.setEnabled(count > 0)
self.toolbar.setEnabled(count > 0)
self.btn_prev.setEnabled(curnt > 1)
self.btn_next.setEnabled(curnt < count)
self.btn_del.setEnabled(count > 0)
Expand Down Expand Up @@ -1080,9 +1125,3 @@ def axis_autocheck_changed(self):
brfwin.viewer.toggle_graphpannel()

sys.exit(app.exec_())

# plt.close('all')
# produce_par_file()
# run_kgsbrf()
# load_BRFOutput(show_ebar=True, msize=5, draw_line=False)
# plt.show()
47 changes: 41 additions & 6 deletions gwhat/brf_mod/tests/test_brf_mod.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-

# Copyright © 2014-2018 GWHAT Project Contributors
# -----------------------------------------------------------------------------
# Copyright © GWHAT Project Contributors
# https://github.com/jnsebgosselin/gwhat
#
# This file is part of GWHAT (Ground-Water Hydrograph Analysis Toolbox).
# Licensed under the terms of the GNU General Public License.
# -----------------------------------------------------------------------------

# ---- Standard library imports
import os
Expand Down Expand Up @@ -126,11 +127,12 @@ def test_calcul_brf(brfmanager, wldataset, qtbot):
brfmanager.set_wldset(wldataset)
assert brfmanager.get_brfperiod() == [41384.0, 41416.0]

assert brfmanager.viewer.tbar.isEnabled() is False
assert brfmanager.viewer.toolbar.isEnabled() is False
assert brfmanager.viewer.current_brf.value() == 0

brfmanager.calc_brf()
assert brfmanager.viewer.current_brf.value() == 1
assert brfmanager.viewer.tbar.isEnabled()
assert brfmanager.viewer.toolbar.isEnabled()


# =============================================================================
Expand Down Expand Up @@ -215,6 +217,39 @@ def test_graph_panel(brfmanager, wldataset, mocker, qtbot):
assert(brfmanager.viewer.graph_opt_panel.isVisible() is False)


@pytest.mark.skipif(os.name == 'posix',
reason="This feature is not supported on Linux")
def test_import_viewer_params_in_manager(brfmanager, wldataset, mocker, qtbot):
"""
Test importing the parameters of the BRF shown in the viewer in the manager
is working as expected.
"""
brfmanager.set_wldset(wldataset)
brfmanager.viewer.show()

# Change the parameters in the manager.
brfmanager.baro_spinbox.setValue(95)
brfmanager.earthtides_spinbox.setValue(72)
brfmanager.set_brfperiod([41390, 41415])
brfmanager.earthtides_cbox.setChecked(False)
brfmanager.detrend_waterlevels_cbox.setChecked(False)

# Assert that the value were correctly changed in the manager.
assert brfmanager.get_brfperiod() == [41390, 41415]
assert brfmanager.nlag_baro == 95
assert brfmanager.nlag_earthtides == -1
assert brfmanager.detrend_waterlevels is False

# Sync the parameters of the used to compute the BRF currently showen in
# the viewer with the manager.
qtbot.mouseClick(brfmanager.viewer.import_params_in_manager_btn,
Qt.LeftButton)
assert brfmanager.get_brfperiod() == [41384.0, 41416.0]
assert brfmanager.nlag_baro == 100
assert brfmanager.nlag_earthtides == 100
assert brfmanager.detrend_waterlevels is True


@pytest.mark.skipif(os.name == 'posix',
reason="This feature is not supported on Linux")
def test_del_brf_result(brfmanager, wldataset, mocker, qtbot):
Expand All @@ -225,7 +260,7 @@ def test_del_brf_result(brfmanager, wldataset, mocker, qtbot):
assert brfmanager.viewer.current_brf.value() == 1
qtbot.mouseClick(brfmanager.viewer.btn_del, Qt.LeftButton)
assert brfmanager.viewer.current_brf.value() == 0
assert brfmanager.viewer.tbar.isEnabled() is False
assert brfmanager.viewer.toolbar.isEnabled() is False


@pytest.mark.skipif(os.name == 'posix',
Expand All @@ -249,7 +284,7 @@ def test_del_all_brf_result(brfmanager, wldataset, mocker, qtbot):
mocker.patch.object(QMessageBox, 'question', return_value=QMessageBox.Yes)
qtbot.mouseClick(brfmanager.viewer.btn_del_all, Qt.LeftButton)
assert brfmanager.viewer.current_brf.value() == 0
assert brfmanager.viewer.tbar.isEnabled() is False
assert brfmanager.viewer.toolbar.isEnabled() is False


@pytest.mark.skipif(os.name == 'posix',
Expand Down
3 changes: 3 additions & 0 deletions gwhat/utils/icons.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@
{'scale_factor': 0.6,
'offset': (0.3, 0.3),
'color': COLOR}]}],
'content_duplicate': [
('mdi.content-duplicate',),
{'color': COLOR, 'scale_factor': 1.2}],
'commit_changes': [
('mdi.check-circle-outline',),
{'color': GREEN, 'scale_factor': 1.3}],
Expand Down
10 changes: 9 additions & 1 deletion gwhat/utils/qthelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"""Qt utilities"""

# ---- Third party imports
from qtpy.QtCore import QByteArray
from PyQt5.QtCore import QByteArray
from PyQt5.QtWidgets import QWidget, QSizePolicy


def qbytearray_to_hexstate(qba):
Expand All @@ -21,3 +22,10 @@ def qbytearray_to_hexstate(qba):
def hexstate_to_qbytearray(hexstate):
"""Convert a str hexstate to a QByteArray object."""
return QByteArray().fromHex(str(hexstate).encode('utf-8'))


def create_toolbar_stretcher():
"""Create a stretcher to be used in a toolbar """
stretcher = QWidget()
stretcher.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
return stretcher

0 comments on commit 0743a1b

Please sign in to comment.