Pamhyr2/src/View/Tools/PamhyrPlot.py

250 lines
7.0 KiB
Python

# PamhyrPlot.py -- Pamhyr
# Copyright (C) 2023-2024 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 matplotlib.colors as mplcolors
from matplotlib.widgets import RectangleSelector
from matplotlib import ticker
from tools import timestamp_to_old_pamhyr_date
from View.Tools.Plot.APlot import APlot
from View.Tools.Plot.PamhyrCanvas import MplCanvas
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
class PamhyrPlot(APlot):
color_axes = "black"
color_axes_grid = "grey"
color_axes_labels = "black"
color_plot = "red"
color_plot_highlight = "blue"
color_plot_previous = "black"
color_plot_current = "blue"
color_plot_next = "purple"
color_plot_river_bottom = "grey"
color_plot_river_water = "blue"
color_plot_river_water_zone = "skyblue"
colors = list(mplcolors.TABLEAU_COLORS)
linestyle = ['solid', 'dashed', 'dashdot', 'dotted']
plot_default_kargs = {
"lw": 1.,
"markersize": 3,
"marker": "+",
}
def __init__(self, data=None,
trad=None, # Translate object
canvas=None, # Use existing canvas
canvas_height=4, canvas_width=5,
canvas_dpi=100,
toolbar=None,
table=None,
parent=None):
if canvas is None:
canvas = MplCanvas(
height=canvas_height, width=canvas_width,
dpi=canvas_dpi
)
self._trad = trad
self._canvas = canvas
self._toolbar = toolbar
self._table = table
self._parent = parent
self._init_event()
self._init_default_value()
super(PamhyrPlot, self).__init__(data=data)
def _init_event(self):
connector = {
'pick_event': self.onpick,
'button_press_event': self.onclick,
}
for event in connector:
self.canvas.mpl_connect(
event, connector[event]
)
def _init_default_value(self):
self._label_x = "X"
self._label_y = "Y"
self._isometric_axis = True #: Use isometric view
self._auto_relim = True #: Auto relim axes at plot creation
self._autoscale = True #: Auto scale at plot creation
self._auto_relim_update = False #: Auto relim axes at plot update
self._autoscale_update = False #: Auto scale at plot creation
self._highlight_data = None #: Data identifier to highlight
self._highlight_data_update = False
self._current_data = None #: Current data identifier
self._current_data_update = False
self._rect_select = RectangleSelector(ax=self.canvas.axes,
onselect=self.rect_select_callback,
useblit=True,
button=[1, 3], # don't use middle button
minspanx=1.0,
minspany=1.0,
spancoords='pixels',
interactive=False)
@property
def canvas(self):
return self._canvas
@property
def toolbar(self):
return self._toolbar
@property
def table(self):
return self._table
@property
def label_x(self):
"""Plot X axes label"""
return self._label_x
@label_x.setter
def label_x(self, name):
self._label_x = name
@property
def label_y(self):
"""Plot Y axes label"""
return self._label_x
@label_y.setter
def label_y(self, name):
self._label_y = name
@property
def highlight(self):
return self._highlight_data
@highlight.setter
def highlight(self, data):
self._highlight_data = data
self._highlight_data_update = True
@property
def current(self):
return self._current_data
@current.setter
def current(self, data):
self._current_data = data
self._current_data_update = True
def init_axes(self):
self.canvas.axes.cla()
self.canvas.axes.grid(
color=self.color_axes_grid,
linestyle='--',
linewidth=0.5
)
self.init_axes_labels()
self.init_axes_axis()
def init_axes_labels(self):
self.canvas.axes.set_xlabel(
self._label_x,
color=self.color_axes_labels,
fontsize=10
)
self.canvas.axes.set_ylabel(
self._label_y,
color=self.color_axes_labels,
fontsize=10
)
def init_axes_axis(self):
if self._isometric_axis:
self.canvas.axes.axis("equal")
else:
self.canvas.axes.axis("tight")
def idle(self):
if self._auto_relim:
self.canvas.axes.relim()
if self._autoscale:
self.canvas.axes.autoscale_view(True, True, True)
self.canvas.axes.autoscale()
self.canvas.figure.tight_layout()
self.canvas.figure.canvas.draw_idle()
self.toolbar_update()
def update_idle(self):
if self._auto_relim_update:
self.canvas.axes.relim()
if self._autoscale_update:
self.canvas.axes.autoscale_view(True, True, True)
self.canvas.axes.autoscale()
self.canvas.figure.tight_layout()
self.canvas.figure.canvas.draw_idle()
self.toolbar_update()
def toolbar_update(self):
if self._toolbar is not None:
self._toolbar.update()
def set_ticks_time_formater(self):
self.canvas.axes.xaxis.set_major_formatter(
lambda x, pos: timestamp_to_old_pamhyr_date(int(x))
)
self.canvas.axes.tick_params(
labelsize=9,
labelrotation=45
)
def enable_legend(self):
self.canvas.axes.legend(
fancybox=True,
shadow=True,
fontsize=8
)
def onpick(self, event):
return
def onclick(self, event):
return
def rect_select_callback(self, eclick, erelease):
'eclick and erelease are the press and release events'
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
print("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2))
return