mirror of https://gitlab.com/pamhyr/pamhyr2
Merge branch 'results-custom-plot'.
commit
f5fdde9a5d
|
|
@ -72,11 +72,11 @@ class PlotAC(PamhyrPlot):
|
|||
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "Transverse abscissa (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Height (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.figure.tight_layout()
|
||||
|
||||
|
|
@ -176,11 +176,11 @@ class PlotAC(PamhyrPlot):
|
|||
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "Abscisse en travers (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Cote (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.figure.tight_layout()
|
||||
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ class PlotKPZ(PamhyrPlot):
|
|||
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "Kp (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Height (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
kp = self.data.get_kp()
|
||||
|
|
|
|||
|
|
@ -65,11 +65,11 @@ class PlotXY(PamhyrPlot):
|
|||
# Axes
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("Geometry", "X (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("Geometry", "Y (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.axis("equal")
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
# CustomPlotValuesSelectionDialog.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from View.Tools.PamhyrWindow import PamhyrDialog
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QRadioButton, QCheckBox, QVBoxLayout,
|
||||
)
|
||||
|
||||
from View.Results.CustomPlot.Translate import CustomPlotTranslate
|
||||
|
||||
|
||||
class CustomPlotValuesSelectionDialog(PamhyrDialog):
|
||||
_pamhyr_ui = "CustomPlotValuesSelectionDialog"
|
||||
_pamhyr_name = "Custom Plot Selection"
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(CustomPlotValuesSelectionDialog, self).__init__(
|
||||
title=self._pamhyr_name,
|
||||
options=[],
|
||||
trad=CustomPlotTranslate(),
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self._available_values_x = self._trad.get_dict("values_x")
|
||||
self._available_values_y = self._trad.get_dict("values_y")
|
||||
|
||||
self.setup_radio_buttons()
|
||||
self.setup_check_boxs()
|
||||
|
||||
self.value = None
|
||||
|
||||
def setup_radio_buttons(self):
|
||||
self._radio = []
|
||||
layout = self.find(QVBoxLayout, "verticalLayout_x")
|
||||
|
||||
for value in self._available_values_x:
|
||||
btn = QRadioButton(
|
||||
self._available_values_x[value],
|
||||
parent=self
|
||||
)
|
||||
self._radio.append((value, btn))
|
||||
layout.addWidget(btn)
|
||||
|
||||
self._radio[0][1].setChecked(True)
|
||||
layout.addStretch()
|
||||
|
||||
def setup_check_boxs(self):
|
||||
self._check = []
|
||||
layout = self.find(QVBoxLayout, "verticalLayout_y")
|
||||
|
||||
for value in self._available_values_y:
|
||||
btn = QCheckBox(
|
||||
self._available_values_y[value],
|
||||
parent=self
|
||||
)
|
||||
self._check.append((value, btn))
|
||||
layout.addWidget(btn)
|
||||
|
||||
self._check[0][1].setChecked(True)
|
||||
layout.addStretch()
|
||||
|
||||
def accept(self):
|
||||
x = next(
|
||||
filter(
|
||||
lambda r: r[1].isChecked(),
|
||||
self._radio
|
||||
)
|
||||
)[0]
|
||||
|
||||
y = list(
|
||||
map(
|
||||
lambda b: b[0],
|
||||
filter(
|
||||
lambda b: b[1].isChecked(),
|
||||
self._check
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
self.value = x, y
|
||||
super().accept()
|
||||
|
|
@ -0,0 +1,348 @@
|
|||
# Plot.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from functools import reduce
|
||||
from datetime import datetime
|
||||
|
||||
from tools import timer
|
||||
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||
|
||||
from View.Results.CustomPlot.Translate import CustomPlotTranslate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
unit = {
|
||||
"elevation": "0-meter",
|
||||
"water_elevation": "0-meter",
|
||||
"discharge": "1-m3s",
|
||||
}
|
||||
|
||||
|
||||
class CustomPlot(PamhyrPlot):
|
||||
def __init__(self, x, y, reach, profile, timestamp,
|
||||
data=None, canvas=None, trad=None,
|
||||
toolbar=None, parent=None):
|
||||
super(CustomPlot, self).__init__(
|
||||
canvas=canvas,
|
||||
trad=CustomPlotTranslate(),
|
||||
data=data,
|
||||
toolbar=toolbar,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self._x = x
|
||||
self._y = y
|
||||
self._reach = reach
|
||||
self._profile = profile
|
||||
self._timestamp = timestamp
|
||||
|
||||
logger.debug(
|
||||
"Create custom plot for: " +
|
||||
f"{x} -> {','.join(y)}: " +
|
||||
f"reach={reach}, profile={profile}, " +
|
||||
f"timestamp={timestamp}"
|
||||
)
|
||||
|
||||
self._y_axes = sorted(
|
||||
set(
|
||||
map(
|
||||
lambda y: unit[y],
|
||||
self._y
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
self._axes = {}
|
||||
|
||||
def _draw_kp(self):
|
||||
results = self.data
|
||||
reach = results.river.reach(self._reach)
|
||||
kp = reach.geometry.get_kp()
|
||||
z_min = reach.geometry.get_z_min()
|
||||
|
||||
self.canvas.axes.set_xlim(
|
||||
left=min(kp), right=max(kp)
|
||||
)
|
||||
|
||||
meter_axes = self.canvas.axes
|
||||
m3S_axes = self.canvas.axes
|
||||
if "0-meter" in self._y_axes and "1-m3s" in self._y_axes:
|
||||
m3s_axes = self._axes["1-m3s"]
|
||||
|
||||
|
||||
lines = {}
|
||||
if "elevation" in self._y:
|
||||
meter_axes.set_ylim(
|
||||
bottom=min(0, min(z_min)),
|
||||
top=max(z_min) + 1
|
||||
)
|
||||
|
||||
line = meter_axes.plot(
|
||||
kp, z_min,
|
||||
color='grey', lw=1.,
|
||||
)
|
||||
lines["elevation"] = line
|
||||
|
||||
if "water_elevation" in self._y:
|
||||
# Water elevation
|
||||
water_z = list(
|
||||
map(
|
||||
lambda p: p.get_ts_key(self._timestamp, "Z"),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
meter_axes.set_ylim(
|
||||
bottom=min(0, min(z_min)),
|
||||
top=max(water_z) + 1
|
||||
)
|
||||
|
||||
line = meter_axes.plot(
|
||||
kp, water_z, lw=1.,
|
||||
color='blue',
|
||||
)
|
||||
lines["water_elevation"] = line
|
||||
|
||||
if "elevation" in self._y:
|
||||
meter_axes.fill_between(
|
||||
kp, z_min, water_z,
|
||||
color='blue', alpha=0.5, interpolate=True
|
||||
)
|
||||
|
||||
if "discharge" in self._y:
|
||||
q = list(
|
||||
map(
|
||||
lambda p: p.get_ts_key(self._timestamp, "Q"),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
m3s_axes.set_ylim(
|
||||
bottom=min(0, min(q)),
|
||||
top=max(q) + 1
|
||||
)
|
||||
|
||||
line = m3s_axes.plot(
|
||||
kp, q, lw=1.,
|
||||
color='r',
|
||||
)
|
||||
lines["discharge"] = line
|
||||
|
||||
# Legend
|
||||
lns = reduce(
|
||||
lambda acc, l: acc + l,
|
||||
map(lambda l: lines[l], lines),
|
||||
[]
|
||||
)
|
||||
labs = list(map(lambda l: self._trad[l], lines))
|
||||
self.canvas.axes.legend(lns, labs, loc="lower left")
|
||||
|
||||
def _customize_x_axes_time(self, ts, mode="time"):
|
||||
# Custom time display
|
||||
nb = len(ts)
|
||||
mod = int(nb / 5)
|
||||
mod = mod if mod > 0 else nb
|
||||
|
||||
fx = list(
|
||||
map(
|
||||
lambda x: x[1],
|
||||
filter(
|
||||
lambda x: x[0] % mod == 0,
|
||||
enumerate(ts)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if mode == "time":
|
||||
t0 = datetime.fromtimestamp(0)
|
||||
xt = list(
|
||||
map(
|
||||
lambda v: (
|
||||
str(
|
||||
datetime.fromtimestamp(v) - t0
|
||||
).split(",")[0]
|
||||
.replace("days", self._trad["days"])
|
||||
.replace("day", self._trad["day"])
|
||||
),
|
||||
fx
|
||||
)
|
||||
)
|
||||
else:
|
||||
xt = list(
|
||||
map(
|
||||
lambda v: str(datetime.fromtimestamp(v).date()),
|
||||
fx
|
||||
)
|
||||
)
|
||||
|
||||
self.canvas.axes.set_xticks(ticks=fx, labels=xt, rotation=45)
|
||||
|
||||
def _draw_time(self):
|
||||
results = self.data
|
||||
reach = results.river.reach(self._reach)
|
||||
profile = reach.profile(self._profile)
|
||||
|
||||
meter_axes = self.canvas.axes
|
||||
m3S_axes = self.canvas.axes
|
||||
if "0-meter" in self._y_axes and "1-m3s" in self._y_axes:
|
||||
m3s_axes = self._axes["1-m3s"]
|
||||
|
||||
ts = list(results.get("timestamps"))
|
||||
ts.sort()
|
||||
|
||||
self.canvas.axes.set_xlim(
|
||||
left=min(ts), right=max(ts)
|
||||
)
|
||||
|
||||
x = ts
|
||||
lines = {}
|
||||
if "elevation" in self._y:
|
||||
# Z min is constant in time
|
||||
z_min = profile.geometry.z_min()
|
||||
ts_z_min = list(
|
||||
map(
|
||||
lambda ts: z_min,
|
||||
ts
|
||||
)
|
||||
)
|
||||
|
||||
line = meter_axes.plot(
|
||||
ts, ts_z_min,
|
||||
color='grey', lw=1.
|
||||
)
|
||||
lines["elevation"] = line
|
||||
|
||||
if "water_elevation" in self._y:
|
||||
# Water elevation
|
||||
z = profile.get_key("Z")
|
||||
|
||||
meter_axes.set_ylim(
|
||||
bottom=min(0, min(z)),
|
||||
top=max(z) + 1
|
||||
)
|
||||
|
||||
line = meter_axes.plot(
|
||||
ts, z, lw=1.,
|
||||
color='b',
|
||||
)
|
||||
lines["water_elevation"] = line
|
||||
|
||||
if "elevation" in self._y:
|
||||
z_min = profile.geometry.z_min()
|
||||
ts_z_min = list(
|
||||
map(
|
||||
lambda ts: z_min,
|
||||
ts
|
||||
)
|
||||
)
|
||||
|
||||
meter_axes.fill_between(
|
||||
ts, ts_z_min, z,
|
||||
color='blue', alpha=0.5, interpolate=True
|
||||
)
|
||||
|
||||
if "discharge" in self._y:
|
||||
q = profile.get_key("Q")
|
||||
|
||||
m3s_axes.set_ylim(
|
||||
bottom=min(0, min(q)),
|
||||
top=max(q) + 1
|
||||
)
|
||||
|
||||
line = m3s_axes.plot(
|
||||
ts, q, lw=1.,
|
||||
color='r',
|
||||
)
|
||||
lines["discharge"] = line
|
||||
|
||||
|
||||
self._customize_x_axes_time(ts)
|
||||
|
||||
# Legend
|
||||
lns = reduce(
|
||||
lambda acc, l: acc + l,
|
||||
map(lambda l: lines[l], lines),
|
||||
[]
|
||||
)
|
||||
labs = list(map(lambda l: self._trad[l], lines))
|
||||
self.canvas.axes.legend(lns, labs, loc="lower left")
|
||||
|
||||
@timer
|
||||
def draw(self):
|
||||
self.canvas.axes.cla()
|
||||
self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
|
||||
if self.data is None:
|
||||
return
|
||||
|
||||
self.canvas.axes.set_xlabel(
|
||||
self._trad[self._x],
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
self.canvas.axes.set_ylabel(
|
||||
self._trad[self._y_axes[0]],
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
for axes in self._y_axes[1:]:
|
||||
if axes in self._axes:
|
||||
continue
|
||||
|
||||
ax_new = self.canvas.axes.twinx()
|
||||
ax_new.set_ylabel(
|
||||
self._trad[axes],
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self._axes[axes] = ax_new
|
||||
|
||||
if self._x == "kp":
|
||||
self._draw_kp()
|
||||
elif self._x == "time":
|
||||
self._draw_time()
|
||||
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.update()
|
||||
|
||||
@timer
|
||||
def update(self):
|
||||
if not self._init:
|
||||
self.draw()
|
||||
return
|
||||
|
||||
def set_reach(self, reach_id):
|
||||
self._reach = reach_id
|
||||
self._profile = 0
|
||||
|
||||
self.update()
|
||||
|
||||
def set_profile(self, profile_id):
|
||||
self._profile = profile_id
|
||||
|
||||
if self._x != "kp":
|
||||
self.update()
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self._timestamp = timestamp
|
||||
|
||||
if self._x != "time":
|
||||
self.update()
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# Translate.py -- Pamhyr
|
||||
# Copyright (C) 2023 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from PyQt5.QtCore import QCoreApplication
|
||||
|
||||
from View.Results.translate import ResultsTranslate
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class CustomPlotTranslate(ResultsTranslate):
|
||||
def __init__(self):
|
||||
super(CustomPlotTranslate, self).__init__()
|
||||
|
||||
# Value type
|
||||
|
||||
self._dict['time'] = _translate(
|
||||
"CustomPlot", "Time (sec)"
|
||||
)
|
||||
self._dict['kp'] = _translate(
|
||||
"CustomPlot", "Kp (m)"
|
||||
)
|
||||
self._dict['elevation'] = _translate(
|
||||
"CustomPlot", "Elevation (m)"
|
||||
)
|
||||
self._dict['water_elevation'] = _translate(
|
||||
"CustomPlot", "Water elevation (m)"
|
||||
)
|
||||
self._dict['discharge'] = _translate(
|
||||
"CustomPlot", "Discharge (m³/s)"
|
||||
)
|
||||
|
||||
# Unit corresponding long name (plot axes display)
|
||||
|
||||
self._dict['0-meter'] = _translate(
|
||||
"CustomPlot", "Elevation (m)"
|
||||
)
|
||||
self._dict['1-m3s'] = _translate(
|
||||
"CustomPlot", "Discharge (m³/s)"
|
||||
)
|
||||
|
||||
# SubDict
|
||||
|
||||
self._sub_dict["values_x"] = {
|
||||
"kp": self._dict["kp"],
|
||||
"time": self._dict["time"],
|
||||
}
|
||||
self._sub_dict["values_y"] = {
|
||||
"elevation": self._dict["elevation"],
|
||||
"water_elevation": self._dict["water_elevation"],
|
||||
"discharge": self._dict["discharge"],
|
||||
}
|
||||
|
|
@ -82,11 +82,11 @@ class PlotH(PamhyrPlot):
|
|||
# Axes
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("Results", "Time (s)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("Results", "Discharge (m³/s)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
ts = list(self.results.get("timestamps"))
|
||||
|
|
|
|||
|
|
@ -132,11 +132,11 @@ class PlotSedProfile(PamhyrPlot):
|
|||
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "X (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Height (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
x = profile.geometry.get_station()
|
||||
|
|
|
|||
|
|
@ -213,11 +213,11 @@ class PlotSedReach(PamhyrPlot):
|
|||
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "Kp (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Height (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
kp = reach.geometry.get_kp()
|
||||
|
|
|
|||
|
|
@ -83,11 +83,11 @@ class PlotXY(PamhyrPlot):
|
|||
# Axes
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("Results", "X (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("Results", "Y (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.axis("equal")
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ from PyQt5.QtWidgets import (
|
|||
QFileDialog, QTableView, QAbstractItemView,
|
||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||
QSlider, QLabel,
|
||||
QSlider, QLabel, QWidget, QGridLayout,
|
||||
)
|
||||
|
||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||
|
|
@ -51,6 +51,11 @@ from View.Results.PlotH import PlotH
|
|||
from View.Results.PlotSedReach import PlotSedReach
|
||||
from View.Results.PlotSedProfile import PlotSedProfile
|
||||
|
||||
from View.Results.CustomPlot.Plot import CustomPlot
|
||||
from View.Results.CustomPlot.CustomPlotValuesSelectionDialog import (
|
||||
CustomPlotValuesSelectionDialog,
|
||||
)
|
||||
|
||||
from View.Results.Table import TableModel
|
||||
from View.Results.translate import ResultsTranslate
|
||||
from View.Stricklers.Window import StricklersWindow
|
||||
|
|
@ -86,6 +91,8 @@ class ResultsWindow(PamhyrWindow):
|
|||
parent=parent
|
||||
)
|
||||
|
||||
self._additional_plot = {}
|
||||
|
||||
self.setup_table()
|
||||
self.setup_plot()
|
||||
self.setup_slider()
|
||||
|
|
@ -274,6 +281,7 @@ class ResultsWindow(PamhyrWindow):
|
|||
# Action
|
||||
actions = {
|
||||
"action_reload": self._reload,
|
||||
"action_add": self._add_custom_plot
|
||||
}
|
||||
|
||||
for action in actions:
|
||||
|
|
@ -281,6 +289,7 @@ class ResultsWindow(PamhyrWindow):
|
|||
actions[action]
|
||||
)
|
||||
|
||||
# Table and Plot
|
||||
fun = {
|
||||
"reach": self._set_current_reach,
|
||||
"profile": self._set_current_profile,
|
||||
|
|
@ -336,6 +345,9 @@ class ResultsWindow(PamhyrWindow):
|
|||
self.plot_sed_reach.set_reach(reach_id)
|
||||
self.plot_sed_profile.set_reach(reach_id)
|
||||
|
||||
for plot in self._additional_plot:
|
||||
self._additional_plot[plot].set_reach(reach_id)
|
||||
|
||||
self.update_table_selection_reach(reach_id)
|
||||
self.update_table_selection_profile(0)
|
||||
|
||||
|
|
@ -349,7 +361,11 @@ class ResultsWindow(PamhyrWindow):
|
|||
self.plot_sed_reach.set_profile(profile_id)
|
||||
self.plot_sed_profile.set_profile(profile_id)
|
||||
|
||||
for plot in self._additional_plot:
|
||||
self._additional_plot[plot].set_profile(profile_id)
|
||||
|
||||
self.update_table_selection_profile(profile_id)
|
||||
|
||||
if timestamp is not None:
|
||||
self.plot_xy.set_timestamp(timestamp)
|
||||
self.plot_ac.set_timestamp(timestamp)
|
||||
|
|
@ -360,17 +376,32 @@ class ResultsWindow(PamhyrWindow):
|
|||
self.plot_sed_reach.set_timestamp(timestamp)
|
||||
self.plot_sed_profile.set_timestamp(timestamp)
|
||||
|
||||
self.plot_xy.draw()
|
||||
self.plot_ac.draw()
|
||||
self.plot_kpc.draw()
|
||||
self.plot_h.draw()
|
||||
|
||||
if self._study.river.has_sediment():
|
||||
self.plot_sed_reach.draw()
|
||||
self.plot_sed_profile.draw()
|
||||
for plot in self._additional_plot:
|
||||
self._additional_plot[plot].set_timestamp(timestamp)
|
||||
|
||||
self.update_statusbar()
|
||||
|
||||
def _get_current_reach(self):
|
||||
table = self.find(QTableView, f"tableView_reach")
|
||||
indexes = table.selectedIndexes()
|
||||
if len(indexes) == 0:
|
||||
return 0
|
||||
|
||||
return indexes[0].row()
|
||||
|
||||
def _get_current_profile(self):
|
||||
table = self.find(QTableView, f"tableView_profile")
|
||||
indexes = table.selectedIndexes()
|
||||
if len(indexes) == 0:
|
||||
return 0
|
||||
|
||||
return indexes[0].row()
|
||||
|
||||
def _get_current_timestamp(self):
|
||||
return self._timestamps[
|
||||
self._slider_time.value()
|
||||
]
|
||||
|
||||
def _set_current_reach(self):
|
||||
table = self.find(QTableView, f"tableView_reach")
|
||||
indexes = table.selectedIndexes()
|
||||
|
|
@ -430,6 +461,56 @@ class ResultsWindow(PamhyrWindow):
|
|||
self._reload_plots()
|
||||
self._reload_slider()
|
||||
|
||||
def _add_custom_plot(self):
|
||||
dlg = CustomPlotValuesSelectionDialog(parent=self)
|
||||
if dlg.exec():
|
||||
x, y = dlg.value
|
||||
self.create_new_tab_custom_plot(x, y)
|
||||
|
||||
def create_new_tab_custom_plot(self, x: str, y: list):
|
||||
name = f"{x}: {','.join(y)}"
|
||||
wname = f"tab_custom_{x}_{y}"
|
||||
|
||||
tab_widget = self.find(QTabWidget, f"tabWidget")
|
||||
|
||||
# This plot already exists
|
||||
if name in self._additional_plot:
|
||||
tab_widget.setCurrentWidget(
|
||||
tab_widget.findChild(QWidget, wname)
|
||||
)
|
||||
return
|
||||
|
||||
widget = QWidget()
|
||||
grid = QGridLayout()
|
||||
|
||||
widget.setObjectName(wname)
|
||||
|
||||
canvas = MplCanvas(width=5, height=4, dpi=100)
|
||||
canvas.setObjectName(f"canvas_{x}_{y}")
|
||||
toolbar = PamhyrPlotToolbar(
|
||||
canvas, self
|
||||
)
|
||||
|
||||
plot = CustomPlot(
|
||||
x, y,
|
||||
self._get_current_reach(),
|
||||
self._get_current_profile(),
|
||||
self._get_current_timestamp(),
|
||||
data=self._results,
|
||||
canvas=canvas,
|
||||
toolbar=toolbar,
|
||||
parent=self,
|
||||
)
|
||||
plot.draw()
|
||||
|
||||
# Add plot to additional plot
|
||||
self._additional_plot[name] = plot
|
||||
|
||||
grid.addWidget(toolbar, 0, 0)
|
||||
grid.addWidget(canvas, 1, 0)
|
||||
widget.setLayout(grid)
|
||||
tab_widget.addTab(widget, name)
|
||||
|
||||
def _copy(self):
|
||||
logger.info("TODO: copy")
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,13 @@ class ResultsTranslate(PamhyrTranslate):
|
|||
def __init__(self):
|
||||
super(ResultsTranslate, self).__init__()
|
||||
|
||||
self._dict['day'] = _translate(
|
||||
"Results", "day"
|
||||
)
|
||||
self._dict['days'] = _translate(
|
||||
"Results", "days"
|
||||
)
|
||||
|
||||
self._sub_dict["table_headers_reach"] = {
|
||||
"name": _translate("Results", "Reach name"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class Plot(PamhyrPlot):
|
|||
self.canvas.axes.axes.get_xaxis().set_visible(False)
|
||||
self.canvas.axes.set_ylabel(
|
||||
self._trad["height"],
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
if self.data is None:
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ class Plot(PamhyrPlot):
|
|||
|
||||
self.canvas.axes.set_xlabel(
|
||||
self._trad["kp"],
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
self._trad["height"],
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
kp = self.data.get_kp()
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ class Plot(PamhyrPlot):
|
|||
|
||||
self.canvas.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "X (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
self.canvas.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Height (m)"),
|
||||
color='green', fontsize=12
|
||||
color='green', fontsize=10
|
||||
)
|
||||
|
||||
x = self.data.get_station()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>414</width>
|
||||
<height>482</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_x">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>X axis:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_y">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Y axis:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
Loading…
Reference in New Issue