Skip to content

Commit

Permalink
PR: Plot GLUE water levels with the hydrograph editor (#202)
Browse files Browse the repository at this point in the history
* Update GLUE wl plotting method with setter/getter

* Add the nbr of behavioural models in a print

* Clean code and imports

* Remove duplicate code to plot GLUE water levels.

* Add a method to return gluedf by index

* Add the glue_wl_on key to the layout.

* Code style changes

* Add a gluedf explicit attribute

* Fixed a small bug when saving glue results npy

* Wire everything on the UI side to make this work

* Finish commit and comment the saving of glue results

* Cancel change to logo support svg
  • Loading branch information
jnsebgosselin authored May 6, 2018
1 parent 8c5a1c2 commit ca2f67b
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 164 deletions.
24 changes: 9 additions & 15 deletions gwhat/HydroCalc2.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import gwhat.common.widgets as myqt
from gwhat.common import StyleDB, QToolButtonNormal
from gwhat.common import icons
import gwhat.brf_mod as bm
from gwhat.brf_mod import BRFManager

mpl.rc('font', **{'family': 'sans-serif', 'sans-serif': ['Arial']})

Expand All @@ -58,6 +58,11 @@ def __init__(self, datamanager, parent=None):
self.dmngr.wldsetChanged.connect(self.set_wldset)
self.dmngr.wxdsetChanged.connect(self.set_wxdset)

self.rechg_eval_widget = RechgEvalWidget(parent=self)

self.config_brf = BRFManager(parent=self)
self.config_brf.btn_seldata.clicked.connect(self.aToolbarBtn_isClicked)

self.isGraphExists = False
self.__figbckground = None # figure background
self.__addPeakVisible = True
Expand Down Expand Up @@ -95,19 +100,11 @@ def __init__(self, datamanager, parent=None):
self.brfperiod = [None, None]
self.__brfcount = 0

# self.config_brf = ConfigBRF()
self.config_brf = bm.BRFManager(parent=self)
self.config_brf.btn_seldata.clicked.connect(self.aToolbarBtn_isClicked)

# Soil Profiles :

self.soilFilename = []
self.SOILPROFIL = SoilProfil()

# Recharge :

self.rechg_setup_win = RechgEvalWidget(parent=self)

# ---- Initialize the GUI
self.__initFig__()
self.__initUI__()
Expand Down Expand Up @@ -370,7 +367,7 @@ def __initUI__(self):
tooltab.setTabPosition(tooltab.North)

tooltab.addTab(self.widget_MRCparam, icons.get_icon('MRCalc'), '')
tooltab.addTab(self.rechg_setup_win, icons.get_icon('recharge'), '')
tooltab.addTab(self.rechg_eval_widget, icons.get_icon('recharge'), '')
tooltab.addTab(self.config_brf, icons.get_icon('setup'), '')

# ---------------------------------------------------- Right Panel ----
Expand Down Expand Up @@ -412,7 +409,7 @@ def wxdset(self):

def set_wldset(self, wldset):
self.config_brf.set_wldset(wldset)
self.rechg_setup_win.set_wldset(wldset)
self.rechg_eval_widget.set_wldset(wldset)

if wldset is None:
self.water_lvl = None
Expand All @@ -431,7 +428,7 @@ def set_wldset(self, wldset):

def set_wxdset(self, wxdset):
"""Set the weather dataset."""
self.rechg_setup_win.wxdset = wxdset
self.rechg_eval_widget.wxdset = wxdset
self.plot_weather_data()

def plot_weather_data(self):
Expand Down Expand Up @@ -1834,9 +1831,6 @@ def load_info(self, filename):
self.color[i] = '#FFFFFF'


# =============================================================================


def mrc2rechg(t, ho, A, B, z, Sy):
"""
Calculate groundwater recharge from the Master Recession Curve (MRC)
Expand Down
23 changes: 22 additions & 1 deletion gwhat/HydroPrint2.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from PyQt5.QtCore import Qt, QDate, QCoreApplication, QPoint
from PyQt5.QtCore import pyqtSignal as QSignal
from PyQt5.QtCore import pyqtSlot as QSlot
from PyQt5.QtWidgets import (QSpinBox, QDoubleSpinBox, QWidget, QDateEdit,
QAbstractSpinBox, QGridLayout, QFrame,
QMessageBox, QComboBox, QLabel, QTabWidget,
Expand All @@ -38,6 +39,7 @@
from gwhat.common.utils import find_unique_filename
from gwhat.projet.reader_waterlvl import load_waterlvl_measures
from gwhat.widgets.layout import OnOffToggleWidget
from gwhat.gwrecharge.glue import GLUEDataFrameBase


class HydroprintGUI(myqt.DialogWindow):
Expand Down Expand Up @@ -478,6 +480,7 @@ def wldset_changed(self):
else:
wldset = self.wldset
self.hydrograph.set_wldset(wldset)
self.hydrograph.gluedf = self.wldset.get_glue_at(-1)

# Load the manual measurements.

Expand Down Expand Up @@ -528,6 +531,15 @@ def best_fit_time(self):
self.date_start_widget.setDate(QDate(date0[0], date0[1], date0[2]))
self.date_end_widget.setDate(QDate(date1[0], date1[1], date1[2]))

@QSlot(GLUEDataFrameBase)
def glue_wl_changed(self, gluedf):
"""
Force a redraw of the GLUE water levels after the results have
changed for the dataset.
"""
self.hydrograph.set_gluedf(gluedf)
self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph)

def layout_changed(self):
"""
When an element of the graph layout is changed in the UI.
Expand Down Expand Up @@ -657,6 +669,7 @@ def update_graph_layout_parameter(self):
self.hydrograph.isLegend = self.page_setup_win.isLegend
self.hydrograph.isGraphTitle = self.page_setup_win.isGraphTitle
self.hydrograph.set_meteo_on(self.page_setup_win.is_meteo_on)
self.hydrograph.set_glue_wl_on(self.page_setup_win.is_glue_wl_on)

# Weather bins :

Expand Down Expand Up @@ -782,11 +795,13 @@ def load_graph_layout(self, layout):
self.page_setup_win.isGraphTitle = layout['title_on']
self.page_setup_win.isTrendLine = layout['trend_line']
self.page_setup_win.is_meteo_on = layout['meteo_on']
self.page_setup_win.is_glue_wl_on = layout['glue_wl_on']

self.page_setup_win.legend_on.set_value(layout['legend_on'])
self.page_setup_win.title_on.set_value(layout['title_on'])
self.page_setup_win.wltrend_on.set_value(layout['trend_line'])
self.page_setup_win.meteo_on.set_value(layout['meteo_on'])
self.page_setup_win.glue_wl_on.set_value(layout['glue_wl_on'])

self.page_setup_win.fwidth.setValue(layout['fwidth'])
self.page_setup_win.fheight.setValue(layout['fheight'])
Expand Down Expand Up @@ -857,6 +872,7 @@ def save_graph_layout(self):
layout['language'] = self.language_box.currentText()
layout['trend_line'] = bool(self.page_setup_win.isTrendLine)
layout['meteo_on'] = bool(self.page_setup_win.is_meteo_on)
layout['glue_wl_on'] = bool(self.page_setup_win.is_glue_wl_on)

# Save the colors :

Expand Down Expand Up @@ -892,6 +908,7 @@ def __init__(self, parent=None):
self.isGraphTitle = True
self.isTrendLine = False
self.is_meteo_on = True
self.is_glue_wl_on = False
self.va_ratio = 0.2

self.__initUI__()
Expand Down Expand Up @@ -979,11 +996,13 @@ def _setup_element_visibility_grpbox(self):
self.title_on = OnOffToggleWidget('Figure Title', True)
self.wltrend_on = OnOffToggleWidget('Water Level Trend', False)
self.meteo_on = OnOffToggleWidget('Weather Data', True)
self.glue_wl_on = OnOffToggleWidget('GLUE Water Levels', False)

grpbox = QGroupBox("Graph Components Visibility :")
layout = QGridLayout(grpbox)
for i, widget in enumerate([self.legend_on, self.title_on,
self.wltrend_on, self.meteo_on]):
self.wltrend_on, self.meteo_on,
self.glue_wl_on]):
layout.addWidget(widget, i, 0)
layout.setContentsMargins(10, 10, 10, 10)

Expand All @@ -1003,6 +1022,7 @@ def btn_apply_isClicked(self):
self.isGraphTitle = self.title_on.value()
self.isTrendLine = self.wltrend_on.value()
self.is_meteo_on = self.meteo_on.value()
self.is_glue_wl_on = self.glue_wl_on.value()
self.va_ratio = self.va_ratio_spinBox.value()

self.newPageSetupSent.emit(True)
Expand All @@ -1024,6 +1044,7 @@ def closeEvent(self, event):
self.title_on.set_value(self.isGraphTitle)
self.wltrend_on.set_value(self.isTrendLine)
self.meteo_on.set_value(self.is_meteo_on)
self.glue_wl_on.set_value(self.is_glue_wl_on)

def show(self):
super(PageSetupWin, self).show()
Expand Down
4 changes: 3 additions & 1 deletion gwhat/gwrecharge/gwrecharge_calc2.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ def eval_recharge(self):

if glue_rawdata['count'] > 0:
glue_dataf = GLUEDataFrame(glue_rawdata)
# self._save_glue_to_npy(glue_rawdata)
else:
glue_dataf = None
self.sig_glue_finished.emit(glue_dataf)
Expand All @@ -282,6 +283,7 @@ def _print_model_params_summary(self, set_Sy, set_Cru, set_RASmax):
print('-'*78)
if len(set_Sy) > 0:
print('-'*78)
print('%d behavioural models were produced' % len(set_Sy))
range_sy = (np.min(set_Sy), np.max(set_Sy))
print('range Sy = %0.3f to %0.3f' % range_sy)
range_rasmax = (np.min(set_RASmax), np.max(set_RASmax))
Expand All @@ -294,7 +296,7 @@ def _print_model_params_summary(self, set_Sy, set_Cru, set_RASmax):

def _save_glue_to_npy(self, glue_rawdata):
"""Save the last computed glue results in a numpy npy file."""
if osp.exists(osp.dirname(__file__)):
if not osp.exists(osp.dirname(__file__)):
os.makedirs(osp.dirname(__file__))
filename = osp.join(osp.dirname(__file__), 'glue_rawdata.npy')
np.save(filename, glue_rawdata)
Expand Down
20 changes: 7 additions & 13 deletions gwhat/gwrecharge/gwrecharge_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@
# Licensed under the terms of the GNU General Public License.

import time
import os
import os.path as osp

# ---- Imports: third parties

import matplotlib.pyplot as plt
from PyQt5.QtCore import Qt, QThread
from PyQt5.QtCore import pyqtSlot as QSlot
from PyQt5.QtCore import pyqtSignal as QSignal
from PyQt5.QtWidgets import (QWidget, QGridLayout, QPushButton, QProgressBar,
QLabel, QSizePolicy, QScrollArea, QApplication,
QMessageBox, QMenu, QFileDialog)
QMessageBox)

# ---- Imports: local

Expand All @@ -26,11 +24,14 @@
from gwhat.gwrecharge.gwrecharge_calc2 import RechgEvalWorker
from gwhat.gwrecharge.gwrecharge_plot_results import FigureStackManager
from gwhat.gwrecharge.glue import GLUEDataFrameBase
from gwhat.common.icons import QToolButtonBase, QToolButtonSmall
from gwhat.common.icons import QToolButtonSmall
from gwhat.common import icons


class RechgEvalWidget(QFrameLayout):

sig_new_gluedf = QSignal(GLUEDataFrameBase)

def __init__(self, parent):
super(RechgEvalWidget, self).__init__(parent)
self.setWindowTitle('Recharge Calibration Setup')
Expand Down Expand Up @@ -263,10 +264,6 @@ def CM(self):
def deltaT(self):
return self._deltaT.value()

def closeEvent(self, event):
super(RechgEvalWidget, self).closeEvent(event)
print('Closing Window')

def btn_calibrate_isClicked(self):
"""
Handles when the button to compute recharge and its uncertainty is
Expand All @@ -279,8 +276,6 @@ def start_glue_calcul(self):
Start the method to evaluate ground-water recharge and its
uncertainty.
"""
plt.close('all')

# Set the parameter ranges.

self.rechg_worker.Sy = self.get_Range('Sy')
Expand Down Expand Up @@ -329,6 +324,7 @@ def receive_glue_calcul(self, glue_dataframe):
else:
self.wldset.clear_glue()
self.wldset.save_glue(glue_dataframe)
self.sig_new_gluedf.emit(glue_dataframe)

self.btn_save_glue.set_model(glue_dataframe)

Expand Down Expand Up @@ -403,8 +399,6 @@ def save_water_levels_tofile(self):

GLUE_RAWDATA = load_glue_from_npy('glue_rawdata.npy')
GLUE_DF = GLUEDataFrame(GLUE_RAWDATA)

print(GLUE_DF)

BTN_EXPORT_GLUE = ExportGLUEButton(GLUE_DF)
BTN_EXPORT_GLUE.show()
Expand Down
91 changes: 1 addition & 90 deletions gwhat/gwrecharge/gwrecharge_plot_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ def setup(self):
layout.addWidget(self.stack, 0, 0)

def setup_stack(self):
fig_wl_glue = FigManagerBase(
FigWaterLevelGLUE,
setp_panels=[FigSizePanel(),
MarginSizePanel()])
fig_rechg_glue = FigManagerBase(
FigYearlyRechgGLUE,
setp_panels=[FigSizePanel(),
Expand Down Expand Up @@ -100,11 +96,10 @@ def setup_stack(self):
YAxisOptPanel(),
TextOptPanel(xlabelsize=False, notesize=False)])

self.figmanagers = [fig_wl_glue, fig_rechg_glue, fig_watbudg_glue,
self.figmanagers = [fig_rechg_glue, fig_watbudg_glue,
fig_avg_yearly_budg, fig_avg_monthly_budg]

self.stack = QTabWidget()
self.stack.addTab(fig_wl_glue, 'Hydrograph')
self.stack.addTab(fig_rechg_glue, 'Recharge')
self.stack.addTab(fig_watbudg_glue, 'Yearly Budget')
self.stack.addTab(fig_avg_yearly_budg, 'Yearly Avg. Budget')
Expand Down Expand Up @@ -1163,90 +1158,6 @@ def setup_legend(self,):
handletextpad=0.2, borderaxespad=0.2, borderpad=0.2)


class FigWaterLevelGLUE(FigCanvasBase):
"""
This is a graph that shows observed ground-water levels and GLUE 5/95
predicted water levels.
"""

FIGNAME = "water_level_glue"

def __init__(self, setp={}):
super(FigWaterLevelGLUE, self).__init__(setp)

def plot(self, glue_df):
super(FigWaterLevelGLUE, self).plot()
ax = self.ax0

ax.grid(axis='x', color='0.35', ls=':', lw=1, zorder=200)
ax.grid(axis='y', color='0.35', ls=':', lw=1, zorder=200)
ax.invert_yaxis()

# ---- ticks format

ax.yaxis.set_ticks_position('left')
ax.tick_params(axis='y', direction='out', labelsize=12)
ax.xaxis.set_ticks_position('bottom')
ax.tick_params(axis='x', direction='out')

xloc = mpl.dates.AutoDateLocator()
ax.xaxis.set_major_locator(xloc)
xfmt = mpl.dates.AutoDateFormatter(xloc)
ax.xaxis.set_major_formatter(xfmt)

# ---- Plot the observed and glue predicted water levels.

wlobs = glue_df['water levels']['observed']
xlstime = glue_df['water levels']['time'] + DT4XLS2MPL
wl05 = glue_df['water levels']['predicted'][:, 0]/1000
wl95 = glue_df['water levels']['predicted'][:, 2]/1000

ax = self.figure.axes[0]
ax.plot(xlstime, wlobs, color='b', ls='None',
marker='.', ms=3, zorder=100)
ax.fill_between(xlstime, wl95, wl05, facecolor='0.85', lw=1,
edgecolor='0.65', zorder=0)

self.setup_axes_labels()
self.setup_legend()

self.sig_fig_changed.emit(self.figure)
self.sig_newfig_plotted.emit(self.setp)

def set_xlimits(self, xmin, xmax):
"""Set the limits of the xaxis to the provided values."""
pass

def setup_ylimits(self):
"""Setup the limits of the yaxis."""
self.ax0.axis(ymin=self.setp['ymin'], ymax=self.setp['ymax'])

def setup_language(self):
"""Setup the language of the text shown in the figure."""
self.setup_axes_labels()

def setup_legend(self):
"""Setup the legend of the graph."""
dum1 = mpl.patches.Rectangle((0, 0), 1, 1, fc='0.85', ec='0.65')
dum2, = self.ax0.plot([], [], color='b', ls='None', marker='.', ms=10)

lg_handles = [dum2, dum1]
lg_labels = ['Observations', 'GLUE 5/95']

self.ax0.legend(lg_handles, lg_labels, ncol=2, fontsize=12,
frameon=False, numpoints=1)

def setup_axes_labels(self):
"""
Set the text and position of the axes labels.
"""
if self.setp['language'] == 'french':
xlabel = "Niveau d'eau (m sous la surface)"
else:
xlabel = 'Water Level (mbgs)'
self.ax0.set_ylabel(xlabel, fontsize=16, labelpad=20)


class FigYearlyRechgGLUE(FigCanvasBase):
"""
This is a graph that shows annual ground-water recharge and its
Expand Down
Loading

0 comments on commit ca2f67b

Please sign in to comment.